add_upper_div_constraint: return return modified result
[isl.git] / isl_map.c
blob1718ce358f6a9200c8052c6ca27ca816bb2dba0c
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/id.h>
27 #include <isl/constraint.h>
28 #include "isl_space_private.h"
29 #include "isl_equalities.h"
30 #include <isl_lp_private.h>
31 #include <isl_seq.h>
32 #include <isl/set.h>
33 #include <isl/map.h>
34 #include <isl_reordering.h>
35 #include "isl_sample.h"
36 #include <isl_sort.h>
37 #include "isl_tab.h"
38 #include <isl/vec.h>
39 #include <isl_mat_private.h>
40 #include <isl_vec_private.h>
41 #include <isl_dim_map.h>
42 #include <isl_local_space_private.h>
43 #include <isl_aff_private.h>
44 #include <isl_options_private.h>
45 #include <isl_morph.h>
46 #include <isl_val_private.h>
48 #include <bset_to_bmap.c>
49 #include <bset_from_bmap.c>
50 #include <set_to_map.c>
51 #include <set_from_map.c>
53 /* Treat "bset" as a basic map.
54 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
55 * this function performs a redundant cast.
57 static __isl_keep const isl_basic_map *const_bset_to_bmap(
58 __isl_keep const isl_basic_set *bset)
60 return (const isl_basic_map *) bset;
63 static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
65 switch (type) {
66 case isl_dim_param: return dim->nparam;
67 case isl_dim_in: return dim->n_in;
68 case isl_dim_out: return dim->n_out;
69 case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
70 default: return 0;
74 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
76 switch (type) {
77 case isl_dim_param: return 1;
78 case isl_dim_in: return 1 + dim->nparam;
79 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
80 default: return 0;
84 unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
85 enum isl_dim_type type)
87 if (!bmap)
88 return 0;
89 switch (type) {
90 case isl_dim_cst: return 1;
91 case isl_dim_param:
92 case isl_dim_in:
93 case isl_dim_out: return isl_space_dim(bmap->dim, type);
94 case isl_dim_div: return bmap->n_div;
95 case isl_dim_all: return isl_basic_map_total_dim(bmap);
96 default: return 0;
100 /* Return the space of "map".
102 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
104 return map ? map->dim : NULL;
107 /* Return the space of "set".
109 __isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
111 return isl_map_peek_space(set_to_map(set));
114 unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
116 return map ? n(map->dim, type) : 0;
119 unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
121 return set ? n(set->dim, type) : 0;
124 /* Return the position of the variables of the given type
125 * within the sequence of variables of "bmap".
127 int isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
128 enum isl_dim_type type)
130 isl_space *space;
132 space = isl_basic_map_peek_space(bmap);
133 if (!space)
134 return -1;
136 switch (type) {
137 case isl_dim_param:
138 case isl_dim_in:
139 case isl_dim_out: return isl_space_offset(space, type);
140 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
141 case isl_dim_cst:
142 default:
143 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
144 "invalid dimension type", return -1);
148 /* Return the position of the coefficients of the variables of the given type
149 * within the sequence of coefficients of "bmap".
151 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
152 enum isl_dim_type type)
154 switch (type) {
155 case isl_dim_cst: return 0;
156 case isl_dim_param:
157 case isl_dim_in:
158 case isl_dim_out:
159 case isl_dim_div: return 1 + isl_basic_map_var_offset(bmap, type);
160 default: return 0;
164 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
165 enum isl_dim_type type)
167 return isl_basic_map_offset(bset, type);
170 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
172 return pos(map->dim, type);
175 unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
176 enum isl_dim_type type)
178 return isl_basic_map_dim(bset, type);
181 unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
183 return isl_basic_set_dim(bset, isl_dim_set);
186 unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
188 return isl_basic_set_dim(bset, isl_dim_param);
191 unsigned isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
193 return isl_basic_map_total_dim(const_bset_to_bmap(bset));
196 unsigned isl_set_n_dim(__isl_keep isl_set *set)
198 return isl_set_dim(set, isl_dim_set);
201 unsigned isl_set_n_param(__isl_keep isl_set *set)
203 return isl_set_dim(set, isl_dim_param);
206 unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap)
208 return bmap ? bmap->dim->n_in : 0;
211 unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap)
213 return bmap ? bmap->dim->n_out : 0;
216 unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap)
218 return bmap ? bmap->dim->nparam : 0;
221 unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap)
223 return bmap ? bmap->n_div : 0;
226 unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
228 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
231 unsigned isl_map_n_in(__isl_keep const isl_map *map)
233 return map ? map->dim->n_in : 0;
236 unsigned isl_map_n_out(__isl_keep const isl_map *map)
238 return map ? map->dim->n_out : 0;
241 unsigned isl_map_n_param(__isl_keep const isl_map *map)
243 return map ? map->dim->nparam : 0;
246 /* Return the number of equality constraints in the description of "bmap".
247 * Return -1 on error.
249 int isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
251 if (!bmap)
252 return -1;
253 return bmap->n_eq;
256 /* Return the number of equality constraints in the description of "bset".
257 * Return -1 on error.
259 int isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
261 return isl_basic_map_n_equality(bset_to_bmap(bset));
264 /* Return the number of inequality constraints in the description of "bmap".
265 * Return -1 on error.
267 int isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
269 if (!bmap)
270 return -1;
271 return bmap->n_ineq;
274 /* Return the number of inequality constraints in the description of "bset".
275 * Return -1 on error.
277 int isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
279 return isl_basic_map_n_inequality(bset_to_bmap(bset));
282 /* Do "bmap1" and "bmap2" have the same parameters?
284 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
285 __isl_keep isl_basic_map *bmap2)
287 isl_space *space1, *space2;
289 space1 = isl_basic_map_peek_space(bmap1);
290 space2 = isl_basic_map_peek_space(bmap2);
291 return isl_space_has_equal_params(space1, space2);
294 /* Do "map1" and "map2" have the same parameters?
296 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
297 __isl_keep isl_map *map2)
299 isl_space *space1, *space2;
301 space1 = isl_map_peek_space(map1);
302 space2 = isl_map_peek_space(map2);
303 return isl_space_has_equal_params(space1, space2);
306 /* Do "map" and "set" have the same parameters?
308 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
309 __isl_keep isl_set *set)
311 return isl_map_has_equal_params(map, set_to_map(set));
314 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
315 __isl_keep isl_set *set)
317 isl_bool m;
318 if (!map || !set)
319 return isl_bool_error;
320 m = isl_map_has_equal_params(map, set_to_map(set));
321 if (m < 0 || !m)
322 return m;
323 return isl_space_tuple_is_equal(map->dim, isl_dim_in,
324 set->dim, isl_dim_set);
327 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
328 __isl_keep isl_basic_set *bset)
330 isl_bool m;
331 if (!bmap || !bset)
332 return isl_bool_error;
333 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
334 if (m < 0 || !m)
335 return m;
336 return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
337 bset->dim, isl_dim_set);
340 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
341 __isl_keep isl_set *set)
343 isl_bool m;
344 if (!map || !set)
345 return isl_bool_error;
346 m = isl_map_has_equal_params(map, set_to_map(set));
347 if (m < 0 || !m)
348 return m;
349 return isl_space_tuple_is_equal(map->dim, isl_dim_out,
350 set->dim, isl_dim_set);
353 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
354 __isl_keep isl_basic_set *bset)
356 isl_bool m;
357 if (!bmap || !bset)
358 return isl_bool_error;
359 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
360 if (m < 0 || !m)
361 return m;
362 return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
363 bset->dim, isl_dim_set);
366 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
368 return bmap ? bmap->ctx : NULL;
371 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
373 return bset ? bset->ctx : NULL;
376 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
378 return map ? map->ctx : NULL;
381 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
383 return set ? set->ctx : NULL;
386 /* Return the space of "bmap".
388 __isl_keep isl_space *isl_basic_map_peek_space(
389 __isl_keep const isl_basic_map *bmap)
391 return bmap ? bmap->dim : NULL;
394 /* Return the space of "bset".
396 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
398 return isl_basic_map_peek_space(bset_to_bmap(bset));
401 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
403 return isl_space_copy(isl_basic_map_peek_space(bmap));
406 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
408 return isl_basic_map_get_space(bset_to_bmap(bset));
411 /* Extract the divs in "bmap" as a matrix.
413 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
415 int i;
416 isl_ctx *ctx;
417 isl_mat *div;
418 unsigned total;
419 unsigned cols;
421 if (!bmap)
422 return NULL;
424 ctx = isl_basic_map_get_ctx(bmap);
425 total = isl_space_dim(bmap->dim, isl_dim_all);
426 cols = 1 + 1 + total + bmap->n_div;
427 div = isl_mat_alloc(ctx, bmap->n_div, cols);
428 if (!div)
429 return NULL;
431 for (i = 0; i < bmap->n_div; ++i)
432 isl_seq_cpy(div->row[i], bmap->div[i], cols);
434 return div;
437 /* Extract the divs in "bset" as a matrix.
439 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
441 return isl_basic_map_get_divs(bset);
444 __isl_give isl_local_space *isl_basic_map_get_local_space(
445 __isl_keep isl_basic_map *bmap)
447 isl_mat *div;
449 if (!bmap)
450 return NULL;
452 div = isl_basic_map_get_divs(bmap);
453 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
456 __isl_give isl_local_space *isl_basic_set_get_local_space(
457 __isl_keep isl_basic_set *bset)
459 return isl_basic_map_get_local_space(bset);
462 /* For each known div d = floor(f/m), add the constraints
464 * f - m d >= 0
465 * -(f-(m-1)) + m d >= 0
467 * Do not finalize the result.
469 static __isl_give isl_basic_map *add_known_div_constraints(
470 __isl_take isl_basic_map *bmap)
472 int i;
473 unsigned n_div;
475 if (!bmap)
476 return NULL;
477 n_div = isl_basic_map_dim(bmap, isl_dim_div);
478 if (n_div == 0)
479 return bmap;
480 bmap = isl_basic_map_cow(bmap);
481 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
482 if (!bmap)
483 return NULL;
484 for (i = 0; i < n_div; ++i) {
485 if (isl_int_is_zero(bmap->div[i][0]))
486 continue;
487 bmap = isl_basic_map_add_div_constraints(bmap, i);
490 return bmap;
493 __isl_give isl_basic_map *isl_basic_map_from_local_space(
494 __isl_take isl_local_space *ls)
496 int i;
497 int n_div;
498 isl_basic_map *bmap;
500 if (!ls)
501 return NULL;
503 n_div = isl_local_space_dim(ls, isl_dim_div);
504 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
505 n_div, 0, 2 * n_div);
507 for (i = 0; i < n_div; ++i)
508 if (isl_basic_map_alloc_div(bmap) < 0)
509 goto error;
511 for (i = 0; i < n_div; ++i)
512 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
513 bmap = add_known_div_constraints(bmap);
515 isl_local_space_free(ls);
516 return bmap;
517 error:
518 isl_local_space_free(ls);
519 isl_basic_map_free(bmap);
520 return NULL;
523 __isl_give isl_basic_set *isl_basic_set_from_local_space(
524 __isl_take isl_local_space *ls)
526 return isl_basic_map_from_local_space(ls);
529 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
531 return isl_space_copy(isl_map_peek_space(map));
534 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
536 if (!set)
537 return NULL;
538 return isl_space_copy(set->dim);
541 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
542 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
544 bmap = isl_basic_map_cow(bmap);
545 if (!bmap)
546 return NULL;
547 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
548 if (!bmap->dim)
549 goto error;
550 bmap = isl_basic_map_finalize(bmap);
551 return bmap;
552 error:
553 isl_basic_map_free(bmap);
554 return NULL;
557 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
558 __isl_take isl_basic_set *bset, const char *s)
560 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
563 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
564 enum isl_dim_type type)
566 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
569 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
570 enum isl_dim_type type, const char *s)
572 int i;
574 map = isl_map_cow(map);
575 if (!map)
576 return NULL;
578 map->dim = isl_space_set_tuple_name(map->dim, type, s);
579 if (!map->dim)
580 goto error;
582 for (i = 0; i < map->n; ++i) {
583 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
584 if (!map->p[i])
585 goto error;
588 return map;
589 error:
590 isl_map_free(map);
591 return NULL;
594 /* Replace the identifier of the tuple of type "type" by "id".
596 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
597 __isl_take isl_basic_map *bmap,
598 enum isl_dim_type type, __isl_take isl_id *id)
600 bmap = isl_basic_map_cow(bmap);
601 if (!bmap)
602 goto error;
603 bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
604 if (!bmap->dim)
605 return isl_basic_map_free(bmap);
606 bmap = isl_basic_map_finalize(bmap);
607 return bmap;
608 error:
609 isl_id_free(id);
610 return NULL;
613 /* Replace the identifier of the tuple by "id".
615 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
616 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
618 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
621 /* Does the input or output tuple have a name?
623 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
625 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
628 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
629 enum isl_dim_type type)
631 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
634 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
635 const char *s)
637 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
638 isl_dim_set, s));
641 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
642 enum isl_dim_type type, __isl_take isl_id *id)
644 map = isl_map_cow(map);
645 if (!map)
646 goto error;
648 map->dim = isl_space_set_tuple_id(map->dim, type, id);
650 return isl_map_reset_space(map, isl_space_copy(map->dim));
651 error:
652 isl_id_free(id);
653 return NULL;
656 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
657 __isl_take isl_id *id)
659 return isl_map_set_tuple_id(set, isl_dim_set, id);
662 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
663 enum isl_dim_type type)
665 map = isl_map_cow(map);
666 if (!map)
667 return NULL;
669 map->dim = isl_space_reset_tuple_id(map->dim, type);
671 return isl_map_reset_space(map, isl_space_copy(map->dim));
674 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
676 return isl_map_reset_tuple_id(set, isl_dim_set);
679 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
681 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
684 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
685 enum isl_dim_type type)
687 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
690 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
692 return isl_map_has_tuple_id(set, isl_dim_set);
695 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
697 return isl_map_get_tuple_id(set, isl_dim_set);
700 /* Does the set tuple have a name?
702 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
704 if (!set)
705 return isl_bool_error;
706 return isl_space_has_tuple_name(set->dim, isl_dim_set);
710 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
712 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
715 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
717 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
720 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
721 enum isl_dim_type type, unsigned pos)
723 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
726 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
727 enum isl_dim_type type, unsigned pos)
729 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
732 /* Does the given dimension have a name?
734 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
735 enum isl_dim_type type, unsigned pos)
737 if (!map)
738 return isl_bool_error;
739 return isl_space_has_dim_name(map->dim, type, pos);
742 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
743 enum isl_dim_type type, unsigned pos)
745 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
748 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
749 enum isl_dim_type type, unsigned pos)
751 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
754 /* Does the given dimension have a name?
756 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
757 enum isl_dim_type type, unsigned pos)
759 if (!set)
760 return isl_bool_error;
761 return isl_space_has_dim_name(set->dim, type, pos);
764 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
765 __isl_take isl_basic_map *bmap,
766 enum isl_dim_type type, unsigned pos, const char *s)
768 bmap = isl_basic_map_cow(bmap);
769 if (!bmap)
770 return NULL;
771 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
772 if (!bmap->dim)
773 goto error;
774 return isl_basic_map_finalize(bmap);
775 error:
776 isl_basic_map_free(bmap);
777 return NULL;
780 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
781 enum isl_dim_type type, unsigned pos, const char *s)
783 int i;
785 map = isl_map_cow(map);
786 if (!map)
787 return NULL;
789 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
790 if (!map->dim)
791 goto error;
793 for (i = 0; i < map->n; ++i) {
794 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
795 if (!map->p[i])
796 goto error;
799 return map;
800 error:
801 isl_map_free(map);
802 return NULL;
805 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
806 __isl_take isl_basic_set *bset,
807 enum isl_dim_type type, unsigned pos, const char *s)
809 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
810 type, pos, s));
813 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
814 enum isl_dim_type type, unsigned pos, const char *s)
816 return set_from_map(isl_map_set_dim_name(set_to_map(set),
817 type, pos, s));
820 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
821 enum isl_dim_type type, unsigned pos)
823 if (!bmap)
824 return isl_bool_error;
825 return isl_space_has_dim_id(bmap->dim, type, pos);
828 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
829 enum isl_dim_type type, unsigned pos)
831 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
834 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
835 enum isl_dim_type type, unsigned pos)
837 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
840 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
841 enum isl_dim_type type, unsigned pos)
843 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
846 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
847 enum isl_dim_type type, unsigned pos)
849 return isl_map_has_dim_id(set, type, pos);
852 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
853 enum isl_dim_type type, unsigned pos)
855 return isl_map_get_dim_id(set, type, pos);
858 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
859 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
861 map = isl_map_cow(map);
862 if (!map)
863 goto error;
865 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
867 return isl_map_reset_space(map, isl_space_copy(map->dim));
868 error:
869 isl_id_free(id);
870 return NULL;
873 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
874 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
876 return isl_map_set_dim_id(set, type, pos, id);
879 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
880 __isl_keep isl_id *id)
882 if (!map)
883 return -1;
884 return isl_space_find_dim_by_id(map->dim, type, id);
887 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
888 __isl_keep isl_id *id)
890 return isl_map_find_dim_by_id(set, type, id);
893 /* Return the position of the dimension of the given type and name
894 * in "bmap".
895 * Return -1 if no such dimension can be found.
897 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
898 enum isl_dim_type type, const char *name)
900 if (!bmap)
901 return -1;
902 return isl_space_find_dim_by_name(bmap->dim, type, name);
905 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
906 const char *name)
908 if (!map)
909 return -1;
910 return isl_space_find_dim_by_name(map->dim, type, name);
913 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
914 const char *name)
916 return isl_map_find_dim_by_name(set, type, name);
919 /* Check whether equality i of bset is a pure stride constraint
920 * on a single dimension, i.e., of the form
922 * v = k e
924 * with k a constant and e an existentially quantified variable.
926 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
928 unsigned nparam;
929 unsigned d;
930 unsigned n_div;
931 int pos1;
932 int pos2;
934 if (!bset)
935 return isl_bool_error;
937 if (!isl_int_is_zero(bset->eq[i][0]))
938 return isl_bool_false;
940 nparam = isl_basic_set_dim(bset, isl_dim_param);
941 d = isl_basic_set_dim(bset, isl_dim_set);
942 n_div = isl_basic_set_dim(bset, isl_dim_div);
944 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
945 return isl_bool_false;
946 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
947 if (pos1 == -1)
948 return isl_bool_false;
949 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
950 d - pos1 - 1) != -1)
951 return isl_bool_false;
953 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
954 if (pos2 == -1)
955 return isl_bool_false;
956 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
957 n_div - pos2 - 1) != -1)
958 return isl_bool_false;
959 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
960 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
961 return isl_bool_false;
963 return isl_bool_true;
966 /* Reset the user pointer on all identifiers of parameters and tuples
967 * of the space of "map".
969 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
971 isl_space *space;
973 space = isl_map_get_space(map);
974 space = isl_space_reset_user(space);
975 map = isl_map_reset_space(map, space);
977 return map;
980 /* Reset the user pointer on all identifiers of parameters and tuples
981 * of the space of "set".
983 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
985 return isl_map_reset_user(set);
988 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
990 if (!bmap)
991 return isl_bool_error;
992 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
995 /* Has "map" been marked as a rational map?
996 * In particular, have all basic maps in "map" been marked this way?
997 * An empty map is not considered to be rational.
998 * Maps where only some of the basic maps are marked rational
999 * are not allowed.
1001 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
1003 int i;
1004 isl_bool rational;
1006 if (!map)
1007 return isl_bool_error;
1008 if (map->n == 0)
1009 return isl_bool_false;
1010 rational = isl_basic_map_is_rational(map->p[0]);
1011 if (rational < 0)
1012 return rational;
1013 for (i = 1; i < map->n; ++i) {
1014 isl_bool rational_i;
1016 rational_i = isl_basic_map_is_rational(map->p[i]);
1017 if (rational_i < 0)
1018 return rational_i;
1019 if (rational != rational_i)
1020 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1021 "mixed rational and integer basic maps "
1022 "not supported", return isl_bool_error);
1025 return rational;
1028 /* Has "set" been marked as a rational set?
1029 * In particular, have all basic set in "set" been marked this way?
1030 * An empty set is not considered to be rational.
1031 * Sets where only some of the basic sets are marked rational
1032 * are not allowed.
1034 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1036 return isl_map_is_rational(set);
1039 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1041 return isl_basic_map_is_rational(bset);
1044 /* Does "bmap" contain any rational points?
1046 * If "bmap" has an equality for each dimension, equating the dimension
1047 * to an integer constant, then it has no rational points, even if it
1048 * is marked as rational.
1050 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1052 isl_bool has_rational = isl_bool_true;
1053 unsigned total;
1055 if (!bmap)
1056 return isl_bool_error;
1057 if (isl_basic_map_plain_is_empty(bmap))
1058 return isl_bool_false;
1059 if (!isl_basic_map_is_rational(bmap))
1060 return isl_bool_false;
1061 bmap = isl_basic_map_copy(bmap);
1062 bmap = isl_basic_map_implicit_equalities(bmap);
1063 if (!bmap)
1064 return isl_bool_error;
1065 total = isl_basic_map_total_dim(bmap);
1066 if (bmap->n_eq == total) {
1067 int i, j;
1068 for (i = 0; i < bmap->n_eq; ++i) {
1069 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1070 if (j < 0)
1071 break;
1072 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1073 !isl_int_is_negone(bmap->eq[i][1 + j]))
1074 break;
1075 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1076 total - j - 1);
1077 if (j >= 0)
1078 break;
1080 if (i == bmap->n_eq)
1081 has_rational = isl_bool_false;
1083 isl_basic_map_free(bmap);
1085 return has_rational;
1088 /* Does "map" contain any rational points?
1090 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1092 int i;
1093 isl_bool has_rational;
1095 if (!map)
1096 return isl_bool_error;
1097 for (i = 0; i < map->n; ++i) {
1098 has_rational = isl_basic_map_has_rational(map->p[i]);
1099 if (has_rational < 0 || has_rational)
1100 return has_rational;
1102 return isl_bool_false;
1105 /* Does "set" contain any rational points?
1107 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1109 return isl_map_has_rational(set);
1112 /* Is this basic set a parameter domain?
1114 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1116 if (!bset)
1117 return isl_bool_error;
1118 return isl_space_is_params(bset->dim);
1121 /* Is this set a parameter domain?
1123 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1125 if (!set)
1126 return isl_bool_error;
1127 return isl_space_is_params(set->dim);
1130 /* Is this map actually a parameter domain?
1131 * Users should never call this function. Outside of isl,
1132 * a map can never be a parameter domain.
1134 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1136 if (!map)
1137 return isl_bool_error;
1138 return isl_space_is_params(map->dim);
1141 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1142 __isl_take isl_basic_map *bmap, unsigned extra,
1143 unsigned n_eq, unsigned n_ineq)
1145 int i;
1146 size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
1148 bmap->ctx = ctx;
1149 isl_ctx_ref(ctx);
1151 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1152 if (isl_blk_is_error(bmap->block))
1153 goto error;
1155 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1156 if ((n_ineq + n_eq) && !bmap->ineq)
1157 goto error;
1159 if (extra == 0) {
1160 bmap->block2 = isl_blk_empty();
1161 bmap->div = NULL;
1162 } else {
1163 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1164 if (isl_blk_is_error(bmap->block2))
1165 goto error;
1167 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1168 if (!bmap->div)
1169 goto error;
1172 for (i = 0; i < n_ineq + n_eq; ++i)
1173 bmap->ineq[i] = bmap->block.data + i * row_size;
1175 for (i = 0; i < extra; ++i)
1176 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1178 bmap->ref = 1;
1179 bmap->flags = 0;
1180 bmap->c_size = n_eq + n_ineq;
1181 bmap->eq = bmap->ineq + n_ineq;
1182 bmap->extra = extra;
1183 bmap->n_eq = 0;
1184 bmap->n_ineq = 0;
1185 bmap->n_div = 0;
1186 bmap->sample = NULL;
1188 return bmap;
1189 error:
1190 isl_basic_map_free(bmap);
1191 return NULL;
1194 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1195 unsigned nparam, unsigned dim, unsigned extra,
1196 unsigned n_eq, unsigned n_ineq)
1198 struct isl_basic_map *bmap;
1199 isl_space *space;
1201 space = isl_space_set_alloc(ctx, nparam, dim);
1202 if (!space)
1203 return NULL;
1205 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1206 return bset_from_bmap(bmap);
1209 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1210 unsigned extra, unsigned n_eq, unsigned n_ineq)
1212 struct isl_basic_map *bmap;
1213 if (!dim)
1214 return NULL;
1215 isl_assert(dim->ctx, dim->n_in == 0, goto error);
1216 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1217 return bset_from_bmap(bmap);
1218 error:
1219 isl_space_free(dim);
1220 return NULL;
1223 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1224 unsigned extra, unsigned n_eq, unsigned n_ineq)
1226 struct isl_basic_map *bmap;
1228 if (!space)
1229 return NULL;
1230 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1231 if (!bmap)
1232 goto error;
1233 bmap->dim = space;
1235 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1236 error:
1237 isl_space_free(space);
1238 return NULL;
1241 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1242 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1243 unsigned n_eq, unsigned n_ineq)
1245 struct isl_basic_map *bmap;
1246 isl_space *dim;
1248 dim = isl_space_alloc(ctx, nparam, in, out);
1249 if (!dim)
1250 return NULL;
1252 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1253 return bmap;
1256 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1257 __isl_keep isl_basic_map *src)
1259 int i;
1260 unsigned total = isl_basic_map_total_dim(src);
1262 if (!dst)
1263 return NULL;
1265 for (i = 0; i < src->n_eq; ++i) {
1266 int j = isl_basic_map_alloc_equality(dst);
1267 if (j < 0)
1268 return isl_basic_map_free(dst);
1269 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1272 for (i = 0; i < src->n_ineq; ++i) {
1273 int j = isl_basic_map_alloc_inequality(dst);
1274 if (j < 0)
1275 return isl_basic_map_free(dst);
1276 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1279 for (i = 0; i < src->n_div; ++i) {
1280 int j = isl_basic_map_alloc_div(dst);
1281 if (j < 0)
1282 return isl_basic_map_free(dst);
1283 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1285 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1286 return dst;
1289 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1291 struct isl_basic_map *dup;
1293 if (!bmap)
1294 return NULL;
1295 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1296 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1297 dup = dup_constraints(dup, bmap);
1298 if (!dup)
1299 return NULL;
1300 dup->flags = bmap->flags;
1301 dup->sample = isl_vec_copy(bmap->sample);
1302 return dup;
1305 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1307 struct isl_basic_map *dup;
1309 dup = isl_basic_map_dup(bset_to_bmap(bset));
1310 return bset_from_bmap(dup);
1313 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1315 if (!bset)
1316 return NULL;
1318 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1319 bset->ref++;
1320 return bset;
1322 return isl_basic_set_dup(bset);
1325 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1327 if (!set)
1328 return NULL;
1330 set->ref++;
1331 return set;
1334 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1336 if (!bmap)
1337 return NULL;
1339 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1340 bmap->ref++;
1341 return bmap;
1343 bmap = isl_basic_map_dup(bmap);
1344 if (bmap)
1345 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1346 return bmap;
1349 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1351 if (!map)
1352 return NULL;
1354 map->ref++;
1355 return map;
1358 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1360 if (!bmap)
1361 return NULL;
1363 if (--bmap->ref > 0)
1364 return NULL;
1366 isl_ctx_deref(bmap->ctx);
1367 free(bmap->div);
1368 isl_blk_free(bmap->ctx, bmap->block2);
1369 free(bmap->ineq);
1370 isl_blk_free(bmap->ctx, bmap->block);
1371 isl_vec_free(bmap->sample);
1372 isl_space_free(bmap->dim);
1373 free(bmap);
1375 return NULL;
1378 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1380 return isl_basic_map_free(bset_to_bmap(bset));
1383 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1385 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1388 /* Check that "bset" does not involve any parameters.
1390 isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1392 if (!bset)
1393 return isl_stat_error;
1394 if (isl_basic_set_dim(bset, isl_dim_param) != 0)
1395 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1396 "basic set should not have any parameters",
1397 return isl_stat_error);
1398 return isl_stat_ok;
1401 /* Check that "bset" does not involve any local variables.
1403 isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1405 if (!bset)
1406 return isl_stat_error;
1407 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
1408 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1409 "basic set should not have any local variables",
1410 return isl_stat_error);
1411 return isl_stat_ok;
1414 /* Check that "map" has only named parameters, reporting an error
1415 * if it does not.
1417 isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1419 return isl_space_check_named_params(isl_map_peek_space(map));
1422 /* Check that "bmap" has only named parameters, reporting an error
1423 * if it does not.
1425 static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
1427 return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
1430 /* Check that "bmap1" and "bmap2" have the same parameters,
1431 * reporting an error if they do not.
1433 static isl_stat isl_basic_map_check_equal_params(
1434 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1436 isl_bool match;
1438 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1439 if (match < 0)
1440 return isl_stat_error;
1441 if (!match)
1442 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1443 "parameters don't match", return isl_stat_error);
1444 return isl_stat_ok;
1447 __isl_give isl_map *isl_map_align_params_map_map_and(
1448 __isl_take isl_map *map1, __isl_take isl_map *map2,
1449 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1450 __isl_take isl_map *map2))
1452 if (!map1 || !map2)
1453 goto error;
1454 if (isl_map_has_equal_params(map1, map2))
1455 return fn(map1, map2);
1456 if (isl_map_check_named_params(map1) < 0)
1457 goto error;
1458 if (isl_map_check_named_params(map2) < 0)
1459 goto error;
1460 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1461 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1462 return fn(map1, map2);
1463 error:
1464 isl_map_free(map1);
1465 isl_map_free(map2);
1466 return NULL;
1469 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1470 __isl_keep isl_map *map2,
1471 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1473 isl_bool r;
1475 if (!map1 || !map2)
1476 return isl_bool_error;
1477 if (isl_map_has_equal_params(map1, map2))
1478 return fn(map1, map2);
1479 if (isl_map_check_named_params(map1) < 0)
1480 return isl_bool_error;
1481 if (isl_map_check_named_params(map2) < 0)
1482 return isl_bool_error;
1483 map1 = isl_map_copy(map1);
1484 map2 = isl_map_copy(map2);
1485 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1486 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1487 r = fn(map1, map2);
1488 isl_map_free(map1);
1489 isl_map_free(map2);
1490 return r;
1493 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1495 struct isl_ctx *ctx;
1496 if (!bmap)
1497 return -1;
1498 ctx = bmap->ctx;
1499 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1500 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1501 return -1);
1502 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1503 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1504 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1505 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1506 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1507 isl_int *t;
1508 int j = isl_basic_map_alloc_inequality(bmap);
1509 if (j < 0)
1510 return -1;
1511 t = bmap->ineq[j];
1512 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1513 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1514 bmap->eq[-1] = t;
1515 bmap->n_eq++;
1516 bmap->n_ineq--;
1517 bmap->eq--;
1518 return 0;
1520 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1521 bmap->extra - bmap->n_div);
1522 return bmap->n_eq++;
1525 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1527 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1530 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1532 if (!bmap)
1533 return -1;
1534 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1535 bmap->n_eq -= n;
1536 return 0;
1539 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1541 return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1544 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1546 isl_int *t;
1547 if (!bmap)
1548 return -1;
1549 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1551 if (pos != bmap->n_eq - 1) {
1552 t = bmap->eq[pos];
1553 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1554 bmap->eq[bmap->n_eq - 1] = t;
1556 bmap->n_eq--;
1557 return 0;
1560 /* Turn inequality "pos" of "bmap" into an equality.
1562 * In particular, we move the inequality in front of the equalities
1563 * and move the last inequality in the position of the moved inequality.
1564 * Note that isl_tab_make_equalities_explicit depends on this particular
1565 * change in the ordering of the constraints.
1567 void isl_basic_map_inequality_to_equality(
1568 struct isl_basic_map *bmap, unsigned pos)
1570 isl_int *t;
1572 t = bmap->ineq[pos];
1573 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1574 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1575 bmap->eq[-1] = t;
1576 bmap->n_eq++;
1577 bmap->n_ineq--;
1578 bmap->eq--;
1579 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1580 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1581 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1582 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1585 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1587 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1590 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1592 struct isl_ctx *ctx;
1593 if (!bmap)
1594 return -1;
1595 ctx = bmap->ctx;
1596 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1597 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1598 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1599 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1600 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1601 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1602 1 + isl_basic_map_total_dim(bmap),
1603 bmap->extra - bmap->n_div);
1604 return bmap->n_ineq++;
1607 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1609 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1612 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1614 if (!bmap)
1615 return -1;
1616 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1617 bmap->n_ineq -= n;
1618 return 0;
1621 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1623 return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1626 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1628 isl_int *t;
1629 if (!bmap)
1630 return -1;
1631 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1633 if (pos != bmap->n_ineq - 1) {
1634 t = bmap->ineq[pos];
1635 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1636 bmap->ineq[bmap->n_ineq - 1] = t;
1637 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1639 bmap->n_ineq--;
1640 return 0;
1643 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1645 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1648 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1649 isl_int *eq)
1651 isl_bool empty;
1652 int k;
1654 empty = isl_basic_map_plain_is_empty(bmap);
1655 if (empty < 0)
1656 return isl_basic_map_free(bmap);
1657 if (empty)
1658 return bmap;
1660 bmap = isl_basic_map_cow(bmap);
1661 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1662 if (!bmap)
1663 return NULL;
1664 k = isl_basic_map_alloc_equality(bmap);
1665 if (k < 0)
1666 goto error;
1667 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1668 return bmap;
1669 error:
1670 isl_basic_map_free(bmap);
1671 return NULL;
1674 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1675 isl_int *eq)
1677 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1680 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1681 isl_int *ineq)
1683 int k;
1685 bmap = isl_basic_map_cow(bmap);
1686 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1687 if (!bmap)
1688 return NULL;
1689 k = isl_basic_map_alloc_inequality(bmap);
1690 if (k < 0)
1691 goto error;
1692 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1693 return bmap;
1694 error:
1695 isl_basic_map_free(bmap);
1696 return NULL;
1699 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1700 isl_int *ineq)
1702 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1705 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1707 if (!bmap)
1708 return -1;
1709 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1710 isl_seq_clr(bmap->div[bmap->n_div] +
1711 1 + 1 + isl_basic_map_total_dim(bmap),
1712 bmap->extra - bmap->n_div);
1713 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1714 return bmap->n_div++;
1717 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1719 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1722 #undef TYPE
1723 #define TYPE isl_basic_map
1724 #include "check_type_range_templ.c"
1726 /* Check that there are "n" dimensions of type "type" starting at "first"
1727 * in "bset".
1729 isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1730 enum isl_dim_type type, unsigned first, unsigned n)
1732 return isl_basic_map_check_range(bset_to_bmap(bset),
1733 type, first, n);
1736 /* Insert an extra integer division, prescribed by "div", to "bmap"
1737 * at (integer division) position "pos".
1739 * The integer division is first added at the end and then moved
1740 * into the right position.
1742 __isl_give isl_basic_map *isl_basic_map_insert_div(
1743 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1745 int i, k;
1747 bmap = isl_basic_map_cow(bmap);
1748 if (!bmap || !div)
1749 return isl_basic_map_free(bmap);
1751 if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1752 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1753 "unexpected size", return isl_basic_map_free(bmap));
1754 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1755 return isl_basic_map_free(bmap);
1757 bmap = isl_basic_map_extend_space(bmap,
1758 isl_basic_map_get_space(bmap), 1, 0, 2);
1759 k = isl_basic_map_alloc_div(bmap);
1760 if (k < 0)
1761 return isl_basic_map_free(bmap);
1762 isl_seq_cpy(bmap->div[k], div->el, div->size);
1763 isl_int_set_si(bmap->div[k][div->size], 0);
1765 for (i = k; i > pos; --i)
1766 bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1768 return bmap;
1771 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1773 if (!bmap)
1774 return isl_stat_error;
1775 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1776 bmap->n_div -= n;
1777 return isl_stat_ok;
1780 static __isl_give isl_basic_map *add_constraints(
1781 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1782 unsigned i_pos, unsigned o_pos)
1784 unsigned total, n_param, n_in, o_in, n_out, o_out, n_div;
1785 isl_ctx *ctx;
1786 isl_space *space;
1787 struct isl_dim_map *dim_map;
1789 space = isl_basic_map_peek_space(bmap2);
1790 if (!bmap1 || !space)
1791 goto error;
1793 total = isl_basic_map_dim(bmap1, isl_dim_all);
1794 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1795 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1796 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1797 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1798 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1799 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1800 ctx = isl_basic_map_get_ctx(bmap1);
1801 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1802 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1803 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1804 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1805 isl_dim_map_div(dim_map, bmap2, total);
1807 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1808 error:
1809 isl_basic_map_free(bmap1);
1810 isl_basic_map_free(bmap2);
1811 return NULL;
1814 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1815 struct isl_basic_set *bset2, unsigned pos)
1817 return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1818 bset_to_bmap(bset2), 0, pos));
1821 __isl_give isl_basic_map *isl_basic_map_extend_space(
1822 __isl_take isl_basic_map *base, __isl_take isl_space *space,
1823 unsigned extra, unsigned n_eq, unsigned n_ineq)
1825 struct isl_basic_map *ext;
1826 unsigned flags;
1827 int dims_ok;
1829 if (!space)
1830 goto error;
1832 if (!base)
1833 goto error;
1835 dims_ok = isl_space_is_equal(base->dim, space) &&
1836 base->extra >= base->n_div + extra;
1838 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1839 room_for_ineq(base, n_ineq)) {
1840 isl_space_free(space);
1841 return base;
1844 isl_assert(base->ctx, base->dim->nparam <= space->nparam, goto error);
1845 isl_assert(base->ctx, base->dim->n_in <= space->n_in, goto error);
1846 isl_assert(base->ctx, base->dim->n_out <= space->n_out, goto error);
1847 extra += base->extra;
1848 n_eq += base->n_eq;
1849 n_ineq += base->n_ineq;
1851 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1852 space = NULL;
1853 if (!ext)
1854 goto error;
1856 if (dims_ok)
1857 ext->sample = isl_vec_copy(base->sample);
1858 flags = base->flags;
1859 ext = add_constraints(ext, base, 0, 0);
1860 if (ext) {
1861 ext->flags = flags;
1862 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1865 return ext;
1867 error:
1868 isl_space_free(space);
1869 isl_basic_map_free(base);
1870 return NULL;
1873 __isl_give isl_basic_set *isl_basic_set_extend_space(
1874 __isl_take isl_basic_set *base,
1875 __isl_take isl_space *dim, unsigned extra,
1876 unsigned n_eq, unsigned n_ineq)
1878 return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1879 dim, extra, n_eq, n_ineq));
1882 struct isl_basic_map *isl_basic_map_extend_constraints(
1883 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1885 if (!base)
1886 return NULL;
1887 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1888 0, n_eq, n_ineq);
1891 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1892 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1893 unsigned n_eq, unsigned n_ineq)
1895 struct isl_basic_map *bmap;
1896 isl_space *dim;
1898 if (!base)
1899 return NULL;
1900 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1901 if (!dim)
1902 goto error;
1904 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1905 return bmap;
1906 error:
1907 isl_basic_map_free(base);
1908 return NULL;
1911 struct isl_basic_set *isl_basic_set_extend_constraints(
1912 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1914 isl_basic_map *bmap = bset_to_bmap(base);
1915 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1916 return bset_from_bmap(bmap);
1919 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1921 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1924 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1926 if (!bmap)
1927 return NULL;
1929 if (bmap->ref > 1) {
1930 bmap->ref--;
1931 bmap = isl_basic_map_dup(bmap);
1933 if (bmap) {
1934 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1935 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1937 return bmap;
1940 /* Clear all cached information in "map", either because it is about
1941 * to be modified or because it is being freed.
1942 * Always return the same pointer that is passed in.
1943 * This is needed for the use in isl_map_free.
1945 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1947 isl_basic_map_free(map->cached_simple_hull[0]);
1948 isl_basic_map_free(map->cached_simple_hull[1]);
1949 map->cached_simple_hull[0] = NULL;
1950 map->cached_simple_hull[1] = NULL;
1951 return map;
1954 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
1956 return isl_map_cow(set);
1959 /* Return an isl_map that is equal to "map" and that has only
1960 * a single reference.
1962 * If the original input already has only one reference, then
1963 * simply return it, but clear all cached information, since
1964 * it may be rendered invalid by the operations that will be
1965 * performed on the result.
1967 * Otherwise, create a duplicate (without any cached information).
1969 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
1971 if (!map)
1972 return NULL;
1974 if (map->ref == 1)
1975 return clear_caches(map);
1976 map->ref--;
1977 return isl_map_dup(map);
1980 static void swap_vars(struct isl_blk blk, isl_int *a,
1981 unsigned a_len, unsigned b_len)
1983 isl_seq_cpy(blk.data, a+a_len, b_len);
1984 isl_seq_cpy(blk.data+b_len, a, a_len);
1985 isl_seq_cpy(a, blk.data, b_len+a_len);
1988 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1989 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1991 int i;
1992 struct isl_blk blk;
1994 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
1995 goto error;
1997 if (n1 == 0 || n2 == 0)
1998 return bmap;
2000 bmap = isl_basic_map_cow(bmap);
2001 if (!bmap)
2002 return NULL;
2004 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2005 if (isl_blk_is_error(blk))
2006 goto error;
2008 for (i = 0; i < bmap->n_eq; ++i)
2009 swap_vars(blk,
2010 bmap->eq[i] + pos, n1, n2);
2012 for (i = 0; i < bmap->n_ineq; ++i)
2013 swap_vars(blk,
2014 bmap->ineq[i] + pos, n1, n2);
2016 for (i = 0; i < bmap->n_div; ++i)
2017 swap_vars(blk,
2018 bmap->div[i]+1 + pos, n1, n2);
2020 isl_blk_free(bmap->ctx, blk);
2022 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2023 bmap = isl_basic_map_gauss(bmap, NULL);
2024 return isl_basic_map_finalize(bmap);
2025 error:
2026 isl_basic_map_free(bmap);
2027 return NULL;
2030 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2031 __isl_take isl_basic_map *bmap)
2033 int i = 0;
2034 unsigned total;
2035 if (!bmap)
2036 goto error;
2037 total = isl_basic_map_total_dim(bmap);
2038 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2039 return isl_basic_map_free(bmap);
2040 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2041 if (bmap->n_eq > 0)
2042 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
2043 else {
2044 i = isl_basic_map_alloc_equality(bmap);
2045 if (i < 0)
2046 goto error;
2048 isl_int_set_si(bmap->eq[i][0], 1);
2049 isl_seq_clr(bmap->eq[i]+1, total);
2050 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2051 isl_vec_free(bmap->sample);
2052 bmap->sample = NULL;
2053 return isl_basic_map_finalize(bmap);
2054 error:
2055 isl_basic_map_free(bmap);
2056 return NULL;
2059 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2060 __isl_take isl_basic_set *bset)
2062 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2065 __isl_give isl_basic_map *isl_basic_map_set_rational(
2066 __isl_take isl_basic_map *bmap)
2068 if (!bmap)
2069 return NULL;
2071 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2072 return bmap;
2074 bmap = isl_basic_map_cow(bmap);
2075 if (!bmap)
2076 return NULL;
2078 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2080 return isl_basic_map_finalize(bmap);
2083 __isl_give isl_basic_set *isl_basic_set_set_rational(
2084 __isl_take isl_basic_set *bset)
2086 return isl_basic_map_set_rational(bset);
2089 __isl_give isl_basic_set *isl_basic_set_set_integral(
2090 __isl_take isl_basic_set *bset)
2092 if (!bset)
2093 return NULL;
2095 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2096 return bset;
2098 bset = isl_basic_set_cow(bset);
2099 if (!bset)
2100 return NULL;
2102 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2104 return isl_basic_set_finalize(bset);
2107 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2109 int i;
2111 map = isl_map_cow(map);
2112 if (!map)
2113 return NULL;
2114 for (i = 0; i < map->n; ++i) {
2115 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2116 if (!map->p[i])
2117 goto error;
2119 return map;
2120 error:
2121 isl_map_free(map);
2122 return NULL;
2125 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2127 return isl_map_set_rational(set);
2130 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2131 * of "bmap").
2133 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2135 isl_int *t = bmap->div[a];
2136 bmap->div[a] = bmap->div[b];
2137 bmap->div[b] = t;
2140 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2141 * div definitions accordingly.
2143 __isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2144 int a, int b)
2146 int i;
2147 unsigned off;
2149 if (!bmap)
2150 return NULL;
2152 off = isl_space_dim(bmap->dim, isl_dim_all);
2153 swap_div(bmap, a, b);
2155 for (i = 0; i < bmap->n_eq; ++i)
2156 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2158 for (i = 0; i < bmap->n_ineq; ++i)
2159 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2161 for (i = 0; i < bmap->n_div; ++i)
2162 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2163 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2165 return bmap;
2168 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2170 isl_seq_cpy(c, c + n, rem);
2171 isl_seq_clr(c + rem, n);
2174 /* Drop n dimensions starting at first.
2176 * In principle, this frees up some extra variables as the number
2177 * of columns remains constant, but we would have to extend
2178 * the div array too as the number of rows in this array is assumed
2179 * to be equal to extra.
2181 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2182 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2184 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2187 /* Move "n" divs starting at "first" to the end of the list of divs.
2189 static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
2190 unsigned first, unsigned n)
2192 isl_int **div;
2193 int i;
2195 if (first + n == bmap->n_div)
2196 return bmap;
2198 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2199 if (!div)
2200 goto error;
2201 for (i = 0; i < n; ++i)
2202 div[i] = bmap->div[first + i];
2203 for (i = 0; i < bmap->n_div - first - n; ++i)
2204 bmap->div[first + i] = bmap->div[first + n + i];
2205 for (i = 0; i < n; ++i)
2206 bmap->div[bmap->n_div - n + i] = div[i];
2207 free(div);
2208 return bmap;
2209 error:
2210 isl_basic_map_free(bmap);
2211 return NULL;
2214 #undef TYPE
2215 #define TYPE isl_map
2216 static
2217 #include "check_type_range_templ.c"
2219 /* Check that there are "n" dimensions of type "type" starting at "first"
2220 * in "set".
2222 static isl_stat isl_set_check_range(__isl_keep isl_set *set,
2223 enum isl_dim_type type, unsigned first, unsigned n)
2225 return isl_map_check_range(set_to_map(set), type, first, n);
2228 /* Drop "n" dimensions of type "type" starting at "first".
2229 * Perform the core computation, without cowing or
2230 * simplifying and finalizing the result.
2232 * In principle, this frees up some extra variables as the number
2233 * of columns remains constant, but we would have to extend
2234 * the div array too as the number of rows in this array is assumed
2235 * to be equal to extra.
2237 __isl_give isl_basic_map *isl_basic_map_drop_core(
2238 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2239 unsigned first, unsigned n)
2241 int i;
2242 unsigned offset;
2243 unsigned left;
2245 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2246 return isl_basic_map_free(bmap);
2248 offset = isl_basic_map_offset(bmap, type) + first;
2249 left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
2250 for (i = 0; i < bmap->n_eq; ++i)
2251 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2253 for (i = 0; i < bmap->n_ineq; ++i)
2254 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2256 for (i = 0; i < bmap->n_div; ++i)
2257 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2259 if (type == isl_dim_div) {
2260 bmap = move_divs_last(bmap, first, n);
2261 if (!bmap)
2262 return NULL;
2263 if (isl_basic_map_free_div(bmap, n) < 0)
2264 return isl_basic_map_free(bmap);
2265 } else
2266 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2267 if (!bmap->dim)
2268 return isl_basic_map_free(bmap);
2270 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2271 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2272 return bmap;
2275 /* Drop "n" dimensions of type "type" starting at "first".
2277 * In principle, this frees up some extra variables as the number
2278 * of columns remains constant, but we would have to extend
2279 * the div array too as the number of rows in this array is assumed
2280 * to be equal to extra.
2282 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2283 enum isl_dim_type type, unsigned first, unsigned n)
2285 if (!bmap)
2286 return NULL;
2287 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2288 return bmap;
2290 bmap = isl_basic_map_cow(bmap);
2291 if (!bmap)
2292 return NULL;
2294 bmap = isl_basic_map_drop_core(bmap, type, first, n);
2296 bmap = isl_basic_map_simplify(bmap);
2297 return isl_basic_map_finalize(bmap);
2300 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2301 enum isl_dim_type type, unsigned first, unsigned n)
2303 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2304 type, first, n));
2307 /* No longer consider "map" to be normalized.
2309 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2311 if (!map)
2312 return NULL;
2313 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2314 return map;
2317 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2318 enum isl_dim_type type, unsigned first, unsigned n)
2320 int i;
2322 if (isl_map_check_range(map, type, first, n) < 0)
2323 return isl_map_free(map);
2325 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2326 return map;
2327 map = isl_map_cow(map);
2328 if (!map)
2329 goto error;
2330 map->dim = isl_space_drop_dims(map->dim, type, first, n);
2331 if (!map->dim)
2332 goto error;
2334 for (i = 0; i < map->n; ++i) {
2335 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2336 if (!map->p[i])
2337 goto error;
2339 map = isl_map_unmark_normalized(map);
2341 return map;
2342 error:
2343 isl_map_free(map);
2344 return NULL;
2347 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2348 enum isl_dim_type type, unsigned first, unsigned n)
2350 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2353 /* Drop the integer division at position "div", which is assumed
2354 * not to appear in any of the constraints or
2355 * in any of the other integer divisions.
2357 * Since the integer division is redundant, there is no need to cow.
2359 __isl_give isl_basic_map *isl_basic_map_drop_div(
2360 __isl_take isl_basic_map *bmap, unsigned div)
2362 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2365 /* Eliminate the specified n dimensions starting at first from the
2366 * constraints, without removing the dimensions from the space.
2367 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2369 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2370 enum isl_dim_type type, unsigned first, unsigned n)
2372 int i;
2374 if (n == 0)
2375 return map;
2377 if (isl_map_check_range(map, type, first, n) < 0)
2378 return isl_map_free(map);
2380 map = isl_map_cow(map);
2381 if (!map)
2382 return NULL;
2384 for (i = 0; i < map->n; ++i) {
2385 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2386 if (!map->p[i])
2387 goto error;
2389 return map;
2390 error:
2391 isl_map_free(map);
2392 return NULL;
2395 /* Eliminate the specified n dimensions starting at first from the
2396 * constraints, without removing the dimensions from the space.
2397 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2399 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2400 enum isl_dim_type type, unsigned first, unsigned n)
2402 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2405 /* Eliminate the specified n dimensions starting at first from the
2406 * constraints, without removing the dimensions from the space.
2407 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2409 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2410 unsigned first, unsigned n)
2412 return isl_set_eliminate(set, isl_dim_set, first, n);
2415 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2416 __isl_take isl_basic_map *bmap)
2418 if (!bmap)
2419 return NULL;
2420 bmap = isl_basic_map_eliminate_vars(bmap,
2421 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
2422 if (!bmap)
2423 return NULL;
2424 bmap->n_div = 0;
2425 return isl_basic_map_finalize(bmap);
2428 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2429 __isl_take isl_basic_set *bset)
2431 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2434 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2436 int i;
2438 if (!map)
2439 return NULL;
2440 if (map->n == 0)
2441 return map;
2443 map = isl_map_cow(map);
2444 if (!map)
2445 return NULL;
2447 for (i = 0; i < map->n; ++i) {
2448 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2449 if (!map->p[i])
2450 goto error;
2452 return map;
2453 error:
2454 isl_map_free(map);
2455 return NULL;
2458 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2460 return isl_map_remove_divs(set);
2463 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2464 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2465 unsigned first, unsigned n)
2467 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2468 return isl_basic_map_free(bmap);
2469 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2470 return bmap;
2471 bmap = isl_basic_map_eliminate_vars(bmap,
2472 isl_basic_map_offset(bmap, type) - 1 + first, n);
2473 if (!bmap)
2474 return bmap;
2475 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2476 return bmap;
2477 bmap = isl_basic_map_drop(bmap, type, first, n);
2478 return bmap;
2481 /* Return true if the definition of the given div (recursively) involves
2482 * any of the given variables.
2484 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2485 unsigned first, unsigned n)
2487 int i;
2488 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2490 if (isl_int_is_zero(bmap->div[div][0]))
2491 return isl_bool_false;
2492 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2493 return isl_bool_true;
2495 for (i = bmap->n_div - 1; i >= 0; --i) {
2496 isl_bool involves;
2498 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2499 continue;
2500 involves = div_involves_vars(bmap, i, first, n);
2501 if (involves < 0 || involves)
2502 return involves;
2505 return isl_bool_false;
2508 /* Try and add a lower and/or upper bound on "div" to "bmap"
2509 * based on inequality "i".
2510 * "total" is the total number of variables (excluding the divs).
2511 * "v" is a temporary object that can be used during the calculations.
2512 * If "lb" is set, then a lower bound should be constructed.
2513 * If "ub" is set, then an upper bound should be constructed.
2515 * The calling function has already checked that the inequality does not
2516 * reference "div", but we still need to check that the inequality is
2517 * of the right form. We'll consider the case where we want to construct
2518 * a lower bound. The construction of upper bounds is similar.
2520 * Let "div" be of the form
2522 * q = floor((a + f(x))/d)
2524 * We essentially check if constraint "i" is of the form
2526 * b + f(x) >= 0
2528 * so that we can use it to derive a lower bound on "div".
2529 * However, we allow a slightly more general form
2531 * b + g(x) >= 0
2533 * with the condition that the coefficients of g(x) - f(x) are all
2534 * divisible by d.
2535 * Rewriting this constraint as
2537 * 0 >= -b - g(x)
2539 * adding a + f(x) to both sides and dividing by d, we obtain
2541 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2543 * Taking the floor on both sides, we obtain
2545 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2547 * or
2549 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2551 * In the case of an upper bound, we construct the constraint
2553 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2556 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2557 __isl_take isl_basic_map *bmap, int div, int i,
2558 unsigned total, isl_int v, int lb, int ub)
2560 int j;
2562 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2563 if (lb) {
2564 isl_int_sub(v, bmap->ineq[i][1 + j],
2565 bmap->div[div][1 + 1 + j]);
2566 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2568 if (ub) {
2569 isl_int_add(v, bmap->ineq[i][1 + j],
2570 bmap->div[div][1 + 1 + j]);
2571 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2574 if (!lb && !ub)
2575 return bmap;
2577 bmap = isl_basic_map_cow(bmap);
2578 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2579 if (lb) {
2580 int k = isl_basic_map_alloc_inequality(bmap);
2581 if (k < 0)
2582 goto error;
2583 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2584 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2585 bmap->div[div][1 + j]);
2586 isl_int_cdiv_q(bmap->ineq[k][j],
2587 bmap->ineq[k][j], bmap->div[div][0]);
2589 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2591 if (ub) {
2592 int k = isl_basic_map_alloc_inequality(bmap);
2593 if (k < 0)
2594 goto error;
2595 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2596 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2597 bmap->div[div][1 + j]);
2598 isl_int_fdiv_q(bmap->ineq[k][j],
2599 bmap->ineq[k][j], bmap->div[div][0]);
2601 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2604 return bmap;
2605 error:
2606 isl_basic_map_free(bmap);
2607 return NULL;
2610 /* This function is called right before "div" is eliminated from "bmap"
2611 * using Fourier-Motzkin.
2612 * Look through the constraints of "bmap" for constraints on the argument
2613 * of the integer division and use them to construct constraints on the
2614 * integer division itself. These constraints can then be combined
2615 * during the Fourier-Motzkin elimination.
2616 * Note that it is only useful to introduce lower bounds on "div"
2617 * if "bmap" already contains upper bounds on "div" as the newly
2618 * introduce lower bounds can then be combined with the pre-existing
2619 * upper bounds. Similarly for upper bounds.
2620 * We therefore first check if "bmap" contains any lower and/or upper bounds
2621 * on "div".
2623 * It is interesting to note that the introduction of these constraints
2624 * can indeed lead to more accurate results, even when compared to
2625 * deriving constraints on the argument of "div" from constraints on "div".
2626 * Consider, for example, the set
2628 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2630 * The second constraint can be rewritten as
2632 * 2 * [(-i-2j+3)/4] + k >= 0
2634 * from which we can derive
2636 * -i - 2j + 3 >= -2k
2638 * or
2640 * i + 2j <= 3 + 2k
2642 * Combined with the first constraint, we obtain
2644 * -3 <= 3 + 2k or k >= -3
2646 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2647 * the first constraint, we obtain
2649 * [(i + 2j)/4] >= [-3/4] = -1
2651 * Combining this constraint with the second constraint, we obtain
2653 * k >= -2
2655 static __isl_give isl_basic_map *insert_bounds_on_div(
2656 __isl_take isl_basic_map *bmap, int div)
2658 int i;
2659 int check_lb, check_ub;
2660 isl_int v;
2661 unsigned total;
2663 if (!bmap)
2664 return NULL;
2666 if (isl_int_is_zero(bmap->div[div][0]))
2667 return bmap;
2669 total = isl_space_dim(bmap->dim, isl_dim_all);
2671 check_lb = 0;
2672 check_ub = 0;
2673 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2674 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2675 if (s > 0)
2676 check_ub = 1;
2677 if (s < 0)
2678 check_lb = 1;
2681 if (!check_lb && !check_ub)
2682 return bmap;
2684 isl_int_init(v);
2686 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2687 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2688 continue;
2690 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2691 check_lb, check_ub);
2694 isl_int_clear(v);
2696 return bmap;
2699 /* Remove all divs (recursively) involving any of the given dimensions
2700 * in their definitions.
2702 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2703 __isl_take isl_basic_map *bmap,
2704 enum isl_dim_type type, unsigned first, unsigned n)
2706 int i;
2708 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2709 return isl_basic_map_free(bmap);
2710 first += isl_basic_map_offset(bmap, type);
2712 for (i = bmap->n_div - 1; i >= 0; --i) {
2713 isl_bool involves;
2715 involves = div_involves_vars(bmap, i, first, n);
2716 if (involves < 0)
2717 return isl_basic_map_free(bmap);
2718 if (!involves)
2719 continue;
2720 bmap = insert_bounds_on_div(bmap, i);
2721 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2722 if (!bmap)
2723 return NULL;
2724 i = bmap->n_div;
2727 return bmap;
2730 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2731 __isl_take isl_basic_set *bset,
2732 enum isl_dim_type type, unsigned first, unsigned n)
2734 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2737 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2738 enum isl_dim_type type, unsigned first, unsigned n)
2740 int i;
2742 if (!map)
2743 return NULL;
2744 if (map->n == 0)
2745 return map;
2747 map = isl_map_cow(map);
2748 if (!map)
2749 return NULL;
2751 for (i = 0; i < map->n; ++i) {
2752 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2753 type, first, n);
2754 if (!map->p[i])
2755 goto error;
2757 return map;
2758 error:
2759 isl_map_free(map);
2760 return NULL;
2763 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2764 enum isl_dim_type type, unsigned first, unsigned n)
2766 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2767 type, first, n));
2770 /* Does the description of "bmap" depend on the specified dimensions?
2771 * We also check whether the dimensions appear in any of the div definitions.
2772 * In principle there is no need for this check. If the dimensions appear
2773 * in a div definition, they also appear in the defining constraints of that
2774 * div.
2776 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2777 enum isl_dim_type type, unsigned first, unsigned n)
2779 int i;
2781 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2782 return isl_bool_error;
2784 first += isl_basic_map_offset(bmap, type);
2785 for (i = 0; i < bmap->n_eq; ++i)
2786 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2787 return isl_bool_true;
2788 for (i = 0; i < bmap->n_ineq; ++i)
2789 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2790 return isl_bool_true;
2791 for (i = 0; i < bmap->n_div; ++i) {
2792 if (isl_int_is_zero(bmap->div[i][0]))
2793 continue;
2794 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2795 return isl_bool_true;
2798 return isl_bool_false;
2801 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2802 enum isl_dim_type type, unsigned first, unsigned n)
2804 int i;
2806 if (isl_map_check_range(map, type, first, n) < 0)
2807 return isl_bool_error;
2809 for (i = 0; i < map->n; ++i) {
2810 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2811 type, first, n);
2812 if (involves < 0 || involves)
2813 return involves;
2816 return isl_bool_false;
2819 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2820 enum isl_dim_type type, unsigned first, unsigned n)
2822 return isl_basic_map_involves_dims(bset, type, first, n);
2825 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2826 enum isl_dim_type type, unsigned first, unsigned n)
2828 return isl_map_involves_dims(set, type, first, n);
2831 /* Drop all constraints in bmap that involve any of the dimensions
2832 * first to first+n-1.
2833 * This function only performs the actual removal of constraints.
2835 * This function should not call finalize since it is used by
2836 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
2838 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2839 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2841 int i;
2843 if (n == 0)
2844 return bmap;
2846 bmap = isl_basic_map_cow(bmap);
2848 if (!bmap)
2849 return NULL;
2851 for (i = bmap->n_eq - 1; i >= 0; --i) {
2852 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2853 continue;
2854 isl_basic_map_drop_equality(bmap, i);
2857 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2858 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2859 continue;
2860 isl_basic_map_drop_inequality(bmap, i);
2863 return bmap;
2866 /* Drop all constraints in bset that involve any of the dimensions
2867 * first to first+n-1.
2868 * This function only performs the actual removal of constraints.
2870 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2871 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2873 return isl_basic_map_drop_constraints_involving(bset, first, n);
2876 /* Drop all constraints in bmap that do not involve any of the dimensions
2877 * first to first + n - 1 of the given type.
2879 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2880 __isl_take isl_basic_map *bmap,
2881 enum isl_dim_type type, unsigned first, unsigned n)
2883 int i;
2885 if (n == 0) {
2886 isl_space *space = isl_basic_map_get_space(bmap);
2887 isl_basic_map_free(bmap);
2888 return isl_basic_map_universe(space);
2890 bmap = isl_basic_map_cow(bmap);
2891 if (!bmap)
2892 return NULL;
2894 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2895 return isl_basic_map_free(bmap);
2897 first += isl_basic_map_offset(bmap, type) - 1;
2899 for (i = bmap->n_eq - 1; i >= 0; --i) {
2900 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2901 continue;
2902 isl_basic_map_drop_equality(bmap, i);
2905 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2906 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2907 continue;
2908 isl_basic_map_drop_inequality(bmap, i);
2911 bmap = isl_basic_map_add_known_div_constraints(bmap);
2912 return bmap;
2915 /* Drop all constraints in bset that do not involve any of the dimensions
2916 * first to first + n - 1 of the given type.
2918 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2919 __isl_take isl_basic_set *bset,
2920 enum isl_dim_type type, unsigned first, unsigned n)
2922 return isl_basic_map_drop_constraints_not_involving_dims(bset,
2923 type, first, n);
2926 /* Drop all constraints in bmap that involve any of the dimensions
2927 * first to first + n - 1 of the given type.
2929 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2930 __isl_take isl_basic_map *bmap,
2931 enum isl_dim_type type, unsigned first, unsigned n)
2933 if (!bmap)
2934 return NULL;
2935 if (n == 0)
2936 return bmap;
2938 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2939 return isl_basic_map_free(bmap);
2941 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2942 first += isl_basic_map_offset(bmap, type) - 1;
2943 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
2944 bmap = isl_basic_map_add_known_div_constraints(bmap);
2945 return bmap;
2948 /* Drop all constraints in bset that involve any of the dimensions
2949 * first to first + n - 1 of the given type.
2951 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2952 __isl_take isl_basic_set *bset,
2953 enum isl_dim_type type, unsigned first, unsigned n)
2955 return isl_basic_map_drop_constraints_involving_dims(bset,
2956 type, first, n);
2959 /* Drop constraints from "map" by applying "drop" to each basic map.
2961 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2962 enum isl_dim_type type, unsigned first, unsigned n,
2963 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2964 enum isl_dim_type type, unsigned first, unsigned n))
2966 int i;
2968 if (isl_map_check_range(map, type, first, n) < 0)
2969 return isl_map_free(map);
2971 map = isl_map_cow(map);
2972 if (!map)
2973 return NULL;
2975 for (i = 0; i < map->n; ++i) {
2976 map->p[i] = drop(map->p[i], type, first, n);
2977 if (!map->p[i])
2978 return isl_map_free(map);
2981 if (map->n > 1)
2982 ISL_F_CLR(map, ISL_MAP_DISJOINT);
2984 return map;
2987 /* Drop all constraints in map that involve any of the dimensions
2988 * first to first + n - 1 of the given type.
2990 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
2991 __isl_take isl_map *map,
2992 enum isl_dim_type type, unsigned first, unsigned n)
2994 if (n == 0)
2995 return map;
2996 return drop_constraints(map, type, first, n,
2997 &isl_basic_map_drop_constraints_involving_dims);
3000 /* Drop all constraints in "map" that do not involve any of the dimensions
3001 * first to first + n - 1 of the given type.
3003 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3004 __isl_take isl_map *map,
3005 enum isl_dim_type type, unsigned first, unsigned n)
3007 if (n == 0) {
3008 isl_space *space = isl_map_get_space(map);
3009 isl_map_free(map);
3010 return isl_map_universe(space);
3012 return drop_constraints(map, type, first, n,
3013 &isl_basic_map_drop_constraints_not_involving_dims);
3016 /* Drop all constraints in set that involve any of the dimensions
3017 * first to first + n - 1 of the given type.
3019 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3020 __isl_take isl_set *set,
3021 enum isl_dim_type type, unsigned first, unsigned n)
3023 return isl_map_drop_constraints_involving_dims(set, type, first, n);
3026 /* Drop all constraints in "set" that do not involve any of the dimensions
3027 * first to first + n - 1 of the given type.
3029 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3030 __isl_take isl_set *set,
3031 enum isl_dim_type type, unsigned first, unsigned n)
3033 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3036 /* Does local variable "div" of "bmap" have a complete explicit representation?
3037 * Having a complete explicit representation requires not only
3038 * an explicit representation, but also that all local variables
3039 * that appear in this explicit representation in turn have
3040 * a complete explicit representation.
3042 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3044 int i;
3045 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3046 isl_bool marked;
3048 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3049 if (marked < 0 || marked)
3050 return isl_bool_not(marked);
3052 for (i = bmap->n_div - 1; i >= 0; --i) {
3053 isl_bool known;
3055 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3056 continue;
3057 known = isl_basic_map_div_is_known(bmap, i);
3058 if (known < 0 || !known)
3059 return known;
3062 return isl_bool_true;
3065 /* Remove all divs that are unknown or defined in terms of unknown divs.
3067 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3068 __isl_take isl_basic_map *bmap)
3070 int i;
3072 if (!bmap)
3073 return NULL;
3075 for (i = bmap->n_div - 1; i >= 0; --i) {
3076 if (isl_basic_map_div_is_known(bmap, i))
3077 continue;
3078 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3079 if (!bmap)
3080 return NULL;
3081 i = bmap->n_div;
3084 return bmap;
3087 /* Remove all divs that are unknown or defined in terms of unknown divs.
3089 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3090 __isl_take isl_basic_set *bset)
3092 return isl_basic_map_remove_unknown_divs(bset);
3095 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3097 int i;
3099 if (!map)
3100 return NULL;
3101 if (map->n == 0)
3102 return map;
3104 map = isl_map_cow(map);
3105 if (!map)
3106 return NULL;
3108 for (i = 0; i < map->n; ++i) {
3109 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3110 if (!map->p[i])
3111 goto error;
3113 return map;
3114 error:
3115 isl_map_free(map);
3116 return NULL;
3119 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3121 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3124 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3125 __isl_take isl_basic_set *bset,
3126 enum isl_dim_type type, unsigned first, unsigned n)
3128 isl_basic_map *bmap = bset_to_bmap(bset);
3129 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3130 return bset_from_bmap(bmap);
3133 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3134 enum isl_dim_type type, unsigned first, unsigned n)
3136 int i;
3138 if (n == 0)
3139 return map;
3141 map = isl_map_cow(map);
3142 if (isl_map_check_range(map, type, first, n) < 0)
3143 return isl_map_free(map);
3145 for (i = 0; i < map->n; ++i) {
3146 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3147 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3148 if (!map->p[i])
3149 goto error;
3151 map = isl_map_drop(map, type, first, n);
3152 return map;
3153 error:
3154 isl_map_free(map);
3155 return NULL;
3158 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3159 enum isl_dim_type type, unsigned first, unsigned n)
3161 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3162 type, first, n));
3165 /* Project out n inputs starting at first using Fourier-Motzkin */
3166 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
3167 unsigned first, unsigned n)
3169 return isl_map_remove_dims(map, isl_dim_in, first, n);
3172 static void dump_term(struct isl_basic_map *bmap,
3173 isl_int c, int pos, FILE *out)
3175 const char *name;
3176 unsigned in = isl_basic_map_dim(bmap, isl_dim_in);
3177 unsigned dim = in + isl_basic_map_dim(bmap, isl_dim_out);
3178 unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
3179 if (!pos)
3180 isl_int_print(out, c, 0);
3181 else {
3182 if (!isl_int_is_one(c))
3183 isl_int_print(out, c, 0);
3184 if (pos < 1 + nparam) {
3185 name = isl_space_get_dim_name(bmap->dim,
3186 isl_dim_param, pos - 1);
3187 if (name)
3188 fprintf(out, "%s", name);
3189 else
3190 fprintf(out, "p%d", pos - 1);
3191 } else if (pos < 1 + nparam + in)
3192 fprintf(out, "i%d", pos - 1 - nparam);
3193 else if (pos < 1 + nparam + dim)
3194 fprintf(out, "o%d", pos - 1 - nparam - in);
3195 else
3196 fprintf(out, "e%d", pos - 1 - nparam - dim);
3200 static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
3201 int sign, FILE *out)
3203 int i;
3204 int first;
3205 unsigned len = 1 + isl_basic_map_total_dim(bmap);
3206 isl_int v;
3208 isl_int_init(v);
3209 for (i = 0, first = 1; i < len; ++i) {
3210 if (isl_int_sgn(c[i]) * sign <= 0)
3211 continue;
3212 if (!first)
3213 fprintf(out, " + ");
3214 first = 0;
3215 isl_int_abs(v, c[i]);
3216 dump_term(bmap, v, i, out);
3218 isl_int_clear(v);
3219 if (first)
3220 fprintf(out, "0");
3223 static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
3224 const char *op, FILE *out, int indent)
3226 int i;
3228 fprintf(out, "%*s", indent, "");
3230 dump_constraint_sign(bmap, c, 1, out);
3231 fprintf(out, " %s ", op);
3232 dump_constraint_sign(bmap, c, -1, out);
3234 fprintf(out, "\n");
3236 for (i = bmap->n_div; i < bmap->extra; ++i) {
3237 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
3238 continue;
3239 fprintf(out, "%*s", indent, "");
3240 fprintf(out, "ERROR: unused div coefficient not zero\n");
3241 abort();
3245 static void dump_constraints(struct isl_basic_map *bmap,
3246 isl_int **c, unsigned n,
3247 const char *op, FILE *out, int indent)
3249 int i;
3251 for (i = 0; i < n; ++i)
3252 dump_constraint(bmap, c[i], op, out, indent);
3255 static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
3257 int j;
3258 int first = 1;
3259 unsigned total = isl_basic_map_total_dim(bmap);
3261 for (j = 0; j < 1 + total; ++j) {
3262 if (isl_int_is_zero(exp[j]))
3263 continue;
3264 if (!first && isl_int_is_pos(exp[j]))
3265 fprintf(out, "+");
3266 dump_term(bmap, exp[j], j, out);
3267 first = 0;
3271 static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
3273 int i;
3275 dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
3276 dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
3278 for (i = 0; i < bmap->n_div; ++i) {
3279 fprintf(out, "%*s", indent, "");
3280 fprintf(out, "e%d = [(", i);
3281 dump_affine(bmap, bmap->div[i]+1, out);
3282 fprintf(out, ")/");
3283 isl_int_print(out, bmap->div[i][0], 0);
3284 fprintf(out, "]\n");
3288 void isl_basic_set_print_internal(struct isl_basic_set *bset,
3289 FILE *out, int indent)
3291 if (!bset) {
3292 fprintf(out, "null basic set\n");
3293 return;
3296 fprintf(out, "%*s", indent, "");
3297 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3298 bset->ref, bset->dim->nparam, bset->dim->n_out,
3299 bset->extra, bset->flags);
3300 dump(bset_to_bmap(bset), out, indent);
3303 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
3304 FILE *out, int indent)
3306 if (!bmap) {
3307 fprintf(out, "null basic map\n");
3308 return;
3311 fprintf(out, "%*s", indent, "");
3312 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3313 "flags: %x, n_name: %d\n",
3314 bmap->ref,
3315 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3316 bmap->extra, bmap->flags, bmap->dim->n_id);
3317 dump(bmap, out, indent);
3320 __isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3321 unsigned pos)
3323 unsigned total;
3325 if (!bmap)
3326 return NULL;
3327 total = isl_basic_map_total_dim(bmap);
3328 if (pos >= bmap->n_ineq)
3329 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3330 "invalid position", return isl_basic_map_free(bmap));
3331 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3332 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3333 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3334 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3335 return bmap;
3338 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3339 unsigned flags)
3341 if (isl_space_check_is_set(space) < 0)
3342 goto error;
3343 return isl_map_alloc_space(space, n, flags);
3344 error:
3345 isl_space_free(space);
3346 return NULL;
3349 /* Make sure "map" has room for at least "n" more basic maps.
3351 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3353 int i;
3354 struct isl_map *grown = NULL;
3356 if (!map)
3357 return NULL;
3358 isl_assert(map->ctx, n >= 0, goto error);
3359 if (map->n + n <= map->size)
3360 return map;
3361 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3362 if (!grown)
3363 goto error;
3364 for (i = 0; i < map->n; ++i) {
3365 grown->p[i] = isl_basic_map_copy(map->p[i]);
3366 if (!grown->p[i])
3367 goto error;
3368 grown->n++;
3370 isl_map_free(map);
3371 return grown;
3372 error:
3373 isl_map_free(grown);
3374 isl_map_free(map);
3375 return NULL;
3378 /* Make sure "set" has room for at least "n" more basic sets.
3380 struct isl_set *isl_set_grow(struct isl_set *set, int n)
3382 return set_from_map(isl_map_grow(set_to_map(set), n));
3385 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3387 return isl_map_from_basic_map(bset);
3390 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3392 struct isl_map *map;
3394 if (!bmap)
3395 return NULL;
3397 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3398 return isl_map_add_basic_map(map, bmap);
3401 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3402 __isl_take isl_basic_set *bset)
3404 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3405 bset_to_bmap(bset)));
3408 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3410 return isl_map_free(set);
3413 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3415 int i;
3417 if (!set) {
3418 fprintf(out, "null set\n");
3419 return;
3422 fprintf(out, "%*s", indent, "");
3423 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3424 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3425 set->flags);
3426 for (i = 0; i < set->n; ++i) {
3427 fprintf(out, "%*s", indent, "");
3428 fprintf(out, "basic set %d:\n", i);
3429 isl_basic_set_print_internal(set->p[i], out, indent+4);
3433 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3435 int i;
3437 if (!map) {
3438 fprintf(out, "null map\n");
3439 return;
3442 fprintf(out, "%*s", indent, "");
3443 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3444 "flags: %x, n_name: %d\n",
3445 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3446 map->dim->n_out, map->flags, map->dim->n_id);
3447 for (i = 0; i < map->n; ++i) {
3448 fprintf(out, "%*s", indent, "");
3449 fprintf(out, "basic map %d:\n", i);
3450 isl_basic_map_print_internal(map->p[i], out, indent+4);
3454 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3455 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3457 struct isl_basic_map *bmap_domain;
3459 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3460 goto error;
3462 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
3463 isl_assert(bset->ctx,
3464 isl_basic_map_compatible_domain(bmap, bset), goto error);
3466 bmap = isl_basic_map_cow(bmap);
3467 if (!bmap)
3468 goto error;
3469 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3470 bset->n_div, bset->n_eq, bset->n_ineq);
3471 bmap_domain = isl_basic_map_from_domain(bset);
3472 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3474 bmap = isl_basic_map_simplify(bmap);
3475 return isl_basic_map_finalize(bmap);
3476 error:
3477 isl_basic_map_free(bmap);
3478 isl_basic_set_free(bset);
3479 return NULL;
3482 /* Check that the space of "bset" is the same as that of the range of "bmap".
3484 static isl_stat isl_basic_map_check_compatible_range(
3485 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3487 isl_bool ok;
3489 ok = isl_basic_map_compatible_range(bmap, bset);
3490 if (ok < 0)
3491 return isl_stat_error;
3492 if (!ok)
3493 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3494 "incompatible spaces", return isl_stat_error);
3496 return isl_stat_ok;
3499 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3500 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3502 struct isl_basic_map *bmap_range;
3504 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3505 goto error;
3507 if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
3508 isl_basic_map_check_compatible_range(bmap, bset) < 0)
3509 goto error;
3511 if (isl_basic_set_plain_is_universe(bset)) {
3512 isl_basic_set_free(bset);
3513 return bmap;
3516 bmap = isl_basic_map_cow(bmap);
3517 if (!bmap)
3518 goto error;
3519 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3520 bset->n_div, bset->n_eq, bset->n_ineq);
3521 bmap_range = bset_to_bmap(bset);
3522 bmap = add_constraints(bmap, bmap_range, 0, 0);
3524 bmap = isl_basic_map_simplify(bmap);
3525 return isl_basic_map_finalize(bmap);
3526 error:
3527 isl_basic_map_free(bmap);
3528 isl_basic_set_free(bset);
3529 return NULL;
3532 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3533 __isl_keep isl_vec *vec)
3535 int i;
3536 unsigned total;
3537 isl_int s;
3539 if (!bmap || !vec)
3540 return isl_bool_error;
3542 total = 1 + isl_basic_map_total_dim(bmap);
3543 if (total != vec->size)
3544 return isl_bool_false;
3546 isl_int_init(s);
3548 for (i = 0; i < bmap->n_eq; ++i) {
3549 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3550 if (!isl_int_is_zero(s)) {
3551 isl_int_clear(s);
3552 return isl_bool_false;
3556 for (i = 0; i < bmap->n_ineq; ++i) {
3557 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3558 if (isl_int_is_neg(s)) {
3559 isl_int_clear(s);
3560 return isl_bool_false;
3564 isl_int_clear(s);
3566 return isl_bool_true;
3569 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3570 __isl_keep isl_vec *vec)
3572 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3575 __isl_give isl_basic_map *isl_basic_map_intersect(
3576 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3578 struct isl_vec *sample = NULL;
3580 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3581 goto error;
3582 if (isl_space_dim(bmap1->dim, isl_dim_all) ==
3583 isl_space_dim(bmap1->dim, isl_dim_param) &&
3584 isl_space_dim(bmap2->dim, isl_dim_all) !=
3585 isl_space_dim(bmap2->dim, isl_dim_param))
3586 return isl_basic_map_intersect(bmap2, bmap1);
3588 if (isl_space_dim(bmap2->dim, isl_dim_all) !=
3589 isl_space_dim(bmap2->dim, isl_dim_param))
3590 isl_assert(bmap1->ctx,
3591 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3593 if (isl_basic_map_plain_is_empty(bmap1)) {
3594 isl_basic_map_free(bmap2);
3595 return bmap1;
3597 if (isl_basic_map_plain_is_empty(bmap2)) {
3598 isl_basic_map_free(bmap1);
3599 return bmap2;
3602 if (bmap1->sample &&
3603 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3604 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3605 sample = isl_vec_copy(bmap1->sample);
3606 else if (bmap2->sample &&
3607 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3608 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3609 sample = isl_vec_copy(bmap2->sample);
3611 bmap1 = isl_basic_map_cow(bmap1);
3612 if (!bmap1)
3613 goto error;
3614 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3615 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3616 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3618 if (!bmap1)
3619 isl_vec_free(sample);
3620 else if (sample) {
3621 isl_vec_free(bmap1->sample);
3622 bmap1->sample = sample;
3625 bmap1 = isl_basic_map_simplify(bmap1);
3626 return isl_basic_map_finalize(bmap1);
3627 error:
3628 if (sample)
3629 isl_vec_free(sample);
3630 isl_basic_map_free(bmap1);
3631 isl_basic_map_free(bmap2);
3632 return NULL;
3635 struct isl_basic_set *isl_basic_set_intersect(
3636 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3638 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3639 bset_to_bmap(bset2)));
3642 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3643 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3645 return isl_basic_set_intersect(bset1, bset2);
3648 /* Special case of isl_map_intersect, where both map1 and map2
3649 * are convex, without any divs and such that either map1 or map2
3650 * contains a single constraint. This constraint is then simply
3651 * added to the other map.
3653 static __isl_give isl_map *map_intersect_add_constraint(
3654 __isl_take isl_map *map1, __isl_take isl_map *map2)
3656 isl_assert(map1->ctx, map1->n == 1, goto error);
3657 isl_assert(map2->ctx, map1->n == 1, goto error);
3658 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3659 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3661 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3662 return isl_map_intersect(map2, map1);
3664 map1 = isl_map_cow(map1);
3665 if (!map1)
3666 goto error;
3667 if (isl_map_plain_is_empty(map1)) {
3668 isl_map_free(map2);
3669 return map1;
3671 if (map2->p[0]->n_eq == 1)
3672 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3673 else
3674 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3675 map2->p[0]->ineq[0]);
3677 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3678 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3679 if (!map1->p[0])
3680 goto error;
3682 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3683 isl_basic_map_free(map1->p[0]);
3684 map1->n = 0;
3687 isl_map_free(map2);
3689 map1 = isl_map_unmark_normalized(map1);
3690 return map1;
3691 error:
3692 isl_map_free(map1);
3693 isl_map_free(map2);
3694 return NULL;
3697 /* map2 may be either a parameter domain or a map living in the same
3698 * space as map1.
3700 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3701 __isl_take isl_map *map2)
3703 unsigned flags = 0;
3704 isl_bool equal;
3705 isl_map *result;
3706 int i, j;
3708 if (!map1 || !map2)
3709 goto error;
3711 if ((isl_map_plain_is_empty(map1) ||
3712 isl_map_plain_is_universe(map2)) &&
3713 isl_space_is_equal(map1->dim, map2->dim)) {
3714 isl_map_free(map2);
3715 return map1;
3717 if ((isl_map_plain_is_empty(map2) ||
3718 isl_map_plain_is_universe(map1)) &&
3719 isl_space_is_equal(map1->dim, map2->dim)) {
3720 isl_map_free(map1);
3721 return map2;
3724 if (map1->n == 1 && map2->n == 1 &&
3725 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3726 isl_space_is_equal(map1->dim, map2->dim) &&
3727 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3728 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3729 return map_intersect_add_constraint(map1, map2);
3731 equal = isl_map_plain_is_equal(map1, map2);
3732 if (equal < 0)
3733 goto error;
3734 if (equal) {
3735 isl_map_free(map2);
3736 return map1;
3739 if (isl_space_dim(map2->dim, isl_dim_all) !=
3740 isl_space_dim(map2->dim, isl_dim_param))
3741 isl_assert(map1->ctx,
3742 isl_space_is_equal(map1->dim, map2->dim), goto error);
3744 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3745 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3746 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3748 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3749 map1->n * map2->n, flags);
3750 if (!result)
3751 goto error;
3752 for (i = 0; i < map1->n; ++i)
3753 for (j = 0; j < map2->n; ++j) {
3754 struct isl_basic_map *part;
3755 part = isl_basic_map_intersect(
3756 isl_basic_map_copy(map1->p[i]),
3757 isl_basic_map_copy(map2->p[j]));
3758 if (isl_basic_map_is_empty(part) < 0)
3759 part = isl_basic_map_free(part);
3760 result = isl_map_add_basic_map(result, part);
3761 if (!result)
3762 goto error;
3764 isl_map_free(map1);
3765 isl_map_free(map2);
3766 return result;
3767 error:
3768 isl_map_free(map1);
3769 isl_map_free(map2);
3770 return NULL;
3773 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3774 __isl_take isl_map *map2)
3776 if (!map1 || !map2)
3777 goto error;
3778 if (!isl_space_is_equal(map1->dim, map2->dim))
3779 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3780 "spaces don't match", goto error);
3781 return map_intersect_internal(map1, map2);
3782 error:
3783 isl_map_free(map1);
3784 isl_map_free(map2);
3785 return NULL;
3788 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3789 __isl_take isl_map *map2)
3791 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3794 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3796 return set_from_map(isl_map_intersect(set_to_map(set1),
3797 set_to_map(set2)));
3800 /* map_intersect_internal accepts intersections
3801 * with parameter domains, so we can just call that function.
3803 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3804 __isl_take isl_set *params)
3806 return map_intersect_internal(map, params);
3809 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3810 __isl_take isl_map *map2)
3812 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3815 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3816 __isl_take isl_set *params)
3818 return isl_map_intersect_params(set, params);
3821 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3823 isl_space *space;
3824 unsigned pos, n1, n2;
3826 if (!bmap)
3827 return NULL;
3828 bmap = isl_basic_map_cow(bmap);
3829 if (!bmap)
3830 return NULL;
3831 space = isl_space_reverse(isl_space_copy(bmap->dim));
3832 pos = isl_basic_map_offset(bmap, isl_dim_in);
3833 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3834 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3835 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3836 return isl_basic_map_reset_space(bmap, space);
3839 static __isl_give isl_basic_map *basic_map_space_reset(
3840 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3842 isl_space *space;
3844 if (!bmap)
3845 return NULL;
3846 if (!isl_space_is_named_or_nested(bmap->dim, type))
3847 return bmap;
3849 space = isl_basic_map_get_space(bmap);
3850 space = isl_space_reset(space, type);
3851 bmap = isl_basic_map_reset_space(bmap, space);
3852 return bmap;
3855 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3856 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3857 unsigned pos, unsigned n)
3859 isl_bool rational, is_empty;
3860 isl_space *res_space;
3861 struct isl_basic_map *res;
3862 struct isl_dim_map *dim_map;
3863 unsigned total, off;
3864 enum isl_dim_type t;
3866 if (n == 0)
3867 return basic_map_space_reset(bmap, type);
3869 is_empty = isl_basic_map_plain_is_empty(bmap);
3870 if (is_empty < 0)
3871 return isl_basic_map_free(bmap);
3872 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3873 type, pos, n);
3874 if (!res_space)
3875 return isl_basic_map_free(bmap);
3876 if (is_empty) {
3877 isl_basic_map_free(bmap);
3878 return isl_basic_map_empty(res_space);
3881 total = isl_basic_map_total_dim(bmap) + n;
3882 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3883 off = 0;
3884 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3885 if (t != type) {
3886 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3887 } else {
3888 unsigned size = isl_basic_map_dim(bmap, t);
3889 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3890 0, pos, off);
3891 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3892 pos, size - pos, off + pos + n);
3894 off += isl_space_dim(res_space, t);
3896 isl_dim_map_div(dim_map, bmap, off);
3898 res = isl_basic_map_alloc_space(res_space,
3899 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3900 rational = isl_basic_map_is_rational(bmap);
3901 if (rational < 0)
3902 res = isl_basic_map_free(res);
3903 if (rational)
3904 res = isl_basic_map_set_rational(res);
3905 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3906 return isl_basic_map_finalize(res);
3909 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3910 __isl_take isl_basic_set *bset,
3911 enum isl_dim_type type, unsigned pos, unsigned n)
3913 return isl_basic_map_insert_dims(bset, type, pos, n);
3916 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3917 enum isl_dim_type type, unsigned n)
3919 if (!bmap)
3920 return NULL;
3921 return isl_basic_map_insert_dims(bmap, type,
3922 isl_basic_map_dim(bmap, type), n);
3925 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3926 enum isl_dim_type type, unsigned n)
3928 if (!bset)
3929 return NULL;
3930 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3931 return isl_basic_map_add_dims(bset, type, n);
3932 error:
3933 isl_basic_set_free(bset);
3934 return NULL;
3937 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3938 enum isl_dim_type type)
3940 isl_space *space;
3942 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3943 return map;
3945 space = isl_map_get_space(map);
3946 space = isl_space_reset(space, type);
3947 map = isl_map_reset_space(map, space);
3948 return map;
3951 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3952 enum isl_dim_type type, unsigned pos, unsigned n)
3954 int i;
3956 if (n == 0)
3957 return map_space_reset(map, type);
3959 map = isl_map_cow(map);
3960 if (!map)
3961 return NULL;
3963 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3964 if (!map->dim)
3965 goto error;
3967 for (i = 0; i < map->n; ++i) {
3968 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3969 if (!map->p[i])
3970 goto error;
3973 return map;
3974 error:
3975 isl_map_free(map);
3976 return NULL;
3979 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3980 enum isl_dim_type type, unsigned pos, unsigned n)
3982 return isl_map_insert_dims(set, type, pos, n);
3985 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3986 enum isl_dim_type type, unsigned n)
3988 if (!map)
3989 return NULL;
3990 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3993 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3994 enum isl_dim_type type, unsigned n)
3996 if (!set)
3997 return NULL;
3998 isl_assert(set->ctx, type != isl_dim_in, goto error);
3999 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
4000 error:
4001 isl_set_free(set);
4002 return NULL;
4005 __isl_give isl_basic_map *isl_basic_map_move_dims(
4006 __isl_take isl_basic_map *bmap,
4007 enum isl_dim_type dst_type, unsigned dst_pos,
4008 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4010 struct isl_dim_map *dim_map;
4011 struct isl_basic_map *res;
4012 enum isl_dim_type t;
4013 unsigned total, off;
4015 if (!bmap)
4016 return NULL;
4017 if (n == 0) {
4018 bmap = isl_basic_map_reset(bmap, src_type);
4019 bmap = isl_basic_map_reset(bmap, dst_type);
4020 return bmap;
4023 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
4024 return isl_basic_map_free(bmap);
4026 if (dst_type == src_type && dst_pos == src_pos)
4027 return bmap;
4029 isl_assert(bmap->ctx, dst_type != src_type, goto error);
4031 if (pos(bmap->dim, dst_type) + dst_pos ==
4032 pos(bmap->dim, src_type) + src_pos +
4033 ((src_type < dst_type) ? n : 0)) {
4034 bmap = isl_basic_map_cow(bmap);
4035 if (!bmap)
4036 return NULL;
4038 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4039 src_type, src_pos, n);
4040 if (!bmap->dim)
4041 goto error;
4043 bmap = isl_basic_map_finalize(bmap);
4045 return bmap;
4048 total = isl_basic_map_total_dim(bmap);
4049 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4051 off = 0;
4052 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4053 unsigned size = isl_space_dim(bmap->dim, t);
4054 if (t == dst_type) {
4055 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4056 0, dst_pos, off);
4057 off += dst_pos;
4058 isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
4059 src_pos, n, off);
4060 off += n;
4061 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4062 dst_pos, size - dst_pos, off);
4063 off += size - dst_pos;
4064 } else if (t == src_type) {
4065 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4066 0, src_pos, off);
4067 off += src_pos;
4068 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4069 src_pos + n, size - src_pos - n, off);
4070 off += size - src_pos - n;
4071 } else {
4072 isl_dim_map_dim(dim_map, bmap->dim, t, off);
4073 off += size;
4076 isl_dim_map_div(dim_map, bmap, off);
4078 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4079 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4080 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4081 if (!bmap)
4082 goto error;
4084 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4085 src_type, src_pos, n);
4086 if (!bmap->dim)
4087 goto error;
4089 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4090 bmap = isl_basic_map_gauss(bmap, NULL);
4091 bmap = isl_basic_map_finalize(bmap);
4093 return bmap;
4094 error:
4095 isl_basic_map_free(bmap);
4096 return NULL;
4099 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4100 enum isl_dim_type dst_type, unsigned dst_pos,
4101 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4103 isl_basic_map *bmap = bset_to_bmap(bset);
4104 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4105 src_type, src_pos, n);
4106 return bset_from_bmap(bmap);
4109 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4110 enum isl_dim_type dst_type, unsigned dst_pos,
4111 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4113 if (!set)
4114 return NULL;
4115 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4116 return set_from_map(isl_map_move_dims(set_to_map(set),
4117 dst_type, dst_pos, src_type, src_pos, n));
4118 error:
4119 isl_set_free(set);
4120 return NULL;
4123 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4124 enum isl_dim_type dst_type, unsigned dst_pos,
4125 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4127 int i;
4129 if (n == 0) {
4130 map = isl_map_reset(map, src_type);
4131 map = isl_map_reset(map, dst_type);
4132 return map;
4135 if (isl_map_check_range(map, src_type, src_pos, n))
4136 return isl_map_free(map);
4138 if (dst_type == src_type && dst_pos == src_pos)
4139 return map;
4141 isl_assert(map->ctx, dst_type != src_type, goto error);
4143 map = isl_map_cow(map);
4144 if (!map)
4145 return NULL;
4147 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
4148 if (!map->dim)
4149 goto error;
4151 for (i = 0; i < map->n; ++i) {
4152 map->p[i] = isl_basic_map_move_dims(map->p[i],
4153 dst_type, dst_pos,
4154 src_type, src_pos, n);
4155 if (!map->p[i])
4156 goto error;
4159 return map;
4160 error:
4161 isl_map_free(map);
4162 return NULL;
4165 /* Move the specified dimensions to the last columns right before
4166 * the divs. Don't change the dimension specification of bmap.
4167 * That's the responsibility of the caller.
4169 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4170 enum isl_dim_type type, unsigned first, unsigned n)
4172 struct isl_dim_map *dim_map;
4173 struct isl_basic_map *res;
4174 enum isl_dim_type t;
4175 unsigned total, off;
4177 if (!bmap)
4178 return NULL;
4179 if (pos(bmap->dim, type) + first + n ==
4180 1 + isl_space_dim(bmap->dim, isl_dim_all))
4181 return bmap;
4183 total = isl_basic_map_total_dim(bmap);
4184 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4186 off = 0;
4187 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4188 unsigned size = isl_space_dim(bmap->dim, t);
4189 if (t == type) {
4190 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4191 0, first, off);
4192 off += first;
4193 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4194 first, n, total - bmap->n_div - n);
4195 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4196 first + n, size - (first + n), off);
4197 off += size - (first + n);
4198 } else {
4199 isl_dim_map_dim(dim_map, bmap->dim, t, off);
4200 off += size;
4203 isl_dim_map_div(dim_map, bmap, off + n);
4205 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4206 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4207 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4208 return res;
4211 /* Insert "n" rows in the divs of "bmap".
4213 * The number of columns is not changed, which means that the last
4214 * dimensions of "bmap" are being reintepreted as the new divs.
4215 * The space of "bmap" is not adjusted, however, which means
4216 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4217 * from the space of "bmap" is the responsibility of the caller.
4219 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4220 int n)
4222 int i;
4223 size_t row_size;
4224 isl_int **new_div;
4225 isl_int *old;
4227 bmap = isl_basic_map_cow(bmap);
4228 if (!bmap)
4229 return NULL;
4231 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
4232 old = bmap->block2.data;
4233 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4234 (bmap->extra + n) * (1 + row_size));
4235 if (!bmap->block2.data)
4236 return isl_basic_map_free(bmap);
4237 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4238 if (!new_div)
4239 return isl_basic_map_free(bmap);
4240 for (i = 0; i < n; ++i) {
4241 new_div[i] = bmap->block2.data +
4242 (bmap->extra + i) * (1 + row_size);
4243 isl_seq_clr(new_div[i], 1 + row_size);
4245 for (i = 0; i < bmap->extra; ++i)
4246 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4247 free(bmap->div);
4248 bmap->div = new_div;
4249 bmap->n_div += n;
4250 bmap->extra += n;
4252 return bmap;
4255 /* Drop constraints from "bmap" that only involve the variables
4256 * of "type" in the range [first, first + n] that are not related
4257 * to any of the variables outside that interval.
4258 * These constraints cannot influence the values for the variables
4259 * outside the interval, except in case they cause "bmap" to be empty.
4260 * Only drop the constraints if "bmap" is known to be non-empty.
4262 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4263 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4264 unsigned first, unsigned n)
4266 int i;
4267 int *groups;
4268 unsigned dim, n_div;
4269 isl_bool non_empty;
4271 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4272 if (non_empty < 0)
4273 return isl_basic_map_free(bmap);
4274 if (!non_empty)
4275 return bmap;
4277 dim = isl_basic_map_dim(bmap, isl_dim_all);
4278 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4279 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4280 if (!groups)
4281 return isl_basic_map_free(bmap);
4282 first += isl_basic_map_offset(bmap, type) - 1;
4283 for (i = 0; i < first; ++i)
4284 groups[i] = -1;
4285 for (i = first + n; i < dim - n_div; ++i)
4286 groups[i] = -1;
4288 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4290 return bmap;
4293 /* Turn the n dimensions of type type, starting at first
4294 * into existentially quantified variables.
4296 * If a subset of the projected out variables are unrelated
4297 * to any of the variables that remain, then the constraints
4298 * involving this subset are simply dropped first.
4300 __isl_give isl_basic_map *isl_basic_map_project_out(
4301 __isl_take isl_basic_map *bmap,
4302 enum isl_dim_type type, unsigned first, unsigned n)
4304 isl_bool empty;
4306 if (n == 0)
4307 return basic_map_space_reset(bmap, type);
4308 if (type == isl_dim_div)
4309 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4310 "cannot project out existentially quantified variables",
4311 return isl_basic_map_free(bmap));
4313 empty = isl_basic_map_plain_is_empty(bmap);
4314 if (empty < 0)
4315 return isl_basic_map_free(bmap);
4316 if (empty)
4317 bmap = isl_basic_map_set_to_empty(bmap);
4319 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4320 if (!bmap)
4321 return NULL;
4323 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4324 return isl_basic_map_remove_dims(bmap, type, first, n);
4326 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4327 return isl_basic_map_free(bmap);
4329 bmap = move_last(bmap, type, first, n);
4330 bmap = isl_basic_map_cow(bmap);
4331 bmap = insert_div_rows(bmap, n);
4332 if (!bmap)
4333 return NULL;
4335 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
4336 if (!bmap->dim)
4337 goto error;
4338 bmap = isl_basic_map_simplify(bmap);
4339 bmap = isl_basic_map_drop_redundant_divs(bmap);
4340 return isl_basic_map_finalize(bmap);
4341 error:
4342 isl_basic_map_free(bmap);
4343 return NULL;
4346 /* Turn the n dimensions of type type, starting at first
4347 * into existentially quantified variables.
4349 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
4350 enum isl_dim_type type, unsigned first, unsigned n)
4352 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4353 type, first, n));
4356 /* Turn the n dimensions of type type, starting at first
4357 * into existentially quantified variables.
4359 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4360 enum isl_dim_type type, unsigned first, unsigned n)
4362 int i;
4364 if (n == 0)
4365 return map_space_reset(map, type);
4367 if (isl_map_check_range(map, type, first, n) < 0)
4368 return isl_map_free(map);
4370 map = isl_map_cow(map);
4371 if (!map)
4372 return NULL;
4374 map->dim = isl_space_drop_dims(map->dim, type, first, n);
4375 if (!map->dim)
4376 goto error;
4378 for (i = 0; i < map->n; ++i) {
4379 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4380 if (!map->p[i])
4381 goto error;
4384 return map;
4385 error:
4386 isl_map_free(map);
4387 return NULL;
4390 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4391 * into existentially quantified variables.
4393 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4394 enum isl_dim_type type, unsigned first, unsigned n)
4396 unsigned dim;
4398 if (isl_map_check_range(map, type, first, n) < 0)
4399 return isl_map_free(map);
4400 dim = isl_map_dim(map, type);
4401 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4402 map = isl_map_project_out(map, type, 0, first);
4403 return map;
4406 /* Turn the n dimensions of type type, starting at first
4407 * into existentially quantified variables.
4409 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4410 enum isl_dim_type type, unsigned first, unsigned n)
4412 return set_from_map(isl_map_project_out(set_to_map(set),
4413 type, first, n));
4416 /* Return a map that projects the elements in "set" onto their
4417 * "n" set dimensions starting at "first".
4418 * "type" should be equal to isl_dim_set.
4420 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4421 enum isl_dim_type type, unsigned first, unsigned n)
4423 int i;
4424 isl_map *map;
4426 if (type != isl_dim_set)
4427 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4428 "only set dimensions can be projected out", goto error);
4429 if (isl_set_check_range(set, type, first, n) < 0)
4430 return isl_set_free(set);
4432 map = isl_map_from_domain(set);
4433 map = isl_map_add_dims(map, isl_dim_out, n);
4434 for (i = 0; i < n; ++i)
4435 map = isl_map_equate(map, isl_dim_in, first + i,
4436 isl_dim_out, i);
4437 return map;
4438 error:
4439 isl_set_free(set);
4440 return NULL;
4443 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4444 unsigned n)
4446 int i, j;
4448 for (i = 0; i < n; ++i) {
4449 j = isl_basic_map_alloc_div(bmap);
4450 if (j < 0)
4451 goto error;
4452 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4454 return bmap;
4455 error:
4456 isl_basic_map_free(bmap);
4457 return NULL;
4460 struct isl_basic_map *isl_basic_map_apply_range(
4461 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4463 isl_space *space_result = NULL;
4464 struct isl_basic_map *bmap;
4465 unsigned n_in, n_out, n, nparam, total, pos;
4466 struct isl_dim_map *dim_map1, *dim_map2;
4468 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4469 goto error;
4470 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4471 bmap2->dim, isl_dim_in))
4472 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4473 "spaces don't match", goto error);
4475 space_result = isl_space_join(isl_space_copy(bmap1->dim),
4476 isl_space_copy(bmap2->dim));
4478 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4479 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4480 n = isl_basic_map_dim(bmap1, isl_dim_out);
4481 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4483 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4484 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4485 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4486 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4487 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4488 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4489 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4490 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4491 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4492 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4493 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4495 bmap = isl_basic_map_alloc_space(space_result,
4496 bmap1->n_div + bmap2->n_div + n,
4497 bmap1->n_eq + bmap2->n_eq,
4498 bmap1->n_ineq + bmap2->n_ineq);
4499 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4500 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4501 bmap = add_divs(bmap, n);
4502 bmap = isl_basic_map_simplify(bmap);
4503 bmap = isl_basic_map_drop_redundant_divs(bmap);
4504 return isl_basic_map_finalize(bmap);
4505 error:
4506 isl_basic_map_free(bmap1);
4507 isl_basic_map_free(bmap2);
4508 return NULL;
4511 struct isl_basic_set *isl_basic_set_apply(
4512 struct isl_basic_set *bset, struct isl_basic_map *bmap)
4514 if (!bset || !bmap)
4515 goto error;
4517 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4518 goto error);
4520 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4521 bmap));
4522 error:
4523 isl_basic_set_free(bset);
4524 isl_basic_map_free(bmap);
4525 return NULL;
4528 struct isl_basic_map *isl_basic_map_apply_domain(
4529 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4531 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4532 goto error;
4533 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4534 bmap2->dim, isl_dim_in))
4535 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4536 "spaces don't match", goto error);
4538 bmap1 = isl_basic_map_reverse(bmap1);
4539 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4540 return isl_basic_map_reverse(bmap1);
4541 error:
4542 isl_basic_map_free(bmap1);
4543 isl_basic_map_free(bmap2);
4544 return NULL;
4547 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4548 * A \cap B -> f(A) + f(B)
4550 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4551 __isl_take isl_basic_map *bmap2)
4553 unsigned n_in, n_out, nparam, total, pos;
4554 struct isl_basic_map *bmap = NULL;
4555 struct isl_dim_map *dim_map1, *dim_map2;
4556 int i;
4558 if (!bmap1 || !bmap2)
4559 goto error;
4561 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4562 goto error);
4564 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4565 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4566 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4568 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4569 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4570 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4571 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4572 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4573 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4574 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4575 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4576 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4577 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4578 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4580 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4581 bmap1->n_div + bmap2->n_div + 2 * n_out,
4582 bmap1->n_eq + bmap2->n_eq + n_out,
4583 bmap1->n_ineq + bmap2->n_ineq);
4584 for (i = 0; i < n_out; ++i) {
4585 int j = isl_basic_map_alloc_equality(bmap);
4586 if (j < 0)
4587 goto error;
4588 isl_seq_clr(bmap->eq[j], 1+total);
4589 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4590 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4591 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4593 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4594 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4595 bmap = add_divs(bmap, 2 * n_out);
4597 bmap = isl_basic_map_simplify(bmap);
4598 return isl_basic_map_finalize(bmap);
4599 error:
4600 isl_basic_map_free(bmap);
4601 isl_basic_map_free(bmap1);
4602 isl_basic_map_free(bmap2);
4603 return NULL;
4606 /* Given two maps A -> f(A) and B -> g(B), construct a map
4607 * A \cap B -> f(A) + f(B)
4609 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4610 __isl_take isl_map *map2)
4612 struct isl_map *result;
4613 int i, j;
4615 if (!map1 || !map2)
4616 goto error;
4618 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4620 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4621 map1->n * map2->n, 0);
4622 if (!result)
4623 goto error;
4624 for (i = 0; i < map1->n; ++i)
4625 for (j = 0; j < map2->n; ++j) {
4626 struct isl_basic_map *part;
4627 part = isl_basic_map_sum(
4628 isl_basic_map_copy(map1->p[i]),
4629 isl_basic_map_copy(map2->p[j]));
4630 if (isl_basic_map_is_empty(part))
4631 isl_basic_map_free(part);
4632 else
4633 result = isl_map_add_basic_map(result, part);
4634 if (!result)
4635 goto error;
4637 isl_map_free(map1);
4638 isl_map_free(map2);
4639 return result;
4640 error:
4641 isl_map_free(map1);
4642 isl_map_free(map2);
4643 return NULL;
4646 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4647 __isl_take isl_set *set2)
4649 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4652 /* Given a basic map A -> f(A), construct A -> -f(A).
4654 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4656 int i, j;
4657 unsigned off, n;
4659 bmap = isl_basic_map_cow(bmap);
4660 if (!bmap)
4661 return NULL;
4663 n = isl_basic_map_dim(bmap, isl_dim_out);
4664 off = isl_basic_map_offset(bmap, isl_dim_out);
4665 for (i = 0; i < bmap->n_eq; ++i)
4666 for (j = 0; j < n; ++j)
4667 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4668 for (i = 0; i < bmap->n_ineq; ++i)
4669 for (j = 0; j < n; ++j)
4670 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4671 for (i = 0; i < bmap->n_div; ++i)
4672 for (j = 0; j < n; ++j)
4673 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4674 bmap = isl_basic_map_gauss(bmap, NULL);
4675 return isl_basic_map_finalize(bmap);
4678 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4680 return isl_basic_map_neg(bset);
4683 /* Given a map A -> f(A), construct A -> -f(A).
4685 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4687 int i;
4689 map = isl_map_cow(map);
4690 if (!map)
4691 return NULL;
4693 for (i = 0; i < map->n; ++i) {
4694 map->p[i] = isl_basic_map_neg(map->p[i]);
4695 if (!map->p[i])
4696 goto error;
4699 return map;
4700 error:
4701 isl_map_free(map);
4702 return NULL;
4705 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4707 return set_from_map(isl_map_neg(set_to_map(set)));
4710 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4711 * A -> floor(f(A)/d).
4713 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4714 isl_int d)
4716 unsigned n_in, n_out, nparam, total, pos;
4717 struct isl_basic_map *result = NULL;
4718 struct isl_dim_map *dim_map;
4719 int i;
4721 if (!bmap)
4722 return NULL;
4724 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4725 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4726 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4728 total = nparam + n_in + n_out + bmap->n_div + n_out;
4729 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4730 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4731 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4732 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4733 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4735 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4736 bmap->n_div + n_out,
4737 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4738 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4739 result = add_divs(result, n_out);
4740 for (i = 0; i < n_out; ++i) {
4741 int j;
4742 j = isl_basic_map_alloc_inequality(result);
4743 if (j < 0)
4744 goto error;
4745 isl_seq_clr(result->ineq[j], 1+total);
4746 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4747 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4748 j = isl_basic_map_alloc_inequality(result);
4749 if (j < 0)
4750 goto error;
4751 isl_seq_clr(result->ineq[j], 1+total);
4752 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4753 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4754 isl_int_sub_ui(result->ineq[j][0], d, 1);
4757 result = isl_basic_map_simplify(result);
4758 return isl_basic_map_finalize(result);
4759 error:
4760 isl_basic_map_free(result);
4761 return NULL;
4764 /* Given a map A -> f(A) and an integer d, construct a map
4765 * A -> floor(f(A)/d).
4767 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4769 int i;
4771 map = isl_map_cow(map);
4772 if (!map)
4773 return NULL;
4775 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4776 for (i = 0; i < map->n; ++i) {
4777 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4778 if (!map->p[i])
4779 goto error;
4781 map = isl_map_unmark_normalized(map);
4783 return map;
4784 error:
4785 isl_map_free(map);
4786 return NULL;
4789 /* Given a map A -> f(A) and an integer d, construct a map
4790 * A -> floor(f(A)/d).
4792 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4793 __isl_take isl_val *d)
4795 if (!map || !d)
4796 goto error;
4797 if (!isl_val_is_int(d))
4798 isl_die(isl_val_get_ctx(d), isl_error_invalid,
4799 "expecting integer denominator", goto error);
4800 map = isl_map_floordiv(map, d->n);
4801 isl_val_free(d);
4802 return map;
4803 error:
4804 isl_map_free(map);
4805 isl_val_free(d);
4806 return NULL;
4809 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
4810 unsigned pos)
4812 int i;
4813 unsigned nparam;
4814 unsigned n_in;
4816 i = isl_basic_map_alloc_equality(bmap);
4817 if (i < 0)
4818 goto error;
4819 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4820 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4821 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4822 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4823 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4824 return isl_basic_map_finalize(bmap);
4825 error:
4826 isl_basic_map_free(bmap);
4827 return NULL;
4830 /* Add a constraint to "bmap" expressing i_pos < o_pos
4832 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
4833 unsigned pos)
4835 int i;
4836 unsigned nparam;
4837 unsigned n_in;
4839 i = isl_basic_map_alloc_inequality(bmap);
4840 if (i < 0)
4841 goto error;
4842 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4843 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4844 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4845 isl_int_set_si(bmap->ineq[i][0], -1);
4846 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4847 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4848 return isl_basic_map_finalize(bmap);
4849 error:
4850 isl_basic_map_free(bmap);
4851 return NULL;
4854 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4856 static __isl_give isl_basic_map *var_less_or_equal(
4857 __isl_take isl_basic_map *bmap, unsigned pos)
4859 int i;
4860 unsigned nparam;
4861 unsigned n_in;
4863 i = isl_basic_map_alloc_inequality(bmap);
4864 if (i < 0)
4865 goto error;
4866 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4867 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4868 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4869 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4870 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4871 return isl_basic_map_finalize(bmap);
4872 error:
4873 isl_basic_map_free(bmap);
4874 return NULL;
4877 /* Add a constraint to "bmap" expressing i_pos > o_pos
4879 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
4880 unsigned pos)
4882 int i;
4883 unsigned nparam;
4884 unsigned n_in;
4886 i = isl_basic_map_alloc_inequality(bmap);
4887 if (i < 0)
4888 goto error;
4889 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4890 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4891 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4892 isl_int_set_si(bmap->ineq[i][0], -1);
4893 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4894 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4895 return isl_basic_map_finalize(bmap);
4896 error:
4897 isl_basic_map_free(bmap);
4898 return NULL;
4901 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4903 static __isl_give isl_basic_map *var_more_or_equal(
4904 __isl_take isl_basic_map *bmap, unsigned pos)
4906 int i;
4907 unsigned nparam;
4908 unsigned n_in;
4910 i = isl_basic_map_alloc_inequality(bmap);
4911 if (i < 0)
4912 goto error;
4913 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4914 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4915 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4916 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4917 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4918 return isl_basic_map_finalize(bmap);
4919 error:
4920 isl_basic_map_free(bmap);
4921 return NULL;
4924 __isl_give isl_basic_map *isl_basic_map_equal(
4925 __isl_take isl_space *space, unsigned n_equal)
4927 int i;
4928 struct isl_basic_map *bmap;
4929 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
4930 if (!bmap)
4931 return NULL;
4932 for (i = 0; i < n_equal && bmap; ++i)
4933 bmap = var_equal(bmap, i);
4934 return isl_basic_map_finalize(bmap);
4937 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
4939 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
4940 unsigned pos)
4942 int i;
4943 struct isl_basic_map *bmap;
4944 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4945 if (!bmap)
4946 return NULL;
4947 for (i = 0; i < pos && bmap; ++i)
4948 bmap = var_equal(bmap, i);
4949 if (bmap)
4950 bmap = var_less(bmap, pos);
4951 return isl_basic_map_finalize(bmap);
4954 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
4956 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4957 __isl_take isl_space *space, unsigned pos)
4959 int i;
4960 isl_basic_map *bmap;
4962 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4963 for (i = 0; i < pos; ++i)
4964 bmap = var_equal(bmap, i);
4965 bmap = var_less_or_equal(bmap, pos);
4966 return isl_basic_map_finalize(bmap);
4969 /* Return a relation on "space" expressing i_pos > o_pos
4971 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
4972 unsigned pos)
4974 int i;
4975 struct isl_basic_map *bmap;
4976 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4977 if (!bmap)
4978 return NULL;
4979 for (i = 0; i < pos && bmap; ++i)
4980 bmap = var_equal(bmap, i);
4981 if (bmap)
4982 bmap = var_more(bmap, pos);
4983 return isl_basic_map_finalize(bmap);
4986 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
4988 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4989 __isl_take isl_space *space, unsigned pos)
4991 int i;
4992 isl_basic_map *bmap;
4994 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4995 for (i = 0; i < pos; ++i)
4996 bmap = var_equal(bmap, i);
4997 bmap = var_more_or_equal(bmap, pos);
4998 return isl_basic_map_finalize(bmap);
5001 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
5002 unsigned n, int equal)
5004 struct isl_map *map;
5005 int i;
5007 if (n == 0 && equal)
5008 return isl_map_universe(space);
5010 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5012 for (i = 0; i + 1 < n; ++i)
5013 map = isl_map_add_basic_map(map,
5014 isl_basic_map_less_at(isl_space_copy(space), i));
5015 if (n > 0) {
5016 if (equal)
5017 map = isl_map_add_basic_map(map,
5018 isl_basic_map_less_or_equal_at(space, n - 1));
5019 else
5020 map = isl_map_add_basic_map(map,
5021 isl_basic_map_less_at(space, n - 1));
5022 } else
5023 isl_space_free(space);
5025 return map;
5028 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
5030 if (!space)
5031 return NULL;
5032 return map_lex_lte_first(space, space->n_out, equal);
5035 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
5037 return map_lex_lte_first(dim, n, 0);
5040 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
5042 return map_lex_lte_first(dim, n, 1);
5045 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
5047 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
5050 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
5052 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
5055 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5056 unsigned n, int equal)
5058 struct isl_map *map;
5059 int i;
5061 if (n == 0 && equal)
5062 return isl_map_universe(space);
5064 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5066 for (i = 0; i + 1 < n; ++i)
5067 map = isl_map_add_basic_map(map,
5068 isl_basic_map_more_at(isl_space_copy(space), i));
5069 if (n > 0) {
5070 if (equal)
5071 map = isl_map_add_basic_map(map,
5072 isl_basic_map_more_or_equal_at(space, n - 1));
5073 else
5074 map = isl_map_add_basic_map(map,
5075 isl_basic_map_more_at(space, n - 1));
5076 } else
5077 isl_space_free(space);
5079 return map;
5082 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5084 if (!space)
5085 return NULL;
5086 return map_lex_gte_first(space, space->n_out, equal);
5089 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
5091 return map_lex_gte_first(dim, n, 0);
5094 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
5096 return map_lex_gte_first(dim, n, 1);
5099 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
5101 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
5104 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
5106 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
5109 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5110 __isl_take isl_set *set2)
5112 isl_map *map;
5113 map = isl_map_lex_le(isl_set_get_space(set1));
5114 map = isl_map_intersect_domain(map, set1);
5115 map = isl_map_intersect_range(map, set2);
5116 return map;
5119 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5120 __isl_take isl_set *set2)
5122 isl_map *map;
5123 map = isl_map_lex_lt(isl_set_get_space(set1));
5124 map = isl_map_intersect_domain(map, set1);
5125 map = isl_map_intersect_range(map, set2);
5126 return map;
5129 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5130 __isl_take isl_set *set2)
5132 isl_map *map;
5133 map = isl_map_lex_ge(isl_set_get_space(set1));
5134 map = isl_map_intersect_domain(map, set1);
5135 map = isl_map_intersect_range(map, set2);
5136 return map;
5139 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5140 __isl_take isl_set *set2)
5142 isl_map *map;
5143 map = isl_map_lex_gt(isl_set_get_space(set1));
5144 map = isl_map_intersect_domain(map, set1);
5145 map = isl_map_intersect_range(map, set2);
5146 return map;
5149 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5150 __isl_take isl_map *map2)
5152 isl_map *map;
5153 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5154 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5155 map = isl_map_apply_range(map, isl_map_reverse(map2));
5156 return map;
5159 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5160 __isl_take isl_map *map2)
5162 isl_map *map;
5163 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5164 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5165 map = isl_map_apply_range(map, isl_map_reverse(map2));
5166 return map;
5169 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5170 __isl_take isl_map *map2)
5172 isl_map *map;
5173 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5174 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5175 map = isl_map_apply_range(map, isl_map_reverse(map2));
5176 return map;
5179 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5180 __isl_take isl_map *map2)
5182 isl_map *map;
5183 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5184 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5185 map = isl_map_apply_range(map, isl_map_reverse(map2));
5186 return map;
5189 /* For the div d = floor(f/m) at position "div", add the constraint
5191 * f - m d >= 0
5193 static __isl_give isl_basic_map *add_upper_div_constraint(
5194 __isl_take isl_basic_map *bmap, unsigned div)
5196 int i;
5197 int v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5198 unsigned n_div, pos;
5200 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5201 if (v_div < 0)
5202 return isl_basic_map_free(bmap);
5203 pos = v_div + div;
5204 i = isl_basic_map_alloc_inequality(bmap);
5205 if (i < 0)
5206 return isl_basic_map_free(bmap);
5207 isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5208 isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5210 return bmap;
5213 /* For the div d = floor(f/m) at position "div", add the constraint
5215 * -(f-(m-1)) + m d >= 0
5217 static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
5218 unsigned div)
5220 int i;
5221 int v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5222 unsigned n_div, pos;
5224 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5225 if (v_div < 0)
5226 return isl_stat_error;
5227 pos = v_div + div;
5228 i = isl_basic_map_alloc_inequality(bmap);
5229 if (i < 0)
5230 return isl_stat_error;
5231 isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5232 isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5233 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5234 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5236 return isl_stat_ok;
5239 /* For the div d = floor(f/m) at position "pos", add the constraints
5241 * f - m d >= 0
5242 * -(f-(m-1)) + m d >= 0
5244 * Note that the second constraint is the negation of
5246 * f - m d >= m
5248 __isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5249 __isl_take isl_basic_map *bmap, unsigned pos)
5251 bmap = add_upper_div_constraint(bmap, pos);
5252 if (add_lower_div_constraint(bmap, pos) < 0)
5253 return isl_basic_map_free(bmap);
5254 return bmap;
5257 /* For each known div d = floor(f/m), add the constraints
5259 * f - m d >= 0
5260 * -(f-(m-1)) + m d >= 0
5262 * Remove duplicate constraints in case of some these div constraints
5263 * already appear in "bmap".
5265 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5266 __isl_take isl_basic_map *bmap)
5268 unsigned n_div;
5270 if (!bmap)
5271 return NULL;
5272 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5273 if (n_div == 0)
5274 return bmap;
5276 bmap = add_known_div_constraints(bmap);
5277 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5278 bmap = isl_basic_map_finalize(bmap);
5279 return bmap;
5282 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5284 * In particular, if this div is of the form d = floor(f/m),
5285 * then add the constraint
5287 * f - m d >= 0
5289 * if sign < 0 or the constraint
5291 * -(f-(m-1)) + m d >= 0
5293 * if sign > 0.
5295 __isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5296 __isl_take isl_basic_map *bmap, unsigned div, int sign)
5298 isl_stat r;
5300 if (sign < 0)
5301 return add_upper_div_constraint(bmap, div);
5302 else
5303 r = add_lower_div_constraint(bmap, div);
5305 if (r < 0)
5306 return isl_basic_map_free(bmap);
5307 return bmap;
5310 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5311 __isl_take isl_basic_map *bmap)
5313 if (!bmap)
5314 goto error;
5315 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5316 bmap->n_div == 0 &&
5317 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5318 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5319 return bset_from_bmap(bmap);
5320 bmap = isl_basic_map_cow(bmap);
5321 if (!bmap)
5322 goto error;
5323 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
5324 if (!bmap->dim)
5325 goto error;
5326 bmap->extra -= bmap->n_div;
5327 bmap->n_div = 0;
5328 bmap = isl_basic_map_finalize(bmap);
5329 return bset_from_bmap(bmap);
5330 error:
5331 isl_basic_map_free(bmap);
5332 return NULL;
5335 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5336 __isl_take isl_basic_set *bset)
5338 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5341 /* Replace each element in "list" by the result of applying
5342 * isl_basic_map_underlying_set to the element.
5344 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5345 __isl_take isl_basic_map_list *list)
5347 int i, n;
5349 if (!list)
5350 return NULL;
5352 n = isl_basic_map_list_n_basic_map(list);
5353 for (i = 0; i < n; ++i) {
5354 isl_basic_map *bmap;
5355 isl_basic_set *bset;
5357 bmap = isl_basic_map_list_get_basic_map(list, i);
5358 bset = isl_basic_set_underlying_set(bmap);
5359 list = isl_basic_set_list_set_basic_set(list, i, bset);
5362 return list;
5365 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5366 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5368 struct isl_basic_map *bmap;
5369 struct isl_ctx *ctx;
5370 unsigned total;
5371 int i;
5373 if (!bset || !like)
5374 goto error;
5375 ctx = bset->ctx;
5376 if (isl_basic_set_check_no_params(bset) < 0 ||
5377 isl_basic_set_check_no_locals(bset) < 0)
5378 goto error;
5379 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
5380 goto error);
5381 if (like->n_div == 0) {
5382 isl_space *space = isl_basic_map_get_space(like);
5383 isl_basic_map_free(like);
5384 return isl_basic_map_reset_space(bset, space);
5386 bset = isl_basic_set_cow(bset);
5387 if (!bset)
5388 goto error;
5389 total = bset->dim->n_out + bset->extra;
5390 bmap = bset_to_bmap(bset);
5391 isl_space_free(bmap->dim);
5392 bmap->dim = isl_space_copy(like->dim);
5393 if (!bmap->dim)
5394 goto error;
5395 bmap->n_div = like->n_div;
5396 bmap->extra += like->n_div;
5397 if (bmap->extra) {
5398 unsigned ltotal;
5399 isl_int **div;
5400 ltotal = total - bmap->extra + like->extra;
5401 if (ltotal > total)
5402 ltotal = total;
5403 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5404 bmap->extra * (1 + 1 + total));
5405 if (isl_blk_is_error(bmap->block2))
5406 goto error;
5407 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5408 if (!div)
5409 goto error;
5410 bmap->div = div;
5411 for (i = 0; i < bmap->extra; ++i)
5412 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5413 for (i = 0; i < like->n_div; ++i) {
5414 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5415 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5417 bmap = isl_basic_map_add_known_div_constraints(bmap);
5419 isl_basic_map_free(like);
5420 bmap = isl_basic_map_simplify(bmap);
5421 bmap = isl_basic_map_finalize(bmap);
5422 return bmap;
5423 error:
5424 isl_basic_map_free(like);
5425 isl_basic_set_free(bset);
5426 return NULL;
5429 struct isl_basic_set *isl_basic_set_from_underlying_set(
5430 struct isl_basic_set *bset, struct isl_basic_set *like)
5432 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5433 bset_to_bmap(like)));
5436 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5438 int i;
5440 map = isl_map_cow(map);
5441 if (!map)
5442 return NULL;
5443 map->dim = isl_space_cow(map->dim);
5444 if (!map->dim)
5445 goto error;
5447 for (i = 1; i < map->n; ++i)
5448 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5449 goto error);
5450 for (i = 0; i < map->n; ++i) {
5451 map->p[i] = bset_to_bmap(
5452 isl_basic_map_underlying_set(map->p[i]));
5453 if (!map->p[i])
5454 goto error;
5456 if (map->n == 0)
5457 map->dim = isl_space_underlying(map->dim, 0);
5458 else {
5459 isl_space_free(map->dim);
5460 map->dim = isl_space_copy(map->p[0]->dim);
5462 if (!map->dim)
5463 goto error;
5464 return set_from_map(map);
5465 error:
5466 isl_map_free(map);
5467 return NULL;
5470 /* Replace the space of "bmap" by "space".
5472 * If the space of "bmap" is identical to "space" (including the identifiers
5473 * of the input and output dimensions), then simply return the original input.
5475 __isl_give isl_basic_map *isl_basic_map_reset_space(
5476 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5478 isl_bool equal;
5479 isl_space *bmap_space;
5481 bmap_space = isl_basic_map_peek_space(bmap);
5482 equal = isl_space_is_equal(bmap_space, space);
5483 if (equal >= 0 && equal)
5484 equal = isl_space_has_equal_ids(bmap_space, space);
5485 if (equal < 0)
5486 goto error;
5487 if (equal) {
5488 isl_space_free(space);
5489 return bmap;
5491 bmap = isl_basic_map_cow(bmap);
5492 if (!bmap || !space)
5493 goto error;
5495 isl_space_free(bmap->dim);
5496 bmap->dim = space;
5498 bmap = isl_basic_map_finalize(bmap);
5500 return bmap;
5501 error:
5502 isl_basic_map_free(bmap);
5503 isl_space_free(space);
5504 return NULL;
5507 __isl_give isl_basic_set *isl_basic_set_reset_space(
5508 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5510 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5511 dim));
5514 /* Check that the total dimensions of "map" and "space" are the same.
5516 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5517 __isl_keep isl_space *space)
5519 unsigned dim1, dim2;
5521 if (!map || !space)
5522 return isl_stat_error;
5523 dim1 = isl_map_dim(map, isl_dim_all);
5524 dim2 = isl_space_dim(space, isl_dim_all);
5525 if (dim1 == dim2)
5526 return isl_stat_ok;
5527 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5528 "total dimensions do not match", return isl_stat_error);
5531 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5532 __isl_take isl_space *space)
5534 int i;
5536 map = isl_map_cow(map);
5537 if (!map || !space)
5538 goto error;
5540 for (i = 0; i < map->n; ++i) {
5541 map->p[i] = isl_basic_map_reset_space(map->p[i],
5542 isl_space_copy(space));
5543 if (!map->p[i])
5544 goto error;
5546 isl_space_free(map->dim);
5547 map->dim = space;
5549 return map;
5550 error:
5551 isl_map_free(map);
5552 isl_space_free(space);
5553 return NULL;
5556 /* Replace the space of "map" by "space", without modifying
5557 * the dimension of "map".
5559 * If the space of "map" is identical to "space" (including the identifiers
5560 * of the input and output dimensions), then simply return the original input.
5562 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5563 __isl_take isl_space *space)
5565 isl_bool equal;
5566 isl_space *map_space;
5568 map_space = isl_map_peek_space(map);
5569 equal = isl_space_is_equal(map_space, space);
5570 if (equal >= 0 && equal)
5571 equal = isl_space_has_equal_ids(map_space, space);
5572 if (equal < 0)
5573 goto error;
5574 if (equal) {
5575 isl_space_free(space);
5576 return map;
5578 if (check_map_space_equal_total_dim(map, space) < 0)
5579 goto error;
5580 return isl_map_reset_space(map, space);
5581 error:
5582 isl_map_free(map);
5583 isl_space_free(space);
5584 return NULL;
5587 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5588 __isl_take isl_space *dim)
5590 return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5593 /* Compute the parameter domain of the given basic set.
5595 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5597 isl_bool is_params;
5598 isl_space *space;
5599 unsigned n;
5601 is_params = isl_basic_set_is_params(bset);
5602 if (is_params < 0)
5603 return isl_basic_set_free(bset);
5604 if (is_params)
5605 return bset;
5607 n = isl_basic_set_dim(bset, isl_dim_set);
5608 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5609 space = isl_basic_set_get_space(bset);
5610 space = isl_space_params(space);
5611 bset = isl_basic_set_reset_space(bset, space);
5612 return bset;
5615 /* Construct a zero-dimensional basic set with the given parameter domain.
5617 __isl_give isl_basic_set *isl_basic_set_from_params(
5618 __isl_take isl_basic_set *bset)
5620 isl_space *space;
5621 space = isl_basic_set_get_space(bset);
5622 space = isl_space_set_from_params(space);
5623 bset = isl_basic_set_reset_space(bset, space);
5624 return bset;
5627 /* Compute the parameter domain of the given set.
5629 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5631 isl_space *space;
5632 unsigned n;
5634 if (isl_set_is_params(set))
5635 return set;
5637 n = isl_set_dim(set, isl_dim_set);
5638 set = isl_set_project_out(set, isl_dim_set, 0, n);
5639 space = isl_set_get_space(set);
5640 space = isl_space_params(space);
5641 set = isl_set_reset_space(set, space);
5642 return set;
5645 /* Construct a zero-dimensional set with the given parameter domain.
5647 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5649 isl_space *space;
5650 space = isl_set_get_space(set);
5651 space = isl_space_set_from_params(space);
5652 set = isl_set_reset_space(set, space);
5653 return set;
5656 /* Compute the parameter domain of the given map.
5658 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5660 isl_space *space;
5661 unsigned n;
5663 n = isl_map_dim(map, isl_dim_in);
5664 map = isl_map_project_out(map, isl_dim_in, 0, n);
5665 n = isl_map_dim(map, isl_dim_out);
5666 map = isl_map_project_out(map, isl_dim_out, 0, n);
5667 space = isl_map_get_space(map);
5668 space = isl_space_params(space);
5669 map = isl_map_reset_space(map, space);
5670 return map;
5673 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5675 isl_space *space;
5676 unsigned n_out;
5678 if (!bmap)
5679 return NULL;
5680 space = isl_space_domain(isl_basic_map_get_space(bmap));
5682 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5683 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5685 return isl_basic_map_reset_space(bmap, space);
5688 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5690 if (!bmap)
5691 return isl_bool_error;
5692 return isl_space_may_be_set(bmap->dim);
5695 /* Is this basic map actually a set?
5696 * Users should never call this function. Outside of isl,
5697 * the type should indicate whether something is a set or a map.
5699 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5701 if (!bmap)
5702 return isl_bool_error;
5703 return isl_space_is_set(bmap->dim);
5706 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5708 isl_bool is_set;
5710 is_set = isl_basic_map_is_set(bmap);
5711 if (is_set < 0)
5712 goto error;
5713 if (is_set)
5714 return bmap;
5715 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5716 error:
5717 isl_basic_map_free(bmap);
5718 return NULL;
5721 __isl_give isl_basic_map *isl_basic_map_domain_map(
5722 __isl_take isl_basic_map *bmap)
5724 int i;
5725 isl_space *space;
5726 isl_basic_map *domain;
5727 int nparam, n_in, n_out;
5729 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5730 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5731 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5733 space = isl_basic_map_get_space(bmap);
5734 space = isl_space_from_range(isl_space_domain(space));
5735 domain = isl_basic_map_universe(space);
5737 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5738 bmap = isl_basic_map_apply_range(bmap, domain);
5739 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5741 for (i = 0; i < n_in; ++i)
5742 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5743 isl_dim_out, i);
5745 bmap = isl_basic_map_gauss(bmap, NULL);
5746 return isl_basic_map_finalize(bmap);
5749 __isl_give isl_basic_map *isl_basic_map_range_map(
5750 __isl_take isl_basic_map *bmap)
5752 int i;
5753 isl_space *space;
5754 isl_basic_map *range;
5755 int nparam, n_in, n_out;
5757 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5758 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5759 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5761 space = isl_basic_map_get_space(bmap);
5762 space = isl_space_from_range(isl_space_range(space));
5763 range = isl_basic_map_universe(space);
5765 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5766 bmap = isl_basic_map_apply_range(bmap, range);
5767 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5769 for (i = 0; i < n_out; ++i)
5770 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5771 isl_dim_out, i);
5773 bmap = isl_basic_map_gauss(bmap, NULL);
5774 return isl_basic_map_finalize(bmap);
5777 int isl_map_may_be_set(__isl_keep isl_map *map)
5779 if (!map)
5780 return -1;
5781 return isl_space_may_be_set(map->dim);
5784 /* Is this map actually a set?
5785 * Users should never call this function. Outside of isl,
5786 * the type should indicate whether something is a set or a map.
5788 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5790 if (!map)
5791 return isl_bool_error;
5792 return isl_space_is_set(map->dim);
5795 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
5797 int i;
5798 isl_bool is_set;
5799 struct isl_set *set;
5801 is_set = isl_map_is_set(map);
5802 if (is_set < 0)
5803 goto error;
5804 if (is_set)
5805 return set_from_map(map);
5807 map = isl_map_cow(map);
5808 if (!map)
5809 goto error;
5811 set = set_from_map(map);
5812 set->dim = isl_space_range(set->dim);
5813 if (!set->dim)
5814 goto error;
5815 for (i = 0; i < map->n; ++i) {
5816 set->p[i] = isl_basic_map_range(map->p[i]);
5817 if (!set->p[i])
5818 goto error;
5820 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5821 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5822 return set;
5823 error:
5824 isl_map_free(map);
5825 return NULL;
5828 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5830 int i;
5832 map = isl_map_cow(map);
5833 if (!map)
5834 return NULL;
5836 map->dim = isl_space_domain_map(map->dim);
5837 if (!map->dim)
5838 goto error;
5839 for (i = 0; i < map->n; ++i) {
5840 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5841 if (!map->p[i])
5842 goto error;
5844 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5845 map = isl_map_unmark_normalized(map);
5846 return map;
5847 error:
5848 isl_map_free(map);
5849 return NULL;
5852 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5854 int i;
5855 isl_space *range_dim;
5857 map = isl_map_cow(map);
5858 if (!map)
5859 return NULL;
5861 range_dim = isl_space_range(isl_map_get_space(map));
5862 range_dim = isl_space_from_range(range_dim);
5863 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5864 map->dim = isl_space_join(map->dim, range_dim);
5865 if (!map->dim)
5866 goto error;
5867 for (i = 0; i < map->n; ++i) {
5868 map->p[i] = isl_basic_map_range_map(map->p[i]);
5869 if (!map->p[i])
5870 goto error;
5872 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5873 map = isl_map_unmark_normalized(map);
5874 return map;
5875 error:
5876 isl_map_free(map);
5877 return NULL;
5880 /* Given a wrapped map of the form A[B -> C],
5881 * return the map A[B -> C] -> B.
5883 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5885 isl_id *id;
5886 isl_map *map;
5888 if (!set)
5889 return NULL;
5890 if (!isl_set_has_tuple_id(set))
5891 return isl_map_domain_map(isl_set_unwrap(set));
5893 id = isl_set_get_tuple_id(set);
5894 map = isl_map_domain_map(isl_set_unwrap(set));
5895 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5897 return map;
5900 __isl_give isl_basic_map *isl_basic_map_from_domain(
5901 __isl_take isl_basic_set *bset)
5903 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5906 __isl_give isl_basic_map *isl_basic_map_from_range(
5907 __isl_take isl_basic_set *bset)
5909 isl_space *space;
5910 space = isl_basic_set_get_space(bset);
5911 space = isl_space_from_range(space);
5912 bset = isl_basic_set_reset_space(bset, space);
5913 return bset_to_bmap(bset);
5916 /* Create a relation with the given set as range.
5917 * The domain of the created relation is a zero-dimensional
5918 * flat anonymous space.
5920 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5922 isl_space *space;
5923 space = isl_set_get_space(set);
5924 space = isl_space_from_range(space);
5925 set = isl_set_reset_space(set, space);
5926 return set_to_map(set);
5929 /* Create a relation with the given set as domain.
5930 * The range of the created relation is a zero-dimensional
5931 * flat anonymous space.
5933 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5935 return isl_map_reverse(isl_map_from_range(set));
5938 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5939 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5941 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5944 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5945 __isl_take isl_set *range)
5947 return isl_map_apply_range(isl_map_reverse(domain), range);
5950 /* Return a newly allocated isl_map with given space and flags and
5951 * room for "n" basic maps.
5952 * Make sure that all cached information is cleared.
5954 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5955 unsigned flags)
5957 struct isl_map *map;
5959 if (!space)
5960 return NULL;
5961 if (n < 0)
5962 isl_die(space->ctx, isl_error_internal,
5963 "negative number of basic maps", goto error);
5964 map = isl_calloc(space->ctx, struct isl_map,
5965 sizeof(struct isl_map) +
5966 (n - 1) * sizeof(struct isl_basic_map *));
5967 if (!map)
5968 goto error;
5970 map->ctx = space->ctx;
5971 isl_ctx_ref(map->ctx);
5972 map->ref = 1;
5973 map->size = n;
5974 map->n = 0;
5975 map->dim = space;
5976 map->flags = flags;
5977 return map;
5978 error:
5979 isl_space_free(space);
5980 return NULL;
5983 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
5985 struct isl_basic_map *bmap;
5986 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
5987 bmap = isl_basic_map_set_to_empty(bmap);
5988 return bmap;
5991 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
5993 struct isl_basic_set *bset;
5994 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
5995 bset = isl_basic_set_set_to_empty(bset);
5996 return bset;
5999 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6001 struct isl_basic_map *bmap;
6002 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6003 bmap = isl_basic_map_finalize(bmap);
6004 return bmap;
6007 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6009 struct isl_basic_set *bset;
6010 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6011 bset = isl_basic_set_finalize(bset);
6012 return bset;
6015 __isl_give isl_basic_map *isl_basic_map_nat_universe(
6016 __isl_take isl_space *space)
6018 int i;
6019 unsigned total = isl_space_dim(space, isl_dim_all);
6020 isl_basic_map *bmap;
6022 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
6023 for (i = 0; i < total; ++i) {
6024 int k = isl_basic_map_alloc_inequality(bmap);
6025 if (k < 0)
6026 goto error;
6027 isl_seq_clr(bmap->ineq[k], 1 + total);
6028 isl_int_set_si(bmap->ineq[k][1 + i], 1);
6030 return bmap;
6031 error:
6032 isl_basic_map_free(bmap);
6033 return NULL;
6036 __isl_give isl_basic_set *isl_basic_set_nat_universe(
6037 __isl_take isl_space *space)
6039 return isl_basic_map_nat_universe(space);
6042 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
6044 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
6047 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
6049 return isl_map_nat_universe(dim);
6052 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6054 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6057 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6059 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6062 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6064 struct isl_map *map;
6065 if (!space)
6066 return NULL;
6067 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6068 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6069 return map;
6072 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6074 struct isl_set *set;
6075 if (!space)
6076 return NULL;
6077 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6078 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6079 return set;
6082 struct isl_map *isl_map_dup(struct isl_map *map)
6084 int i;
6085 struct isl_map *dup;
6087 if (!map)
6088 return NULL;
6089 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6090 for (i = 0; i < map->n; ++i)
6091 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6092 return dup;
6095 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6096 __isl_take isl_basic_map *bmap)
6098 if (!bmap || !map)
6099 goto error;
6100 if (isl_basic_map_plain_is_empty(bmap)) {
6101 isl_basic_map_free(bmap);
6102 return map;
6104 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
6105 isl_assert(map->ctx, map->n < map->size, goto error);
6106 map->p[map->n] = bmap;
6107 map->n++;
6108 map = isl_map_unmark_normalized(map);
6109 return map;
6110 error:
6111 if (map)
6112 isl_map_free(map);
6113 if (bmap)
6114 isl_basic_map_free(bmap);
6115 return NULL;
6118 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6120 int i;
6122 if (!map)
6123 return NULL;
6125 if (--map->ref > 0)
6126 return NULL;
6128 clear_caches(map);
6129 isl_ctx_deref(map->ctx);
6130 for (i = 0; i < map->n; ++i)
6131 isl_basic_map_free(map->p[i]);
6132 isl_space_free(map->dim);
6133 free(map);
6135 return NULL;
6138 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6139 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6141 int j;
6143 bmap = isl_basic_map_cow(bmap);
6144 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6145 j = isl_basic_map_alloc_equality(bmap);
6146 if (j < 0)
6147 goto error;
6148 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6149 isl_int_set_si(bmap->eq[j][pos], -1);
6150 isl_int_set_si(bmap->eq[j][0], value);
6151 bmap = isl_basic_map_simplify(bmap);
6152 return isl_basic_map_finalize(bmap);
6153 error:
6154 isl_basic_map_free(bmap);
6155 return NULL;
6158 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6159 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6161 int j;
6163 bmap = isl_basic_map_cow(bmap);
6164 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6165 j = isl_basic_map_alloc_equality(bmap);
6166 if (j < 0)
6167 goto error;
6168 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6169 isl_int_set_si(bmap->eq[j][pos], -1);
6170 isl_int_set(bmap->eq[j][0], value);
6171 bmap = isl_basic_map_simplify(bmap);
6172 return isl_basic_map_finalize(bmap);
6173 error:
6174 isl_basic_map_free(bmap);
6175 return NULL;
6178 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6179 enum isl_dim_type type, unsigned pos, int value)
6181 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6182 return isl_basic_map_free(bmap);
6183 return isl_basic_map_fix_pos_si(bmap,
6184 isl_basic_map_offset(bmap, type) + pos, value);
6187 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6188 enum isl_dim_type type, unsigned pos, isl_int value)
6190 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6191 return isl_basic_map_free(bmap);
6192 return isl_basic_map_fix_pos(bmap,
6193 isl_basic_map_offset(bmap, type) + pos, value);
6196 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6197 * to be equal to "v".
6199 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6200 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6202 if (!bmap || !v)
6203 goto error;
6204 if (!isl_val_is_int(v))
6205 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6206 "expecting integer value", goto error);
6207 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6208 goto error;
6209 pos += isl_basic_map_offset(bmap, type);
6210 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6211 isl_val_free(v);
6212 return bmap;
6213 error:
6214 isl_basic_map_free(bmap);
6215 isl_val_free(v);
6216 return NULL;
6219 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6220 * to be equal to "v".
6222 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6223 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6225 return isl_basic_map_fix_val(bset, type, pos, v);
6228 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
6229 enum isl_dim_type type, unsigned pos, int value)
6231 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6232 type, pos, value));
6235 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6236 enum isl_dim_type type, unsigned pos, isl_int value)
6238 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6239 type, pos, value));
6242 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
6243 unsigned input, int value)
6245 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
6248 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
6249 unsigned dim, int value)
6251 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6252 isl_dim_set, dim, value));
6255 /* Remove the basic map at position "i" from "map" if this basic map
6256 * is (obviously) empty.
6258 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6260 isl_bool empty;
6262 if (!map)
6263 return NULL;
6265 empty = isl_basic_map_plain_is_empty(map->p[i]);
6266 if (empty < 0)
6267 return isl_map_free(map);
6268 if (!empty)
6269 return map;
6271 isl_basic_map_free(map->p[i]);
6272 map->n--;
6273 if (i != map->n) {
6274 map->p[i] = map->p[map->n];
6275 map = isl_map_unmark_normalized(map);
6279 return map;
6282 /* Perform "fn" on each basic map of "map", where we may not be holding
6283 * the only reference to "map".
6284 * In particular, "fn" should be a semantics preserving operation
6285 * that we want to apply to all copies of "map". We therefore need
6286 * to be careful not to modify "map" in a way that breaks "map"
6287 * in case anything goes wrong.
6289 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6290 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6292 struct isl_basic_map *bmap;
6293 int i;
6295 if (!map)
6296 return NULL;
6298 for (i = map->n - 1; i >= 0; --i) {
6299 bmap = isl_basic_map_copy(map->p[i]);
6300 bmap = fn(bmap);
6301 if (!bmap)
6302 goto error;
6303 isl_basic_map_free(map->p[i]);
6304 map->p[i] = bmap;
6305 map = remove_if_empty(map, i);
6306 if (!map)
6307 return NULL;
6310 return map;
6311 error:
6312 isl_map_free(map);
6313 return NULL;
6316 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6317 enum isl_dim_type type, unsigned pos, int value)
6319 int i;
6321 map = isl_map_cow(map);
6322 if (isl_map_check_range(map, type, pos, 1) < 0)
6323 return isl_map_free(map);
6324 for (i = map->n - 1; i >= 0; --i) {
6325 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6326 map = remove_if_empty(map, i);
6327 if (!map)
6328 return NULL;
6330 map = isl_map_unmark_normalized(map);
6331 return map;
6334 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6335 enum isl_dim_type type, unsigned pos, int value)
6337 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6340 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6341 enum isl_dim_type type, unsigned pos, isl_int value)
6343 int i;
6345 map = isl_map_cow(map);
6346 if (isl_map_check_range(map, type, pos, 1) < 0)
6347 return isl_map_free(map);
6348 for (i = 0; i < map->n; ++i) {
6349 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6350 if (!map->p[i])
6351 goto error;
6353 map = isl_map_unmark_normalized(map);
6354 return map;
6355 error:
6356 isl_map_free(map);
6357 return NULL;
6360 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6361 enum isl_dim_type type, unsigned pos, isl_int value)
6363 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6366 /* Fix the value of the variable at position "pos" of type "type" of "map"
6367 * to be equal to "v".
6369 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6370 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6372 int i;
6374 map = isl_map_cow(map);
6375 if (!map || !v)
6376 goto error;
6378 if (!isl_val_is_int(v))
6379 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6380 "expecting integer value", goto error);
6381 if (isl_map_check_range(map, type, pos, 1) < 0)
6382 goto error;
6383 for (i = map->n - 1; i >= 0; --i) {
6384 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6385 isl_val_copy(v));
6386 map = remove_if_empty(map, i);
6387 if (!map)
6388 goto error;
6390 map = isl_map_unmark_normalized(map);
6391 isl_val_free(v);
6392 return map;
6393 error:
6394 isl_map_free(map);
6395 isl_val_free(v);
6396 return NULL;
6399 /* Fix the value of the variable at position "pos" of type "type" of "set"
6400 * to be equal to "v".
6402 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6403 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6405 return isl_map_fix_val(set, type, pos, v);
6408 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
6409 unsigned input, int value)
6411 return isl_map_fix_si(map, isl_dim_in, input, value);
6414 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
6416 return set_from_map(isl_map_fix_si(set_to_map(set),
6417 isl_dim_set, dim, value));
6420 static __isl_give isl_basic_map *basic_map_bound_si(
6421 __isl_take isl_basic_map *bmap,
6422 enum isl_dim_type type, unsigned pos, int value, int upper)
6424 int j;
6426 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6427 return isl_basic_map_free(bmap);
6428 pos += isl_basic_map_offset(bmap, type);
6429 bmap = isl_basic_map_cow(bmap);
6430 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6431 j = isl_basic_map_alloc_inequality(bmap);
6432 if (j < 0)
6433 goto error;
6434 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6435 if (upper) {
6436 isl_int_set_si(bmap->ineq[j][pos], -1);
6437 isl_int_set_si(bmap->ineq[j][0], value);
6438 } else {
6439 isl_int_set_si(bmap->ineq[j][pos], 1);
6440 isl_int_set_si(bmap->ineq[j][0], -value);
6442 bmap = isl_basic_map_simplify(bmap);
6443 return isl_basic_map_finalize(bmap);
6444 error:
6445 isl_basic_map_free(bmap);
6446 return NULL;
6449 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6450 __isl_take isl_basic_map *bmap,
6451 enum isl_dim_type type, unsigned pos, int value)
6453 return basic_map_bound_si(bmap, type, pos, value, 0);
6456 /* Constrain the values of the given dimension to be no greater than "value".
6458 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6459 __isl_take isl_basic_map *bmap,
6460 enum isl_dim_type type, unsigned pos, int value)
6462 return basic_map_bound_si(bmap, type, pos, value, 1);
6465 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6466 enum isl_dim_type type, unsigned pos, int value, int upper)
6468 int i;
6470 map = isl_map_cow(map);
6471 if (isl_map_check_range(map, type, pos, 1) < 0)
6472 return isl_map_free(map);
6473 for (i = 0; i < map->n; ++i) {
6474 map->p[i] = basic_map_bound_si(map->p[i],
6475 type, pos, value, upper);
6476 if (!map->p[i])
6477 goto error;
6479 map = isl_map_unmark_normalized(map);
6480 return map;
6481 error:
6482 isl_map_free(map);
6483 return NULL;
6486 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6487 enum isl_dim_type type, unsigned pos, int value)
6489 return map_bound_si(map, type, pos, value, 0);
6492 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6493 enum isl_dim_type type, unsigned pos, int value)
6495 return map_bound_si(map, type, pos, value, 1);
6498 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6499 enum isl_dim_type type, unsigned pos, int value)
6501 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6502 type, pos, value));
6505 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6506 enum isl_dim_type type, unsigned pos, int value)
6508 return isl_map_upper_bound_si(set, type, pos, value);
6511 /* Bound the given variable of "bmap" from below (or above is "upper"
6512 * is set) to "value".
6514 static __isl_give isl_basic_map *basic_map_bound(
6515 __isl_take isl_basic_map *bmap,
6516 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6518 int j;
6520 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6521 return isl_basic_map_free(bmap);
6522 pos += isl_basic_map_offset(bmap, type);
6523 bmap = isl_basic_map_cow(bmap);
6524 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6525 j = isl_basic_map_alloc_inequality(bmap);
6526 if (j < 0)
6527 goto error;
6528 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6529 if (upper) {
6530 isl_int_set_si(bmap->ineq[j][pos], -1);
6531 isl_int_set(bmap->ineq[j][0], value);
6532 } else {
6533 isl_int_set_si(bmap->ineq[j][pos], 1);
6534 isl_int_neg(bmap->ineq[j][0], value);
6536 bmap = isl_basic_map_simplify(bmap);
6537 return isl_basic_map_finalize(bmap);
6538 error:
6539 isl_basic_map_free(bmap);
6540 return NULL;
6543 /* Bound the given variable of "map" from below (or above is "upper"
6544 * is set) to "value".
6546 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6547 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6549 int i;
6551 map = isl_map_cow(map);
6552 if (isl_map_check_range(map, type, pos, 1) < 0)
6553 return isl_map_free(map);
6554 for (i = map->n - 1; i >= 0; --i) {
6555 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6556 map = remove_if_empty(map, i);
6557 if (!map)
6558 return NULL;
6560 map = isl_map_unmark_normalized(map);
6561 return map;
6564 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6565 enum isl_dim_type type, unsigned pos, isl_int value)
6567 return map_bound(map, type, pos, value, 0);
6570 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6571 enum isl_dim_type type, unsigned pos, isl_int value)
6573 return map_bound(map, type, pos, value, 1);
6576 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6577 enum isl_dim_type type, unsigned pos, isl_int value)
6579 return isl_map_lower_bound(set, type, pos, value);
6582 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6583 enum isl_dim_type type, unsigned pos, isl_int value)
6585 return isl_map_upper_bound(set, type, pos, value);
6588 /* Force the values of the variable at position "pos" of type "type" of "set"
6589 * to be no smaller than "value".
6591 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6592 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6594 if (!value)
6595 goto error;
6596 if (!isl_val_is_int(value))
6597 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6598 "expecting integer value", goto error);
6599 set = isl_set_lower_bound(set, type, pos, value->n);
6600 isl_val_free(value);
6601 return set;
6602 error:
6603 isl_val_free(value);
6604 isl_set_free(set);
6605 return NULL;
6608 /* Force the values of the variable at position "pos" of type "type" of "set"
6609 * to be no greater than "value".
6611 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6612 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6614 if (!value)
6615 goto error;
6616 if (!isl_val_is_int(value))
6617 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6618 "expecting integer value", goto error);
6619 set = isl_set_upper_bound(set, type, pos, value->n);
6620 isl_val_free(value);
6621 return set;
6622 error:
6623 isl_val_free(value);
6624 isl_set_free(set);
6625 return NULL;
6628 /* Bound the given variable of "bset" from below (or above is "upper"
6629 * is set) to "value".
6631 static __isl_give isl_basic_set *isl_basic_set_bound(
6632 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6633 isl_int value, int upper)
6635 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
6636 type, pos, value, upper));
6639 /* Bound the given variable of "bset" from below (or above is "upper"
6640 * is set) to "value".
6642 static __isl_give isl_basic_set *isl_basic_set_bound_val(
6643 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6644 __isl_take isl_val *value, int upper)
6646 if (!value)
6647 goto error;
6648 if (!isl_val_is_int(value))
6649 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
6650 "expecting integer value", goto error);
6651 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
6652 isl_val_free(value);
6653 return bset;
6654 error:
6655 isl_val_free(value);
6656 isl_basic_set_free(bset);
6657 return NULL;
6660 /* Bound the given variable of "bset" from below to "value".
6662 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
6663 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6664 __isl_take isl_val *value)
6666 return isl_basic_set_bound_val(bset, type, pos, value, 0);
6669 /* Bound the given variable of "bset" from above to "value".
6671 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
6672 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6673 __isl_take isl_val *value)
6675 return isl_basic_set_bound_val(bset, type, pos, value, 1);
6678 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
6680 int i;
6682 map = isl_map_cow(map);
6683 if (!map)
6684 return NULL;
6686 map->dim = isl_space_reverse(map->dim);
6687 if (!map->dim)
6688 goto error;
6689 for (i = 0; i < map->n; ++i) {
6690 map->p[i] = isl_basic_map_reverse(map->p[i]);
6691 if (!map->p[i])
6692 goto error;
6694 map = isl_map_unmark_normalized(map);
6695 return map;
6696 error:
6697 isl_map_free(map);
6698 return NULL;
6701 #undef TYPE
6702 #define TYPE isl_pw_multi_aff
6703 #undef SUFFIX
6704 #define SUFFIX _pw_multi_aff
6705 #undef EMPTY
6706 #define EMPTY isl_pw_multi_aff_empty
6707 #undef ADD
6708 #define ADD isl_pw_multi_aff_union_add
6709 #include "isl_map_lexopt_templ.c"
6711 /* Given a map "map", compute the lexicographically minimal
6712 * (or maximal) image element for each domain element in dom,
6713 * in the form of an isl_pw_multi_aff.
6714 * If "empty" is not NULL, then set *empty to those elements in dom that
6715 * do not have an image element.
6716 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6717 * should be computed over the domain of "map". "empty" is also NULL
6718 * in this case.
6720 * We first compute the lexicographically minimal or maximal element
6721 * in the first basic map. This results in a partial solution "res"
6722 * and a subset "todo" of dom that still need to be handled.
6723 * We then consider each of the remaining maps in "map" and successively
6724 * update both "res" and "todo".
6725 * If "empty" is NULL, then the todo sets are not needed and therefore
6726 * also not computed.
6728 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6729 __isl_take isl_map *map, __isl_take isl_set *dom,
6730 __isl_give isl_set **empty, unsigned flags)
6732 int i;
6733 int full;
6734 isl_pw_multi_aff *res;
6735 isl_set *todo;
6737 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6738 if (!map || (!full && !dom))
6739 goto error;
6741 if (isl_map_plain_is_empty(map)) {
6742 if (empty)
6743 *empty = dom;
6744 else
6745 isl_set_free(dom);
6746 return isl_pw_multi_aff_from_map(map);
6749 res = basic_map_partial_lexopt_pw_multi_aff(
6750 isl_basic_map_copy(map->p[0]),
6751 isl_set_copy(dom), empty, flags);
6753 if (empty)
6754 todo = *empty;
6755 for (i = 1; i < map->n; ++i) {
6756 isl_pw_multi_aff *res_i;
6758 res_i = basic_map_partial_lexopt_pw_multi_aff(
6759 isl_basic_map_copy(map->p[i]),
6760 isl_set_copy(dom), empty, flags);
6762 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6763 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6764 else
6765 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6767 if (empty)
6768 todo = isl_set_intersect(todo, *empty);
6771 isl_set_free(dom);
6772 isl_map_free(map);
6774 if (empty)
6775 *empty = todo;
6777 return res;
6778 error:
6779 if (empty)
6780 *empty = NULL;
6781 isl_set_free(dom);
6782 isl_map_free(map);
6783 return NULL;
6786 #undef TYPE
6787 #define TYPE isl_map
6788 #undef SUFFIX
6789 #define SUFFIX
6790 #undef EMPTY
6791 #define EMPTY isl_map_empty
6792 #undef ADD
6793 #define ADD isl_map_union_disjoint
6794 #include "isl_map_lexopt_templ.c"
6796 /* Given a map "map", compute the lexicographically minimal
6797 * (or maximal) image element for each domain element in "dom",
6798 * in the form of an isl_map.
6799 * If "empty" is not NULL, then set *empty to those elements in "dom" that
6800 * do not have an image element.
6801 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6802 * should be computed over the domain of "map". "empty" is also NULL
6803 * in this case.
6805 * If the input consists of more than one disjunct, then first
6806 * compute the desired result in the form of an isl_pw_multi_aff and
6807 * then convert that into an isl_map.
6809 * This function used to have an explicit implementation in terms
6810 * of isl_maps, but it would continually intersect the domains of
6811 * partial results with the complement of the domain of the next
6812 * partial solution, potentially leading to an explosion in the number
6813 * of disjuncts if there are several disjuncts in the input.
6814 * An even earlier implementation of this function would look for
6815 * better results in the domain of the partial result and for extra
6816 * results in the complement of this domain, which would lead to
6817 * even more splintering.
6819 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6820 __isl_take isl_map *map, __isl_take isl_set *dom,
6821 __isl_give isl_set **empty, unsigned flags)
6823 int full;
6824 struct isl_map *res;
6825 isl_pw_multi_aff *pma;
6827 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6828 if (!map || (!full && !dom))
6829 goto error;
6831 if (isl_map_plain_is_empty(map)) {
6832 if (empty)
6833 *empty = dom;
6834 else
6835 isl_set_free(dom);
6836 return map;
6839 if (map->n == 1) {
6840 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6841 dom, empty, flags);
6842 isl_map_free(map);
6843 return res;
6846 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6847 flags);
6848 return isl_map_from_pw_multi_aff(pma);
6849 error:
6850 if (empty)
6851 *empty = NULL;
6852 isl_set_free(dom);
6853 isl_map_free(map);
6854 return NULL;
6857 __isl_give isl_map *isl_map_partial_lexmax(
6858 __isl_take isl_map *map, __isl_take isl_set *dom,
6859 __isl_give isl_set **empty)
6861 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6864 __isl_give isl_map *isl_map_partial_lexmin(
6865 __isl_take isl_map *map, __isl_take isl_set *dom,
6866 __isl_give isl_set **empty)
6868 return isl_map_partial_lexopt(map, dom, empty, 0);
6871 __isl_give isl_set *isl_set_partial_lexmin(
6872 __isl_take isl_set *set, __isl_take isl_set *dom,
6873 __isl_give isl_set **empty)
6875 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6876 dom, empty));
6879 __isl_give isl_set *isl_set_partial_lexmax(
6880 __isl_take isl_set *set, __isl_take isl_set *dom,
6881 __isl_give isl_set **empty)
6883 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6884 dom, empty));
6887 /* Compute the lexicographic minimum (or maximum if "flags" includes
6888 * ISL_OPT_MAX) of "bset" over its parametric domain.
6890 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6891 unsigned flags)
6893 return isl_basic_map_lexopt(bset, flags);
6896 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6898 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6901 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6903 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6906 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6908 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6911 /* Compute the lexicographic minimum of "bset" over its parametric domain
6912 * for the purpose of quantifier elimination.
6913 * That is, find an explicit representation for all the existentially
6914 * quantified variables in "bset" by computing their lexicographic
6915 * minimum.
6917 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6918 __isl_take isl_basic_set *bset)
6920 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6923 /* Given a basic map with one output dimension, compute the minimum or
6924 * maximum of that dimension as an isl_pw_aff.
6926 * Compute the optimum as a lexicographic optimum over the single
6927 * output dimension and extract the single isl_pw_aff from the result.
6929 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6930 int max)
6932 isl_pw_multi_aff *pma;
6933 isl_pw_aff *pwaff;
6935 bmap = isl_basic_map_copy(bmap);
6936 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
6937 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
6938 isl_pw_multi_aff_free(pma);
6940 return pwaff;
6943 /* Compute the minimum or maximum of the given output dimension
6944 * as a function of the parameters and the input dimensions,
6945 * but independently of the other output dimensions.
6947 * We first project out the other output dimension and then compute
6948 * the "lexicographic" maximum in each basic map, combining the results
6949 * using isl_pw_aff_union_max.
6951 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6952 int max)
6954 int i;
6955 isl_pw_aff *pwaff;
6956 unsigned n_out;
6958 n_out = isl_map_dim(map, isl_dim_out);
6959 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6960 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6961 if (!map)
6962 return NULL;
6964 if (map->n == 0) {
6965 isl_space *space = isl_map_get_space(map);
6966 isl_map_free(map);
6967 return isl_pw_aff_empty(space);
6970 pwaff = basic_map_dim_opt(map->p[0], max);
6971 for (i = 1; i < map->n; ++i) {
6972 isl_pw_aff *pwaff_i;
6974 pwaff_i = basic_map_dim_opt(map->p[i], max);
6975 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6978 isl_map_free(map);
6980 return pwaff;
6983 /* Compute the minimum of the given output dimension as a function of the
6984 * parameters and input dimensions, but independently of
6985 * the other output dimensions.
6987 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
6989 return map_dim_opt(map, pos, 0);
6992 /* Compute the maximum of the given output dimension as a function of the
6993 * parameters and input dimensions, but independently of
6994 * the other output dimensions.
6996 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6998 return map_dim_opt(map, pos, 1);
7001 /* Compute the minimum or maximum of the given set dimension
7002 * as a function of the parameters,
7003 * but independently of the other set dimensions.
7005 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7006 int max)
7008 return map_dim_opt(set, pos, max);
7011 /* Compute the maximum of the given set dimension as a function of the
7012 * parameters, but independently of the other set dimensions.
7014 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7016 return set_dim_opt(set, pos, 1);
7019 /* Compute the minimum of the given set dimension as a function of the
7020 * parameters, but independently of the other set dimensions.
7022 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7024 return set_dim_opt(set, pos, 0);
7027 /* Apply a preimage specified by "mat" on the parameters of "bset".
7028 * bset is assumed to have only parameters and divs.
7030 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7031 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7033 unsigned nparam;
7035 if (!bset || !mat)
7036 goto error;
7038 bset->dim = isl_space_cow(bset->dim);
7039 if (!bset->dim)
7040 goto error;
7042 nparam = isl_basic_set_dim(bset, isl_dim_param);
7044 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7046 bset->dim->nparam = 0;
7047 bset->dim->n_out = nparam;
7048 bset = isl_basic_set_preimage(bset, mat);
7049 if (bset) {
7050 bset->dim->nparam = bset->dim->n_out;
7051 bset->dim->n_out = 0;
7053 return bset;
7054 error:
7055 isl_mat_free(mat);
7056 isl_basic_set_free(bset);
7057 return NULL;
7060 /* Apply a preimage specified by "mat" on the parameters of "set".
7061 * set is assumed to have only parameters and divs.
7063 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7064 __isl_take isl_mat *mat)
7066 isl_space *space;
7067 unsigned nparam;
7069 if (!set || !mat)
7070 goto error;
7072 nparam = isl_set_dim(set, isl_dim_param);
7074 if (mat->n_row != 1 + nparam)
7075 isl_die(isl_set_get_ctx(set), isl_error_internal,
7076 "unexpected number of rows", goto error);
7078 space = isl_set_get_space(set);
7079 space = isl_space_move_dims(space, isl_dim_set, 0,
7080 isl_dim_param, 0, nparam);
7081 set = isl_set_reset_space(set, space);
7082 set = isl_set_preimage(set, mat);
7083 nparam = isl_set_dim(set, isl_dim_out);
7084 space = isl_set_get_space(set);
7085 space = isl_space_move_dims(space, isl_dim_param, 0,
7086 isl_dim_out, 0, nparam);
7087 set = isl_set_reset_space(set, space);
7088 return set;
7089 error:
7090 isl_mat_free(mat);
7091 isl_set_free(set);
7092 return NULL;
7095 /* Intersect the basic set "bset" with the affine space specified by the
7096 * equalities in "eq".
7098 static __isl_give isl_basic_set *basic_set_append_equalities(
7099 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7101 int i, k;
7102 unsigned len;
7104 if (!bset || !eq)
7105 goto error;
7107 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
7108 eq->n_row, 0);
7109 if (!bset)
7110 goto error;
7112 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
7113 for (i = 0; i < eq->n_row; ++i) {
7114 k = isl_basic_set_alloc_equality(bset);
7115 if (k < 0)
7116 goto error;
7117 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7118 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7120 isl_mat_free(eq);
7122 bset = isl_basic_set_gauss(bset, NULL);
7123 bset = isl_basic_set_finalize(bset);
7125 return bset;
7126 error:
7127 isl_mat_free(eq);
7128 isl_basic_set_free(bset);
7129 return NULL;
7132 /* Intersect the set "set" with the affine space specified by the
7133 * equalities in "eq".
7135 static struct isl_set *set_append_equalities(struct isl_set *set,
7136 struct isl_mat *eq)
7138 int i;
7140 if (!set || !eq)
7141 goto error;
7143 for (i = 0; i < set->n; ++i) {
7144 set->p[i] = basic_set_append_equalities(set->p[i],
7145 isl_mat_copy(eq));
7146 if (!set->p[i])
7147 goto error;
7149 isl_mat_free(eq);
7150 return set;
7151 error:
7152 isl_mat_free(eq);
7153 isl_set_free(set);
7154 return NULL;
7157 /* Given a basic set "bset" that only involves parameters and existentially
7158 * quantified variables, return the index of the first equality
7159 * that only involves parameters. If there is no such equality then
7160 * return bset->n_eq.
7162 * This function assumes that isl_basic_set_gauss has been called on "bset".
7164 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7166 int i, j;
7167 unsigned nparam, n_div;
7169 if (!bset)
7170 return -1;
7172 nparam = isl_basic_set_dim(bset, isl_dim_param);
7173 n_div = isl_basic_set_dim(bset, isl_dim_div);
7175 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7176 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7177 ++i;
7180 return i;
7183 /* Compute an explicit representation for the existentially quantified
7184 * variables in "bset" by computing the "minimal value" of the set
7185 * variables. Since there are no set variables, the computation of
7186 * the minimal value essentially computes an explicit representation
7187 * of the non-empty part(s) of "bset".
7189 * The input only involves parameters and existentially quantified variables.
7190 * All equalities among parameters have been removed.
7192 * Since the existentially quantified variables in the result are in general
7193 * going to be different from those in the input, we first replace
7194 * them by the minimal number of variables based on their equalities.
7195 * This should simplify the parametric integer programming.
7197 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7199 isl_morph *morph1, *morph2;
7200 isl_set *set;
7201 unsigned n;
7203 if (!bset)
7204 return NULL;
7205 if (bset->n_eq == 0)
7206 return isl_basic_set_lexmin_compute_divs(bset);
7208 morph1 = isl_basic_set_parameter_compression(bset);
7209 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7210 bset = isl_basic_set_lift(bset);
7211 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7212 bset = isl_morph_basic_set(morph2, bset);
7213 n = isl_basic_set_dim(bset, isl_dim_set);
7214 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7216 set = isl_basic_set_lexmin_compute_divs(bset);
7218 set = isl_morph_set(isl_morph_inverse(morph1), set);
7220 return set;
7223 /* Project the given basic set onto its parameter domain, possibly introducing
7224 * new, explicit, existential variables in the constraints.
7225 * The input has parameters and (possibly implicit) existential variables.
7226 * The output has the same parameters, but only
7227 * explicit existentially quantified variables.
7229 * The actual projection is performed by pip, but pip doesn't seem
7230 * to like equalities very much, so we first remove the equalities
7231 * among the parameters by performing a variable compression on
7232 * the parameters. Afterward, an inverse transformation is performed
7233 * and the equalities among the parameters are inserted back in.
7235 * The variable compression on the parameters may uncover additional
7236 * equalities that were only implicit before. We therefore check
7237 * if there are any new parameter equalities in the result and
7238 * if so recurse. The removal of parameter equalities is required
7239 * for the parameter compression performed by base_compute_divs.
7241 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
7243 int i;
7244 struct isl_mat *eq;
7245 struct isl_mat *T, *T2;
7246 struct isl_set *set;
7247 unsigned nparam;
7249 bset = isl_basic_set_cow(bset);
7250 if (!bset)
7251 return NULL;
7253 if (bset->n_eq == 0)
7254 return base_compute_divs(bset);
7256 bset = isl_basic_set_gauss(bset, NULL);
7257 if (!bset)
7258 return NULL;
7259 if (isl_basic_set_plain_is_empty(bset))
7260 return isl_set_from_basic_set(bset);
7262 i = first_parameter_equality(bset);
7263 if (i == bset->n_eq)
7264 return base_compute_divs(bset);
7266 nparam = isl_basic_set_dim(bset, isl_dim_param);
7267 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7268 0, 1 + nparam);
7269 eq = isl_mat_cow(eq);
7270 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7271 if (T && T->n_col == 0) {
7272 isl_mat_free(T);
7273 isl_mat_free(T2);
7274 isl_mat_free(eq);
7275 bset = isl_basic_set_set_to_empty(bset);
7276 return isl_set_from_basic_set(bset);
7278 bset = basic_set_parameter_preimage(bset, T);
7280 i = first_parameter_equality(bset);
7281 if (!bset)
7282 set = NULL;
7283 else if (i == bset->n_eq)
7284 set = base_compute_divs(bset);
7285 else
7286 set = parameter_compute_divs(bset);
7287 set = set_parameter_preimage(set, T2);
7288 set = set_append_equalities(set, eq);
7289 return set;
7292 /* Insert the divs from "ls" before those of "bmap".
7294 * The number of columns is not changed, which means that the last
7295 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7296 * The caller is responsible for removing the same number of dimensions
7297 * from the space of "bmap".
7299 static __isl_give isl_basic_map *insert_divs_from_local_space(
7300 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7302 int i;
7303 int n_div;
7304 int old_n_div;
7306 n_div = isl_local_space_dim(ls, isl_dim_div);
7307 if (n_div == 0)
7308 return bmap;
7310 old_n_div = bmap->n_div;
7311 bmap = insert_div_rows(bmap, n_div);
7312 if (!bmap)
7313 return NULL;
7315 for (i = 0; i < n_div; ++i) {
7316 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7317 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7320 return bmap;
7323 /* Replace the space of "bmap" by the space and divs of "ls".
7325 * If "ls" has any divs, then we simplify the result since we may
7326 * have discovered some additional equalities that could simplify
7327 * the div expressions.
7329 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7330 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7332 int n_div;
7334 bmap = isl_basic_map_cow(bmap);
7335 if (!bmap || !ls)
7336 goto error;
7338 n_div = isl_local_space_dim(ls, isl_dim_div);
7339 bmap = insert_divs_from_local_space(bmap, ls);
7340 if (!bmap)
7341 goto error;
7343 isl_space_free(bmap->dim);
7344 bmap->dim = isl_local_space_get_space(ls);
7345 if (!bmap->dim)
7346 goto error;
7348 isl_local_space_free(ls);
7349 if (n_div > 0)
7350 bmap = isl_basic_map_simplify(bmap);
7351 bmap = isl_basic_map_finalize(bmap);
7352 return bmap;
7353 error:
7354 isl_basic_map_free(bmap);
7355 isl_local_space_free(ls);
7356 return NULL;
7359 /* Replace the space of "map" by the space and divs of "ls".
7361 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7362 __isl_take isl_local_space *ls)
7364 int i;
7366 map = isl_map_cow(map);
7367 if (!map || !ls)
7368 goto error;
7370 for (i = 0; i < map->n; ++i) {
7371 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7372 isl_local_space_copy(ls));
7373 if (!map->p[i])
7374 goto error;
7376 isl_space_free(map->dim);
7377 map->dim = isl_local_space_get_space(ls);
7378 if (!map->dim)
7379 goto error;
7381 isl_local_space_free(ls);
7382 return map;
7383 error:
7384 isl_local_space_free(ls);
7385 isl_map_free(map);
7386 return NULL;
7389 /* Compute an explicit representation for the existentially
7390 * quantified variables for which do not know any explicit representation yet.
7392 * We first sort the existentially quantified variables so that the
7393 * existentially quantified variables for which we already have an explicit
7394 * representation are placed before those for which we do not.
7395 * The input dimensions, the output dimensions and the existentially
7396 * quantified variables for which we already have an explicit
7397 * representation are then turned into parameters.
7398 * compute_divs returns a map with the same parameters and
7399 * no input or output dimensions and the dimension specification
7400 * is reset to that of the input, including the existentially quantified
7401 * variables for which we already had an explicit representation.
7403 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7405 struct isl_basic_set *bset;
7406 struct isl_set *set;
7407 struct isl_map *map;
7408 isl_space *space;
7409 isl_local_space *ls;
7410 unsigned nparam;
7411 unsigned n_in;
7412 unsigned n_out;
7413 int n_known;
7414 int i;
7416 bmap = isl_basic_map_sort_divs(bmap);
7417 bmap = isl_basic_map_cow(bmap);
7418 if (!bmap)
7419 return NULL;
7421 n_known = isl_basic_map_first_unknown_div(bmap);
7422 if (n_known < 0)
7423 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7425 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7426 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7427 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7428 space = isl_space_set_alloc(bmap->ctx,
7429 nparam + n_in + n_out + n_known, 0);
7430 if (!space)
7431 goto error;
7433 ls = isl_basic_map_get_local_space(bmap);
7434 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7435 n_known, bmap->n_div - n_known);
7436 if (n_known > 0) {
7437 for (i = n_known; i < bmap->n_div; ++i)
7438 swap_div(bmap, i - n_known, i);
7439 bmap->n_div -= n_known;
7440 bmap->extra -= n_known;
7442 bmap = isl_basic_map_reset_space(bmap, space);
7443 bset = bset_from_bmap(bmap);
7445 set = parameter_compute_divs(bset);
7446 map = set_to_map(set);
7447 map = replace_space_by_local_space(map, ls);
7449 return map;
7450 error:
7451 isl_basic_map_free(bmap);
7452 return NULL;
7455 /* Remove the explicit representation of local variable "div",
7456 * if there is any.
7458 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7459 __isl_take isl_basic_map *bmap, int div)
7461 isl_bool unknown;
7463 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7464 if (unknown < 0)
7465 return isl_basic_map_free(bmap);
7466 if (unknown)
7467 return bmap;
7469 bmap = isl_basic_map_cow(bmap);
7470 if (!bmap)
7471 return NULL;
7472 isl_int_set_si(bmap->div[div][0], 0);
7473 return bmap;
7476 /* Is local variable "div" of "bmap" marked as not having an explicit
7477 * representation?
7478 * Note that even if "div" is not marked in this way and therefore
7479 * has an explicit representation, this representation may still
7480 * depend (indirectly) on other local variables that do not
7481 * have an explicit representation.
7483 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7484 int div)
7486 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7487 return isl_bool_error;
7488 return isl_int_is_zero(bmap->div[div][0]);
7491 /* Return the position of the first local variable that does not
7492 * have an explicit representation.
7493 * Return the total number of local variables if they all have
7494 * an explicit representation.
7495 * Return -1 on error.
7497 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7499 int i;
7501 if (!bmap)
7502 return -1;
7504 for (i = 0; i < bmap->n_div; ++i) {
7505 if (!isl_basic_map_div_is_known(bmap, i))
7506 return i;
7508 return bmap->n_div;
7511 /* Return the position of the first local variable that does not
7512 * have an explicit representation.
7513 * Return the total number of local variables if they all have
7514 * an explicit representation.
7515 * Return -1 on error.
7517 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7519 return isl_basic_map_first_unknown_div(bset);
7522 /* Does "bmap" have an explicit representation for all local variables?
7524 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7526 int first, n;
7528 n = isl_basic_map_dim(bmap, isl_dim_div);
7529 first = isl_basic_map_first_unknown_div(bmap);
7530 if (first < 0)
7531 return isl_bool_error;
7532 return first == n;
7535 /* Do all basic maps in "map" have an explicit representation
7536 * for all local variables?
7538 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7540 int i;
7542 if (!map)
7543 return isl_bool_error;
7545 for (i = 0; i < map->n; ++i) {
7546 int known = isl_basic_map_divs_known(map->p[i]);
7547 if (known <= 0)
7548 return known;
7551 return isl_bool_true;
7554 /* If bmap contains any unknown divs, then compute explicit
7555 * expressions for them. However, this computation may be
7556 * quite expensive, so first try to remove divs that aren't
7557 * strictly needed.
7559 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7561 int known;
7562 struct isl_map *map;
7564 known = isl_basic_map_divs_known(bmap);
7565 if (known < 0)
7566 goto error;
7567 if (known)
7568 return isl_map_from_basic_map(bmap);
7570 bmap = isl_basic_map_drop_redundant_divs(bmap);
7572 known = isl_basic_map_divs_known(bmap);
7573 if (known < 0)
7574 goto error;
7575 if (known)
7576 return isl_map_from_basic_map(bmap);
7578 map = compute_divs(bmap);
7579 return map;
7580 error:
7581 isl_basic_map_free(bmap);
7582 return NULL;
7585 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7587 int i;
7588 int known;
7589 struct isl_map *res;
7591 if (!map)
7592 return NULL;
7593 if (map->n == 0)
7594 return map;
7596 known = isl_map_divs_known(map);
7597 if (known < 0) {
7598 isl_map_free(map);
7599 return NULL;
7601 if (known)
7602 return map;
7604 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7605 for (i = 1 ; i < map->n; ++i) {
7606 struct isl_map *r2;
7607 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7608 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7609 res = isl_map_union_disjoint(res, r2);
7610 else
7611 res = isl_map_union(res, r2);
7613 isl_map_free(map);
7615 return res;
7618 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
7620 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7623 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7625 return set_from_map(isl_map_compute_divs(set_to_map(set)));
7628 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
7630 int i;
7631 struct isl_set *set;
7633 if (!map)
7634 goto error;
7636 map = isl_map_cow(map);
7637 if (!map)
7638 return NULL;
7640 set = set_from_map(map);
7641 set->dim = isl_space_domain(set->dim);
7642 if (!set->dim)
7643 goto error;
7644 for (i = 0; i < map->n; ++i) {
7645 set->p[i] = isl_basic_map_domain(map->p[i]);
7646 if (!set->p[i])
7647 goto error;
7649 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7650 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7651 return set;
7652 error:
7653 isl_map_free(map);
7654 return NULL;
7657 /* Return the union of "map1" and "map2", where we assume for now that
7658 * "map1" and "map2" are disjoint. Note that the basic maps inside
7659 * "map1" or "map2" may not be disjoint from each other.
7660 * Also note that this function is also called from isl_map_union,
7661 * which takes care of handling the situation where "map1" and "map2"
7662 * may not be disjoint.
7664 * If one of the inputs is empty, we can simply return the other input.
7665 * Similarly, if one of the inputs is universal, then it is equal to the union.
7667 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7668 __isl_take isl_map *map2)
7670 int i;
7671 unsigned flags = 0;
7672 struct isl_map *map = NULL;
7673 int is_universe;
7675 if (!map1 || !map2)
7676 goto error;
7678 if (!isl_space_is_equal(map1->dim, map2->dim))
7679 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7680 "spaces don't match", goto error);
7682 if (map1->n == 0) {
7683 isl_map_free(map1);
7684 return map2;
7686 if (map2->n == 0) {
7687 isl_map_free(map2);
7688 return map1;
7691 is_universe = isl_map_plain_is_universe(map1);
7692 if (is_universe < 0)
7693 goto error;
7694 if (is_universe) {
7695 isl_map_free(map2);
7696 return map1;
7699 is_universe = isl_map_plain_is_universe(map2);
7700 if (is_universe < 0)
7701 goto error;
7702 if (is_universe) {
7703 isl_map_free(map1);
7704 return map2;
7707 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7708 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7709 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7711 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7712 map1->n + map2->n, flags);
7713 if (!map)
7714 goto error;
7715 for (i = 0; i < map1->n; ++i) {
7716 map = isl_map_add_basic_map(map,
7717 isl_basic_map_copy(map1->p[i]));
7718 if (!map)
7719 goto error;
7721 for (i = 0; i < map2->n; ++i) {
7722 map = isl_map_add_basic_map(map,
7723 isl_basic_map_copy(map2->p[i]));
7724 if (!map)
7725 goto error;
7727 isl_map_free(map1);
7728 isl_map_free(map2);
7729 return map;
7730 error:
7731 isl_map_free(map);
7732 isl_map_free(map1);
7733 isl_map_free(map2);
7734 return NULL;
7737 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7738 * guaranteed to be disjoint by the caller.
7740 * Note that this functions is called from within isl_map_make_disjoint,
7741 * so we have to be careful not to touch the constraints of the inputs
7742 * in any way.
7744 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7745 __isl_take isl_map *map2)
7747 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7750 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7751 * not be disjoint. The parameters are assumed to have been aligned.
7753 * We currently simply call map_union_disjoint, the internal operation
7754 * of which does not really depend on the inputs being disjoint.
7755 * If the result contains more than one basic map, then we clear
7756 * the disjoint flag since the result may contain basic maps from
7757 * both inputs and these are not guaranteed to be disjoint.
7759 * As a special case, if "map1" and "map2" are obviously equal,
7760 * then we simply return "map1".
7762 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7763 __isl_take isl_map *map2)
7765 int equal;
7767 if (!map1 || !map2)
7768 goto error;
7770 equal = isl_map_plain_is_equal(map1, map2);
7771 if (equal < 0)
7772 goto error;
7773 if (equal) {
7774 isl_map_free(map2);
7775 return map1;
7778 map1 = map_union_disjoint(map1, map2);
7779 if (!map1)
7780 return NULL;
7781 if (map1->n > 1)
7782 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7783 return map1;
7784 error:
7785 isl_map_free(map1);
7786 isl_map_free(map2);
7787 return NULL;
7790 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7791 * not be disjoint.
7793 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7794 __isl_take isl_map *map2)
7796 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7799 __isl_give isl_set *isl_set_union_disjoint(
7800 __isl_take isl_set *set1, __isl_take isl_set *set2)
7802 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7803 set_to_map(set2)));
7806 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7808 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7811 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7812 * the results.
7814 * "map" and "set" are assumed to be compatible and non-NULL.
7816 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7817 __isl_take isl_set *set,
7818 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7819 __isl_take isl_basic_set *bset))
7821 unsigned flags = 0;
7822 struct isl_map *result;
7823 int i, j;
7825 if (isl_set_plain_is_universe(set)) {
7826 isl_set_free(set);
7827 return map;
7830 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7831 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7832 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7834 result = isl_map_alloc_space(isl_space_copy(map->dim),
7835 map->n * set->n, flags);
7836 for (i = 0; result && i < map->n; ++i)
7837 for (j = 0; j < set->n; ++j) {
7838 result = isl_map_add_basic_map(result,
7839 fn(isl_basic_map_copy(map->p[i]),
7840 isl_basic_set_copy(set->p[j])));
7841 if (!result)
7842 break;
7845 isl_map_free(map);
7846 isl_set_free(set);
7847 return result;
7850 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7851 __isl_take isl_set *set)
7853 isl_bool ok;
7855 ok = isl_map_compatible_range(map, set);
7856 if (ok < 0)
7857 goto error;
7858 if (!ok)
7859 isl_die(set->ctx, isl_error_invalid,
7860 "incompatible spaces", goto error);
7862 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7863 error:
7864 isl_map_free(map);
7865 isl_set_free(set);
7866 return NULL;
7869 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7870 __isl_take isl_set *set)
7872 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7875 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7876 __isl_take isl_set *set)
7878 isl_bool ok;
7880 ok = isl_map_compatible_domain(map, set);
7881 if (ok < 0)
7882 goto error;
7883 if (!ok)
7884 isl_die(set->ctx, isl_error_invalid,
7885 "incompatible spaces", goto error);
7887 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7888 error:
7889 isl_map_free(map);
7890 isl_set_free(set);
7891 return NULL;
7894 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7895 __isl_take isl_set *set)
7897 return isl_map_align_params_map_map_and(map, set,
7898 &map_intersect_domain);
7901 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7902 * in the space B -> C, return the intersection.
7903 * The parameters are assumed to have been aligned.
7905 * The map "factor" is first extended to a map living in the space
7906 * [A -> B] -> C and then a regular intersection is computed.
7908 static __isl_give isl_map *map_intersect_domain_factor_range(
7909 __isl_take isl_map *map, __isl_take isl_map *factor)
7911 isl_space *space;
7912 isl_map *ext_factor;
7914 space = isl_space_domain_factor_domain(isl_map_get_space(map));
7915 ext_factor = isl_map_universe(space);
7916 ext_factor = isl_map_domain_product(ext_factor, factor);
7917 return map_intersect(map, ext_factor);
7920 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7921 * in the space B -> C, return the intersection.
7923 __isl_give isl_map *isl_map_intersect_domain_factor_range(
7924 __isl_take isl_map *map, __isl_take isl_map *factor)
7926 return isl_map_align_params_map_map_and(map, factor,
7927 &map_intersect_domain_factor_range);
7930 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7931 * in the space A -> C, return the intersection.
7933 * The map "factor" is first extended to a map living in the space
7934 * A -> [B -> C] and then a regular intersection is computed.
7936 static __isl_give isl_map *map_intersect_range_factor_range(
7937 __isl_take isl_map *map, __isl_take isl_map *factor)
7939 isl_space *space;
7940 isl_map *ext_factor;
7942 space = isl_space_range_factor_domain(isl_map_get_space(map));
7943 ext_factor = isl_map_universe(space);
7944 ext_factor = isl_map_range_product(ext_factor, factor);
7945 return isl_map_intersect(map, ext_factor);
7948 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7949 * in the space A -> C, return the intersection.
7951 __isl_give isl_map *isl_map_intersect_range_factor_range(
7952 __isl_take isl_map *map, __isl_take isl_map *factor)
7954 return isl_map_align_params_map_map_and(map, factor,
7955 &map_intersect_range_factor_range);
7958 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7959 __isl_take isl_map *map2)
7961 if (!map1 || !map2)
7962 goto error;
7963 map1 = isl_map_reverse(map1);
7964 map1 = isl_map_apply_range(map1, map2);
7965 return isl_map_reverse(map1);
7966 error:
7967 isl_map_free(map1);
7968 isl_map_free(map2);
7969 return NULL;
7972 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7973 __isl_take isl_map *map2)
7975 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7978 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7979 __isl_take isl_map *map2)
7981 isl_space *space;
7982 struct isl_map *result;
7983 int i, j;
7985 if (!map1 || !map2)
7986 goto error;
7988 space = isl_space_join(isl_space_copy(map1->dim),
7989 isl_space_copy(map2->dim));
7991 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
7992 if (!result)
7993 goto error;
7994 for (i = 0; i < map1->n; ++i)
7995 for (j = 0; j < map2->n; ++j) {
7996 result = isl_map_add_basic_map(result,
7997 isl_basic_map_apply_range(
7998 isl_basic_map_copy(map1->p[i]),
7999 isl_basic_map_copy(map2->p[j])));
8000 if (!result)
8001 goto error;
8003 isl_map_free(map1);
8004 isl_map_free(map2);
8005 if (result && result->n <= 1)
8006 ISL_F_SET(result, ISL_MAP_DISJOINT);
8007 return result;
8008 error:
8009 isl_map_free(map1);
8010 isl_map_free(map2);
8011 return NULL;
8014 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8015 __isl_take isl_map *map2)
8017 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
8021 * returns range - domain
8023 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8025 isl_space *target_space;
8026 struct isl_basic_set *bset;
8027 unsigned dim;
8028 unsigned nparam;
8029 int i;
8031 if (!bmap)
8032 goto error;
8033 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8034 bmap->dim, isl_dim_out),
8035 goto error);
8036 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8037 dim = isl_basic_map_dim(bmap, isl_dim_in);
8038 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8039 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8040 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8041 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8042 for (i = 0; i < dim; ++i) {
8043 int j = isl_basic_map_alloc_equality(bmap);
8044 if (j < 0) {
8045 bmap = isl_basic_map_free(bmap);
8046 break;
8048 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
8049 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8050 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8051 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8053 bset = isl_basic_map_domain(bmap);
8054 bset = isl_basic_set_reset_space(bset, target_space);
8055 return bset;
8056 error:
8057 isl_basic_map_free(bmap);
8058 return NULL;
8061 /* Check that domain and range of "map" are the same.
8063 isl_stat isl_map_check_equal_tuples(__isl_keep isl_map *map)
8065 isl_space *space;
8066 isl_bool equal;
8068 space = isl_map_peek_space(map);
8069 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8070 if (equal < 0)
8071 return isl_stat_error;
8072 if (!equal)
8073 isl_die(isl_map_get_ctx(map), isl_error_invalid,
8074 "domain and range don't match", return isl_stat_error);
8075 return isl_stat_ok;
8079 * returns range - domain
8081 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8083 int i;
8084 isl_space *dim;
8085 struct isl_set *result;
8087 if (!map)
8088 return NULL;
8090 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
8091 map->dim, isl_dim_out),
8092 goto error);
8093 dim = isl_map_get_space(map);
8094 dim = isl_space_domain(dim);
8095 result = isl_set_alloc_space(dim, map->n, 0);
8096 if (!result)
8097 goto error;
8098 for (i = 0; i < map->n; ++i)
8099 result = isl_set_add_basic_set(result,
8100 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8101 isl_map_free(map);
8102 return result;
8103 error:
8104 isl_map_free(map);
8105 return NULL;
8109 * returns [domain -> range] -> range - domain
8111 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8112 __isl_take isl_basic_map *bmap)
8114 int i, k;
8115 isl_space *space;
8116 isl_basic_map *domain;
8117 int nparam, n;
8118 unsigned total;
8120 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8121 bmap->dim, isl_dim_out))
8122 isl_die(bmap->ctx, isl_error_invalid,
8123 "domain and range don't match", goto error);
8125 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8126 n = isl_basic_map_dim(bmap, isl_dim_in);
8128 space = isl_basic_map_get_space(bmap);
8129 space = isl_space_from_range(isl_space_domain(space));
8130 domain = isl_basic_map_universe(space);
8132 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8133 bmap = isl_basic_map_apply_range(bmap, domain);
8134 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8136 total = isl_basic_map_total_dim(bmap);
8138 for (i = 0; i < n; ++i) {
8139 k = isl_basic_map_alloc_equality(bmap);
8140 if (k < 0)
8141 goto error;
8142 isl_seq_clr(bmap->eq[k], 1 + total);
8143 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8144 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8145 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8148 bmap = isl_basic_map_gauss(bmap, NULL);
8149 return isl_basic_map_finalize(bmap);
8150 error:
8151 isl_basic_map_free(bmap);
8152 return NULL;
8156 * returns [domain -> range] -> range - domain
8158 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8160 int i;
8161 isl_space *domain_space;
8163 if (isl_map_check_equal_tuples(map) < 0)
8164 return isl_map_free(map);
8166 map = isl_map_cow(map);
8167 if (!map)
8168 return NULL;
8170 domain_space = isl_space_domain(isl_map_get_space(map));
8171 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
8172 map->dim = isl_space_join(map->dim, isl_space_from_range(domain_space));
8173 if (!map->dim)
8174 goto error;
8175 for (i = 0; i < map->n; ++i) {
8176 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
8177 if (!map->p[i])
8178 goto error;
8180 map = isl_map_unmark_normalized(map);
8181 return map;
8182 error:
8183 isl_map_free(map);
8184 return NULL;
8187 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8189 unsigned n_in, n_out;
8191 if (!space)
8192 return NULL;
8193 n_in = isl_space_dim(space, isl_dim_in);
8194 n_out = isl_space_dim(space, isl_dim_out);
8195 if (n_in != n_out)
8196 isl_die(space->ctx, isl_error_invalid,
8197 "number of input and output dimensions needs to be "
8198 "the same", goto error);
8199 return isl_basic_map_equal(space, n_in);
8200 error:
8201 isl_space_free(space);
8202 return NULL;
8205 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
8207 return isl_map_from_basic_map(isl_basic_map_identity(dim));
8210 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8212 isl_space *dim = isl_set_get_space(set);
8213 isl_map *id;
8214 id = isl_map_identity(isl_space_map_from_set(dim));
8215 return isl_map_intersect_range(id, set);
8218 /* Construct a basic set with all set dimensions having only non-negative
8219 * values.
8221 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8222 __isl_take isl_space *space)
8224 int i;
8225 unsigned nparam;
8226 unsigned dim;
8227 struct isl_basic_set *bset;
8229 if (!space)
8230 return NULL;
8231 nparam = space->nparam;
8232 dim = space->n_out;
8233 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8234 if (!bset)
8235 return NULL;
8236 for (i = 0; i < dim; ++i) {
8237 int k = isl_basic_set_alloc_inequality(bset);
8238 if (k < 0)
8239 goto error;
8240 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
8241 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8243 return bset;
8244 error:
8245 isl_basic_set_free(bset);
8246 return NULL;
8249 /* Construct the half-space x_pos >= 0.
8251 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8252 int pos)
8254 int k;
8255 isl_basic_set *nonneg;
8257 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8258 k = isl_basic_set_alloc_inequality(nonneg);
8259 if (k < 0)
8260 goto error;
8261 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
8262 isl_int_set_si(nonneg->ineq[k][pos], 1);
8264 return isl_basic_set_finalize(nonneg);
8265 error:
8266 isl_basic_set_free(nonneg);
8267 return NULL;
8270 /* Construct the half-space x_pos <= -1.
8272 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8273 int pos)
8275 int k;
8276 isl_basic_set *neg;
8278 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8279 k = isl_basic_set_alloc_inequality(neg);
8280 if (k < 0)
8281 goto error;
8282 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
8283 isl_int_set_si(neg->ineq[k][0], -1);
8284 isl_int_set_si(neg->ineq[k][pos], -1);
8286 return isl_basic_set_finalize(neg);
8287 error:
8288 isl_basic_set_free(neg);
8289 return NULL;
8292 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8293 enum isl_dim_type type, unsigned first, unsigned n)
8295 int i;
8296 unsigned offset;
8297 isl_basic_set *nonneg;
8298 isl_basic_set *neg;
8300 if (n == 0)
8301 return set;
8303 if (isl_set_check_range(set, type, first, n) < 0)
8304 return isl_set_free(set);
8306 offset = pos(set->dim, type);
8307 for (i = 0; i < n; ++i) {
8308 nonneg = nonneg_halfspace(isl_set_get_space(set),
8309 offset + first + i);
8310 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8312 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8315 return set;
8318 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8319 int len,
8320 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8321 void *user)
8323 isl_set *half;
8325 if (!set)
8326 return isl_stat_error;
8327 if (isl_set_plain_is_empty(set)) {
8328 isl_set_free(set);
8329 return isl_stat_ok;
8331 if (first == len)
8332 return fn(set, signs, user);
8334 signs[first] = 1;
8335 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8336 1 + first));
8337 half = isl_set_intersect(half, isl_set_copy(set));
8338 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8339 goto error;
8341 signs[first] = -1;
8342 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8343 1 + first));
8344 half = isl_set_intersect(half, set);
8345 return foreach_orthant(half, signs, first + 1, len, fn, user);
8346 error:
8347 isl_set_free(set);
8348 return isl_stat_error;
8351 /* Call "fn" on the intersections of "set" with each of the orthants
8352 * (except for obviously empty intersections). The orthant is identified
8353 * by the signs array, with each entry having value 1 or -1 according
8354 * to the sign of the corresponding variable.
8356 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8357 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8358 void *user)
8360 unsigned nparam;
8361 unsigned nvar;
8362 int *signs;
8363 isl_stat r;
8365 if (!set)
8366 return isl_stat_error;
8367 if (isl_set_plain_is_empty(set))
8368 return isl_stat_ok;
8370 nparam = isl_set_dim(set, isl_dim_param);
8371 nvar = isl_set_dim(set, isl_dim_set);
8373 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8375 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8376 fn, user);
8378 free(signs);
8380 return r;
8383 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8385 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8388 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8389 __isl_keep isl_basic_map *bmap2)
8391 isl_bool is_subset;
8392 struct isl_map *map1;
8393 struct isl_map *map2;
8395 if (!bmap1 || !bmap2)
8396 return isl_bool_error;
8398 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8399 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8401 is_subset = isl_map_is_subset(map1, map2);
8403 isl_map_free(map1);
8404 isl_map_free(map2);
8406 return is_subset;
8409 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8410 __isl_keep isl_basic_set *bset2)
8412 return isl_basic_map_is_subset(bset1, bset2);
8415 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8416 __isl_keep isl_basic_map *bmap2)
8418 isl_bool is_subset;
8420 if (!bmap1 || !bmap2)
8421 return isl_bool_error;
8422 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8423 if (is_subset != isl_bool_true)
8424 return is_subset;
8425 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8426 return is_subset;
8429 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8430 __isl_keep isl_basic_set *bset2)
8432 return isl_basic_map_is_equal(
8433 bset_to_bmap(bset1), bset_to_bmap(bset2));
8436 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8438 int i;
8439 int is_empty;
8441 if (!map)
8442 return isl_bool_error;
8443 for (i = 0; i < map->n; ++i) {
8444 is_empty = isl_basic_map_is_empty(map->p[i]);
8445 if (is_empty < 0)
8446 return isl_bool_error;
8447 if (!is_empty)
8448 return isl_bool_false;
8450 return isl_bool_true;
8453 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8455 return map ? map->n == 0 : isl_bool_error;
8458 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8460 return set ? set->n == 0 : isl_bool_error;
8463 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8465 return isl_map_is_empty(set_to_map(set));
8468 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
8469 __isl_keep isl_map *map2)
8471 if (!map1 || !map2)
8472 return isl_bool_error;
8474 return isl_space_is_equal(map1->dim, map2->dim);
8477 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
8478 __isl_keep isl_set *set2)
8480 if (!set1 || !set2)
8481 return isl_bool_error;
8483 return isl_space_is_equal(set1->dim, set2->dim);
8486 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8488 isl_bool is_subset;
8490 if (!map1 || !map2)
8491 return isl_bool_error;
8492 is_subset = isl_map_is_subset(map1, map2);
8493 if (is_subset != isl_bool_true)
8494 return is_subset;
8495 is_subset = isl_map_is_subset(map2, map1);
8496 return is_subset;
8499 /* Is "map1" equal to "map2"?
8501 * First check if they are obviously equal.
8502 * If not, then perform a more detailed analysis.
8504 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8506 isl_bool equal;
8508 equal = isl_map_plain_is_equal(map1, map2);
8509 if (equal < 0 || equal)
8510 return equal;
8511 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8514 isl_bool isl_basic_map_is_strict_subset(
8515 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8517 isl_bool is_subset;
8519 if (!bmap1 || !bmap2)
8520 return isl_bool_error;
8521 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8522 if (is_subset != isl_bool_true)
8523 return is_subset;
8524 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8525 return isl_bool_not(is_subset);
8528 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8529 __isl_keep isl_map *map2)
8531 isl_bool is_subset;
8533 if (!map1 || !map2)
8534 return isl_bool_error;
8535 is_subset = isl_map_is_subset(map1, map2);
8536 if (is_subset != isl_bool_true)
8537 return is_subset;
8538 is_subset = isl_map_is_subset(map2, map1);
8539 return isl_bool_not(is_subset);
8542 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8543 __isl_keep isl_set *set2)
8545 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8548 /* Is "bmap" obviously equal to the universe with the same space?
8550 * That is, does it not have any constraints?
8552 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8554 if (!bmap)
8555 return isl_bool_error;
8556 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8559 /* Is "bset" obviously equal to the universe with the same space?
8561 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8563 return isl_basic_map_plain_is_universe(bset);
8566 /* If "c" does not involve any existentially quantified variables,
8567 * then set *univ to false and abort
8569 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8571 isl_bool *univ = user;
8572 unsigned n;
8574 n = isl_constraint_dim(c, isl_dim_div);
8575 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8576 isl_constraint_free(c);
8577 if (*univ < 0 || !*univ)
8578 return isl_stat_error;
8579 return isl_stat_ok;
8582 /* Is "bmap" equal to the universe with the same space?
8584 * First check if it is obviously equal to the universe.
8585 * If not and if there are any constraints not involving
8586 * existentially quantified variables, then it is certainly
8587 * not equal to the universe.
8588 * Otherwise, check if the universe is a subset of "bmap".
8590 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8592 isl_bool univ;
8593 isl_basic_map *test;
8595 univ = isl_basic_map_plain_is_universe(bmap);
8596 if (univ < 0 || univ)
8597 return univ;
8598 if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8599 return isl_bool_false;
8600 univ = isl_bool_true;
8601 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8602 univ)
8603 return isl_bool_error;
8604 if (univ < 0 || !univ)
8605 return univ;
8606 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8607 univ = isl_basic_map_is_subset(test, bmap);
8608 isl_basic_map_free(test);
8609 return univ;
8612 /* Is "bset" equal to the universe with the same space?
8614 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8616 return isl_basic_map_is_universe(bset);
8619 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8621 int i;
8623 if (!map)
8624 return isl_bool_error;
8626 for (i = 0; i < map->n; ++i) {
8627 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8628 if (r < 0 || r)
8629 return r;
8632 return isl_bool_false;
8635 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8637 return isl_map_plain_is_universe(set_to_map(set));
8640 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8642 struct isl_basic_set *bset = NULL;
8643 struct isl_vec *sample = NULL;
8644 isl_bool empty, non_empty;
8646 if (!bmap)
8647 return isl_bool_error;
8649 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8650 return isl_bool_true;
8652 if (isl_basic_map_plain_is_universe(bmap))
8653 return isl_bool_false;
8655 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8656 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8657 copy = isl_basic_map_remove_redundancies(copy);
8658 empty = isl_basic_map_plain_is_empty(copy);
8659 isl_basic_map_free(copy);
8660 return empty;
8663 non_empty = isl_basic_map_plain_is_non_empty(bmap);
8664 if (non_empty < 0)
8665 return isl_bool_error;
8666 if (non_empty)
8667 return isl_bool_false;
8668 isl_vec_free(bmap->sample);
8669 bmap->sample = NULL;
8670 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8671 if (!bset)
8672 return isl_bool_error;
8673 sample = isl_basic_set_sample_vec(bset);
8674 if (!sample)
8675 return isl_bool_error;
8676 empty = sample->size == 0;
8677 isl_vec_free(bmap->sample);
8678 bmap->sample = sample;
8679 if (empty)
8680 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8682 return empty;
8685 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8687 if (!bmap)
8688 return isl_bool_error;
8689 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8692 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8694 if (!bset)
8695 return isl_bool_error;
8696 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8699 /* Is "bmap" known to be non-empty?
8701 * That is, is the cached sample still valid?
8703 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8705 unsigned total;
8707 if (!bmap)
8708 return isl_bool_error;
8709 if (!bmap->sample)
8710 return isl_bool_false;
8711 total = 1 + isl_basic_map_total_dim(bmap);
8712 if (bmap->sample->size != total)
8713 return isl_bool_false;
8714 return isl_basic_map_contains(bmap, bmap->sample);
8717 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8719 return isl_basic_map_is_empty(bset_to_bmap(bset));
8722 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
8723 __isl_take isl_basic_map *bmap2)
8725 struct isl_map *map;
8726 if (!bmap1 || !bmap2)
8727 goto error;
8729 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8731 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8732 if (!map)
8733 goto error;
8734 map = isl_map_add_basic_map(map, bmap1);
8735 map = isl_map_add_basic_map(map, bmap2);
8736 return map;
8737 error:
8738 isl_basic_map_free(bmap1);
8739 isl_basic_map_free(bmap2);
8740 return NULL;
8743 struct isl_set *isl_basic_set_union(
8744 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8746 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8747 bset_to_bmap(bset2)));
8750 /* Order divs such that any div only depends on previous divs */
8751 __isl_give isl_basic_map *isl_basic_map_order_divs(
8752 __isl_take isl_basic_map *bmap)
8754 int i;
8755 unsigned off;
8757 if (!bmap)
8758 return NULL;
8760 off = isl_space_dim(bmap->dim, isl_dim_all);
8762 for (i = 0; i < bmap->n_div; ++i) {
8763 int pos;
8764 if (isl_int_is_zero(bmap->div[i][0]))
8765 continue;
8766 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8767 bmap->n_div-i);
8768 if (pos == -1)
8769 continue;
8770 if (pos == 0)
8771 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8772 "integer division depends on itself",
8773 return isl_basic_map_free(bmap));
8774 bmap = isl_basic_map_swap_div(bmap, i, i + pos);
8775 if (!bmap)
8776 return NULL;
8777 --i;
8779 return bmap;
8782 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8784 return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8787 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8789 int i;
8791 if (!map)
8792 return 0;
8794 for (i = 0; i < map->n; ++i) {
8795 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8796 if (!map->p[i])
8797 goto error;
8800 return map;
8801 error:
8802 isl_map_free(map);
8803 return NULL;
8806 /* Sort the local variables of "bset".
8808 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8809 __isl_take isl_basic_set *bset)
8811 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8814 /* Apply the expansion computed by isl_merge_divs.
8815 * The expansion itself is given by "exp" while the resulting
8816 * list of divs is given by "div".
8818 * Move the integer divisions of "bmap" into the right position
8819 * according to "exp" and then introduce the additional integer
8820 * divisions, adding div constraints.
8821 * The moving should be done first to avoid moving coefficients
8822 * in the definitions of the extra integer divisions.
8824 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8825 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8827 int i, j;
8828 int n_div;
8830 bmap = isl_basic_map_cow(bmap);
8831 if (!bmap || !div)
8832 goto error;
8834 if (div->n_row < bmap->n_div)
8835 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8836 "not an expansion", goto error);
8838 n_div = bmap->n_div;
8839 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8840 div->n_row - n_div, 0,
8841 2 * (div->n_row - n_div));
8843 for (i = n_div; i < div->n_row; ++i)
8844 if (isl_basic_map_alloc_div(bmap) < 0)
8845 goto error;
8847 for (j = n_div - 1; j >= 0; --j) {
8848 if (exp[j] == j)
8849 break;
8850 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
8851 if (!bmap)
8852 goto error;
8854 j = 0;
8855 for (i = 0; i < div->n_row; ++i) {
8856 if (j < n_div && exp[j] == i) {
8857 j++;
8858 } else {
8859 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8860 if (isl_basic_map_div_is_marked_unknown(bmap, i))
8861 continue;
8862 bmap = isl_basic_map_add_div_constraints(bmap, i);
8863 if (!bmap)
8864 goto error;
8868 isl_mat_free(div);
8869 return bmap;
8870 error:
8871 isl_basic_map_free(bmap);
8872 isl_mat_free(div);
8873 return NULL;
8876 /* Apply the expansion computed by isl_merge_divs.
8877 * The expansion itself is given by "exp" while the resulting
8878 * list of divs is given by "div".
8880 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8881 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8883 return isl_basic_map_expand_divs(bset, div, exp);
8886 /* Look for a div in dst that corresponds to the div "div" in src.
8887 * The divs before "div" in src and dst are assumed to be the same.
8889 * Returns -1 if no corresponding div was found and the position
8890 * of the corresponding div in dst otherwise.
8892 static int find_div(__isl_keep isl_basic_map *dst,
8893 __isl_keep isl_basic_map *src, unsigned div)
8895 int i;
8897 unsigned total = isl_space_dim(src->dim, isl_dim_all);
8899 isl_assert(dst->ctx, div <= dst->n_div, return -1);
8900 for (i = div; i < dst->n_div; ++i)
8901 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8902 isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8903 dst->n_div - div) == -1)
8904 return i;
8905 return -1;
8908 /* Align the divs of "dst" to those of "src", adding divs from "src"
8909 * if needed. That is, make sure that the first src->n_div divs
8910 * of the result are equal to those of src.
8912 * The result is not finalized as by design it will have redundant
8913 * divs if any divs from "src" were copied.
8915 __isl_give isl_basic_map *isl_basic_map_align_divs(
8916 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8918 int i;
8919 isl_bool known;
8920 int extended;
8921 unsigned total;
8923 if (!dst || !src)
8924 return isl_basic_map_free(dst);
8926 if (src->n_div == 0)
8927 return dst;
8929 known = isl_basic_map_divs_known(src);
8930 if (known < 0)
8931 return isl_basic_map_free(dst);
8932 if (!known)
8933 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8934 "some src divs are unknown",
8935 return isl_basic_map_free(dst));
8937 src = isl_basic_map_order_divs(isl_basic_map_copy(src));
8938 if (!src)
8939 return isl_basic_map_free(dst);
8941 extended = 0;
8942 total = isl_space_dim(src->dim, isl_dim_all);
8943 for (i = 0; i < src->n_div; ++i) {
8944 int j = find_div(dst, src, i);
8945 if (j < 0) {
8946 if (!extended) {
8947 int extra = src->n_div - i;
8948 dst = isl_basic_map_cow(dst);
8949 if (!dst)
8950 goto error;
8951 dst = isl_basic_map_extend_space(dst,
8952 isl_space_copy(dst->dim),
8953 extra, 0, 2 * extra);
8954 extended = 1;
8956 j = isl_basic_map_alloc_div(dst);
8957 if (j < 0)
8958 goto error;
8959 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8960 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8961 dst = isl_basic_map_add_div_constraints(dst, j);
8962 if (!dst)
8963 goto error;
8965 if (j != i)
8966 dst = isl_basic_map_swap_div(dst, i, j);
8967 if (!dst)
8968 goto error;
8970 isl_basic_map_free(src);
8971 return dst;
8972 error:
8973 isl_basic_map_free(src);
8974 isl_basic_map_free(dst);
8975 return NULL;
8978 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
8980 int i;
8982 if (!map)
8983 return NULL;
8984 if (map->n == 0)
8985 return map;
8986 map = isl_map_compute_divs(map);
8987 map = isl_map_cow(map);
8988 if (!map)
8989 return NULL;
8991 for (i = 1; i < map->n; ++i)
8992 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8993 for (i = 1; i < map->n; ++i) {
8994 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8995 if (!map->p[i])
8996 return isl_map_free(map);
8999 map = isl_map_unmark_normalized(map);
9000 return map;
9003 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9005 return isl_map_align_divs_internal(map);
9008 struct isl_set *isl_set_align_divs(struct isl_set *set)
9010 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9013 /* Align the divs of the basic maps in "map" to those
9014 * of the basic maps in "list", as well as to the other basic maps in "map".
9015 * The elements in "list" are assumed to have known divs.
9017 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9018 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9020 int i, n;
9022 map = isl_map_compute_divs(map);
9023 map = isl_map_cow(map);
9024 if (!map || !list)
9025 return isl_map_free(map);
9026 if (map->n == 0)
9027 return map;
9029 n = isl_basic_map_list_n_basic_map(list);
9030 for (i = 0; i < n; ++i) {
9031 isl_basic_map *bmap;
9033 bmap = isl_basic_map_list_get_basic_map(list, i);
9034 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9035 isl_basic_map_free(bmap);
9037 if (!map->p[0])
9038 return isl_map_free(map);
9040 return isl_map_align_divs_internal(map);
9043 /* Align the divs of each element of "list" to those of "bmap".
9044 * Both "bmap" and the elements of "list" are assumed to have known divs.
9046 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9047 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9049 int i, n;
9051 if (!list || !bmap)
9052 return isl_basic_map_list_free(list);
9054 n = isl_basic_map_list_n_basic_map(list);
9055 for (i = 0; i < n; ++i) {
9056 isl_basic_map *bmap_i;
9058 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9059 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9060 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9063 return list;
9066 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
9067 __isl_take isl_map *map)
9069 isl_bool ok;
9071 ok = isl_map_compatible_domain(map, set);
9072 if (ok < 0)
9073 goto error;
9074 if (!ok)
9075 isl_die(isl_set_get_ctx(set), isl_error_invalid,
9076 "incompatible spaces", goto error);
9077 map = isl_map_intersect_domain(map, set);
9078 set = isl_map_range(map);
9079 return set;
9080 error:
9081 isl_set_free(set);
9082 isl_map_free(map);
9083 return NULL;
9086 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9087 __isl_take isl_map *map)
9089 return isl_map_align_params_map_map_and(set, map, &set_apply);
9092 /* There is no need to cow as removing empty parts doesn't change
9093 * the meaning of the set.
9095 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9097 int i;
9099 if (!map)
9100 return NULL;
9102 for (i = map->n - 1; i >= 0; --i)
9103 map = remove_if_empty(map, i);
9105 return map;
9108 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
9110 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9113 /* Create a binary relation that maps the shared initial "pos" dimensions
9114 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9116 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9117 __isl_keep isl_basic_set *bset2, int pos)
9119 isl_basic_map *bmap1;
9120 isl_basic_map *bmap2;
9122 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9123 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9124 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9125 isl_dim_out, 0, pos);
9126 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9127 isl_dim_out, 0, pos);
9128 return isl_basic_map_range_product(bmap1, bmap2);
9131 /* Given two basic sets bset1 and bset2, compute the maximal difference
9132 * between the values of dimension pos in bset1 and those in bset2
9133 * for any common value of the parameters and dimensions preceding pos.
9135 static enum isl_lp_result basic_set_maximal_difference_at(
9136 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9137 int pos, isl_int *opt)
9139 isl_basic_map *bmap1;
9140 struct isl_ctx *ctx;
9141 struct isl_vec *obj;
9142 unsigned total;
9143 unsigned nparam;
9144 unsigned dim1;
9145 enum isl_lp_result res;
9147 if (!bset1 || !bset2)
9148 return isl_lp_error;
9150 nparam = isl_basic_set_n_param(bset1);
9151 dim1 = isl_basic_set_n_dim(bset1);
9153 bmap1 = join_initial(bset1, bset2, pos);
9154 if (!bmap1)
9155 return isl_lp_error;
9157 total = isl_basic_map_total_dim(bmap1);
9158 ctx = bmap1->ctx;
9159 obj = isl_vec_alloc(ctx, 1 + total);
9160 if (!obj)
9161 goto error;
9162 isl_seq_clr(obj->block.data, 1 + total);
9163 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9164 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9165 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9166 opt, NULL, NULL);
9167 isl_basic_map_free(bmap1);
9168 isl_vec_free(obj);
9169 return res;
9170 error:
9171 isl_basic_map_free(bmap1);
9172 return isl_lp_error;
9175 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9176 * for any common value of the parameters and dimensions preceding pos
9177 * in both basic sets, the values of dimension pos in bset1 are
9178 * smaller or larger than those in bset2.
9180 * Returns
9181 * 1 if bset1 follows bset2
9182 * -1 if bset1 precedes bset2
9183 * 0 if bset1 and bset2 are incomparable
9184 * -2 if some error occurred.
9186 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9187 __isl_keep isl_basic_set *bset2, int pos)
9189 isl_int opt;
9190 enum isl_lp_result res;
9191 int cmp;
9193 isl_int_init(opt);
9195 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9197 if (res == isl_lp_empty)
9198 cmp = 0;
9199 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9200 res == isl_lp_unbounded)
9201 cmp = 1;
9202 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9203 cmp = -1;
9204 else
9205 cmp = -2;
9207 isl_int_clear(opt);
9208 return cmp;
9211 /* Given two basic sets bset1 and bset2, check whether
9212 * for any common value of the parameters and dimensions preceding pos
9213 * there is a value of dimension pos in bset1 that is larger
9214 * than a value of the same dimension in bset2.
9216 * Return
9217 * 1 if there exists such a pair
9218 * 0 if there is no such pair, but there is a pair of equal values
9219 * -1 otherwise
9220 * -2 if some error occurred.
9222 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9223 __isl_keep isl_basic_set *bset2, int pos)
9225 isl_bool empty;
9226 isl_basic_map *bmap;
9227 unsigned dim1;
9229 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9230 bmap = join_initial(bset1, bset2, pos);
9231 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9232 isl_dim_out, dim1 - pos);
9233 empty = isl_basic_map_is_empty(bmap);
9234 if (empty < 0)
9235 goto error;
9236 if (empty) {
9237 isl_basic_map_free(bmap);
9238 return -1;
9240 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9241 isl_dim_out, dim1 - pos);
9242 empty = isl_basic_map_is_empty(bmap);
9243 if (empty < 0)
9244 goto error;
9245 isl_basic_map_free(bmap);
9246 if (empty)
9247 return 0;
9248 return 1;
9249 error:
9250 isl_basic_map_free(bmap);
9251 return -2;
9254 /* Given two sets set1 and set2, check whether
9255 * for any common value of the parameters and dimensions preceding pos
9256 * there is a value of dimension pos in set1 that is larger
9257 * than a value of the same dimension in set2.
9259 * Return
9260 * 1 if there exists such a pair
9261 * 0 if there is no such pair, but there is a pair of equal values
9262 * -1 otherwise
9263 * -2 if some error occurred.
9265 int isl_set_follows_at(__isl_keep isl_set *set1,
9266 __isl_keep isl_set *set2, int pos)
9268 int i, j;
9269 int follows = -1;
9271 if (!set1 || !set2)
9272 return -2;
9274 for (i = 0; i < set1->n; ++i)
9275 for (j = 0; j < set2->n; ++j) {
9276 int f;
9277 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9278 if (f == 1 || f == -2)
9279 return f;
9280 if (f > follows)
9281 follows = f;
9284 return follows;
9287 static isl_bool isl_basic_map_plain_has_fixed_var(
9288 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9290 int i;
9291 int d;
9292 unsigned total;
9294 if (!bmap)
9295 return isl_bool_error;
9296 total = isl_basic_map_total_dim(bmap);
9297 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9298 for (; d+1 > pos; --d)
9299 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9300 break;
9301 if (d != pos)
9302 continue;
9303 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9304 return isl_bool_false;
9305 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9306 return isl_bool_false;
9307 if (!isl_int_is_one(bmap->eq[i][1+d]))
9308 return isl_bool_false;
9309 if (val)
9310 isl_int_neg(*val, bmap->eq[i][0]);
9311 return isl_bool_true;
9313 return isl_bool_false;
9316 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9317 unsigned pos, isl_int *val)
9319 int i;
9320 isl_int v;
9321 isl_int tmp;
9322 isl_bool fixed;
9324 if (!map)
9325 return isl_bool_error;
9326 if (map->n == 0)
9327 return isl_bool_false;
9328 if (map->n == 1)
9329 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9330 isl_int_init(v);
9331 isl_int_init(tmp);
9332 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9333 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9334 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9335 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9336 fixed = isl_bool_false;
9338 if (val)
9339 isl_int_set(*val, v);
9340 isl_int_clear(tmp);
9341 isl_int_clear(v);
9342 return fixed;
9345 static isl_bool isl_basic_set_plain_has_fixed_var(
9346 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9348 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9349 pos, val);
9352 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9353 enum isl_dim_type type, unsigned pos, isl_int *val)
9355 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9356 return isl_bool_error;
9357 return isl_basic_map_plain_has_fixed_var(bmap,
9358 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9361 /* If "bmap" obviously lies on a hyperplane where the given dimension
9362 * has a fixed value, then return that value.
9363 * Otherwise return NaN.
9365 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9366 __isl_keep isl_basic_map *bmap,
9367 enum isl_dim_type type, unsigned pos)
9369 isl_ctx *ctx;
9370 isl_val *v;
9371 isl_bool fixed;
9373 if (!bmap)
9374 return NULL;
9375 ctx = isl_basic_map_get_ctx(bmap);
9376 v = isl_val_alloc(ctx);
9377 if (!v)
9378 return NULL;
9379 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9380 if (fixed < 0)
9381 return isl_val_free(v);
9382 if (fixed) {
9383 isl_int_set_si(v->d, 1);
9384 return v;
9386 isl_val_free(v);
9387 return isl_val_nan(ctx);
9390 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9391 enum isl_dim_type type, unsigned pos, isl_int *val)
9393 if (isl_map_check_range(map, type, pos, 1) < 0)
9394 return isl_bool_error;
9395 return isl_map_plain_has_fixed_var(map,
9396 map_offset(map, type) - 1 + pos, val);
9399 /* If "map" obviously lies on a hyperplane where the given dimension
9400 * has a fixed value, then return that value.
9401 * Otherwise return NaN.
9403 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9404 enum isl_dim_type type, unsigned pos)
9406 isl_ctx *ctx;
9407 isl_val *v;
9408 isl_bool fixed;
9410 if (!map)
9411 return NULL;
9412 ctx = isl_map_get_ctx(map);
9413 v = isl_val_alloc(ctx);
9414 if (!v)
9415 return NULL;
9416 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9417 if (fixed < 0)
9418 return isl_val_free(v);
9419 if (fixed) {
9420 isl_int_set_si(v->d, 1);
9421 return v;
9423 isl_val_free(v);
9424 return isl_val_nan(ctx);
9427 /* If "set" obviously lies on a hyperplane where the given dimension
9428 * has a fixed value, then return that value.
9429 * Otherwise return NaN.
9431 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
9432 enum isl_dim_type type, unsigned pos)
9434 return isl_map_plain_get_val_if_fixed(set, type, pos);
9437 /* Check if dimension dim has fixed value and if so and if val is not NULL,
9438 * then return this fixed value in *val.
9440 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
9441 unsigned dim, isl_int *val)
9443 return isl_basic_set_plain_has_fixed_var(bset,
9444 isl_basic_set_n_param(bset) + dim, val);
9447 /* Return -1 if the constraint "c1" should be sorted before "c2"
9448 * and 1 if it should be sorted after "c2".
9449 * Return 0 if the two constraints are the same (up to the constant term).
9451 * In particular, if a constraint involves later variables than another
9452 * then it is sorted after this other constraint.
9453 * uset_gist depends on constraints without existentially quantified
9454 * variables sorting first.
9456 * For constraints that have the same latest variable, those
9457 * with the same coefficient for this latest variable (first in absolute value
9458 * and then in actual value) are grouped together.
9459 * This is useful for detecting pairs of constraints that can
9460 * be chained in their printed representation.
9462 * Finally, within a group, constraints are sorted according to
9463 * their coefficients (excluding the constant term).
9465 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9467 isl_int **c1 = (isl_int **) p1;
9468 isl_int **c2 = (isl_int **) p2;
9469 int l1, l2;
9470 unsigned size = *(unsigned *) arg;
9471 int cmp;
9473 l1 = isl_seq_last_non_zero(*c1 + 1, size);
9474 l2 = isl_seq_last_non_zero(*c2 + 1, size);
9476 if (l1 != l2)
9477 return l1 - l2;
9479 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9480 if (cmp != 0)
9481 return cmp;
9482 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9483 if (cmp != 0)
9484 return -cmp;
9486 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9489 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
9490 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
9491 * and 0 if the two constraints are the same (up to the constant term).
9493 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
9494 isl_int *c1, isl_int *c2)
9496 unsigned total;
9498 if (!bmap)
9499 return -2;
9500 total = isl_basic_map_total_dim(bmap);
9501 return sort_constraint_cmp(&c1, &c2, &total);
9504 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9505 __isl_take isl_basic_map *bmap)
9507 unsigned total;
9509 if (!bmap)
9510 return NULL;
9511 if (bmap->n_ineq == 0)
9512 return bmap;
9513 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
9514 return bmap;
9515 total = isl_basic_map_total_dim(bmap);
9516 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9517 &sort_constraint_cmp, &total) < 0)
9518 return isl_basic_map_free(bmap);
9519 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
9520 return bmap;
9523 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9524 __isl_take isl_basic_set *bset)
9526 isl_basic_map *bmap = bset_to_bmap(bset);
9527 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9530 __isl_give isl_basic_map *isl_basic_map_normalize(
9531 __isl_take isl_basic_map *bmap)
9533 bmap = isl_basic_map_remove_redundancies(bmap);
9534 bmap = isl_basic_map_sort_constraints(bmap);
9535 return bmap;
9537 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9538 __isl_keep isl_basic_map *bmap2)
9540 int i, cmp;
9541 unsigned total;
9542 isl_space *space1, *space2;
9544 if (!bmap1 || !bmap2)
9545 return -1;
9547 if (bmap1 == bmap2)
9548 return 0;
9549 space1 = isl_basic_map_peek_space(bmap1);
9550 space2 = isl_basic_map_peek_space(bmap2);
9551 cmp = isl_space_cmp(space1, space2);
9552 if (cmp)
9553 return cmp;
9554 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9555 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9556 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9557 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9558 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9559 return 0;
9560 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9561 return 1;
9562 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9563 return -1;
9564 if (bmap1->n_eq != bmap2->n_eq)
9565 return bmap1->n_eq - bmap2->n_eq;
9566 if (bmap1->n_ineq != bmap2->n_ineq)
9567 return bmap1->n_ineq - bmap2->n_ineq;
9568 if (bmap1->n_div != bmap2->n_div)
9569 return bmap1->n_div - bmap2->n_div;
9570 total = isl_basic_map_total_dim(bmap1);
9571 for (i = 0; i < bmap1->n_eq; ++i) {
9572 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9573 if (cmp)
9574 return cmp;
9576 for (i = 0; i < bmap1->n_ineq; ++i) {
9577 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9578 if (cmp)
9579 return cmp;
9581 for (i = 0; i < bmap1->n_div; ++i) {
9582 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9583 if (cmp)
9584 return cmp;
9586 return 0;
9589 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9590 __isl_keep isl_basic_set *bset2)
9592 return isl_basic_map_plain_cmp(bset1, bset2);
9595 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9597 int i, cmp;
9599 if (set1 == set2)
9600 return 0;
9601 if (set1->n != set2->n)
9602 return set1->n - set2->n;
9604 for (i = 0; i < set1->n; ++i) {
9605 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9606 if (cmp)
9607 return cmp;
9610 return 0;
9613 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9614 __isl_keep isl_basic_map *bmap2)
9616 if (!bmap1 || !bmap2)
9617 return isl_bool_error;
9618 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9621 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9622 __isl_keep isl_basic_set *bset2)
9624 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9625 bset_to_bmap(bset2));
9628 static int qsort_bmap_cmp(const void *p1, const void *p2)
9630 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9631 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9633 return isl_basic_map_plain_cmp(bmap1, bmap2);
9636 /* Sort the basic maps of "map" and remove duplicate basic maps.
9638 * While removing basic maps, we make sure that the basic maps remain
9639 * sorted because isl_map_normalize expects the basic maps of the result
9640 * to be sorted.
9642 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9644 int i, j;
9646 map = isl_map_remove_empty_parts(map);
9647 if (!map)
9648 return NULL;
9649 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9650 for (i = map->n - 1; i >= 1; --i) {
9651 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9652 continue;
9653 isl_basic_map_free(map->p[i-1]);
9654 for (j = i; j < map->n; ++j)
9655 map->p[j - 1] = map->p[j];
9656 map->n--;
9659 return map;
9662 /* Remove obvious duplicates among the basic maps of "map".
9664 * Unlike isl_map_normalize, this function does not remove redundant
9665 * constraints and only removes duplicates that have exactly the same
9666 * constraints in the input. It does sort the constraints and
9667 * the basic maps to ease the detection of duplicates.
9669 * If "map" has already been normalized or if the basic maps are
9670 * disjoint, then there can be no duplicates.
9672 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9674 int i;
9675 isl_basic_map *bmap;
9677 if (!map)
9678 return NULL;
9679 if (map->n <= 1)
9680 return map;
9681 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9682 return map;
9683 for (i = 0; i < map->n; ++i) {
9684 bmap = isl_basic_map_copy(map->p[i]);
9685 bmap = isl_basic_map_sort_constraints(bmap);
9686 if (!bmap)
9687 return isl_map_free(map);
9688 isl_basic_map_free(map->p[i]);
9689 map->p[i] = bmap;
9692 map = sort_and_remove_duplicates(map);
9693 return map;
9696 /* We normalize in place, but if anything goes wrong we need
9697 * to return NULL, so we need to make sure we don't change the
9698 * meaning of any possible other copies of map.
9700 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9702 int i;
9703 struct isl_basic_map *bmap;
9705 if (!map)
9706 return NULL;
9707 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9708 return map;
9709 for (i = 0; i < map->n; ++i) {
9710 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9711 if (!bmap)
9712 goto error;
9713 isl_basic_map_free(map->p[i]);
9714 map->p[i] = bmap;
9717 map = sort_and_remove_duplicates(map);
9718 if (map)
9719 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9720 return map;
9721 error:
9722 isl_map_free(map);
9723 return NULL;
9726 struct isl_set *isl_set_normalize(struct isl_set *set)
9728 return set_from_map(isl_map_normalize(set_to_map(set)));
9731 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9732 __isl_keep isl_map *map2)
9734 int i;
9735 isl_bool equal;
9737 if (!map1 || !map2)
9738 return isl_bool_error;
9740 if (map1 == map2)
9741 return isl_bool_true;
9742 if (!isl_space_is_equal(map1->dim, map2->dim))
9743 return isl_bool_false;
9745 map1 = isl_map_copy(map1);
9746 map2 = isl_map_copy(map2);
9747 map1 = isl_map_normalize(map1);
9748 map2 = isl_map_normalize(map2);
9749 if (!map1 || !map2)
9750 goto error;
9751 equal = map1->n == map2->n;
9752 for (i = 0; equal && i < map1->n; ++i) {
9753 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9754 if (equal < 0)
9755 goto error;
9757 isl_map_free(map1);
9758 isl_map_free(map2);
9759 return equal;
9760 error:
9761 isl_map_free(map1);
9762 isl_map_free(map2);
9763 return isl_bool_error;
9766 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9767 __isl_keep isl_set *set2)
9769 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9772 /* Return the basic maps in "map" as a list.
9774 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9775 __isl_keep isl_map *map)
9777 int i;
9778 isl_ctx *ctx;
9779 isl_basic_map_list *list;
9781 if (!map)
9782 return NULL;
9783 ctx = isl_map_get_ctx(map);
9784 list = isl_basic_map_list_alloc(ctx, map->n);
9786 for (i = 0; i < map->n; ++i) {
9787 isl_basic_map *bmap;
9789 bmap = isl_basic_map_copy(map->p[i]);
9790 list = isl_basic_map_list_add(list, bmap);
9793 return list;
9796 /* Return the intersection of the elements in the non-empty list "list".
9797 * All elements are assumed to live in the same space.
9799 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9800 __isl_take isl_basic_map_list *list)
9802 int i, n;
9803 isl_basic_map *bmap;
9805 if (!list)
9806 return NULL;
9807 n = isl_basic_map_list_n_basic_map(list);
9808 if (n < 1)
9809 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9810 "expecting non-empty list", goto error);
9812 bmap = isl_basic_map_list_get_basic_map(list, 0);
9813 for (i = 1; i < n; ++i) {
9814 isl_basic_map *bmap_i;
9816 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9817 bmap = isl_basic_map_intersect(bmap, bmap_i);
9820 isl_basic_map_list_free(list);
9821 return bmap;
9822 error:
9823 isl_basic_map_list_free(list);
9824 return NULL;
9827 /* Return the intersection of the elements in the non-empty list "list".
9828 * All elements are assumed to live in the same space.
9830 __isl_give isl_basic_set *isl_basic_set_list_intersect(
9831 __isl_take isl_basic_set_list *list)
9833 return isl_basic_map_list_intersect(list);
9836 /* Return the union of the elements of "list".
9837 * The list is required to have at least one element.
9839 __isl_give isl_set *isl_basic_set_list_union(
9840 __isl_take isl_basic_set_list *list)
9842 int i, n;
9843 isl_space *space;
9844 isl_basic_set *bset;
9845 isl_set *set;
9847 if (!list)
9848 return NULL;
9849 n = isl_basic_set_list_n_basic_set(list);
9850 if (n < 1)
9851 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9852 "expecting non-empty list", goto error);
9854 bset = isl_basic_set_list_get_basic_set(list, 0);
9855 space = isl_basic_set_get_space(bset);
9856 isl_basic_set_free(bset);
9858 set = isl_set_alloc_space(space, n, 0);
9859 for (i = 0; i < n; ++i) {
9860 bset = isl_basic_set_list_get_basic_set(list, i);
9861 set = isl_set_add_basic_set(set, bset);
9864 isl_basic_set_list_free(list);
9865 return set;
9866 error:
9867 isl_basic_set_list_free(list);
9868 return NULL;
9871 /* Return the union of the elements in the non-empty list "list".
9872 * All elements are assumed to live in the same space.
9874 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9876 int i, n;
9877 isl_set *set;
9879 if (!list)
9880 return NULL;
9881 n = isl_set_list_n_set(list);
9882 if (n < 1)
9883 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9884 "expecting non-empty list", goto error);
9886 set = isl_set_list_get_set(list, 0);
9887 for (i = 1; i < n; ++i) {
9888 isl_set *set_i;
9890 set_i = isl_set_list_get_set(list, i);
9891 set = isl_set_union(set, set_i);
9894 isl_set_list_free(list);
9895 return set;
9896 error:
9897 isl_set_list_free(list);
9898 return NULL;
9901 __isl_give isl_basic_map *isl_basic_map_product(
9902 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9904 isl_space *space_result = NULL;
9905 struct isl_basic_map *bmap;
9906 unsigned in1, in2, out1, out2, nparam, total, pos;
9907 struct isl_dim_map *dim_map1, *dim_map2;
9909 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9910 goto error;
9911 space_result = isl_space_product(isl_space_copy(bmap1->dim),
9912 isl_space_copy(bmap2->dim));
9914 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9915 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9916 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9917 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9918 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9920 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9921 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9922 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9923 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9924 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9925 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9926 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9927 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9928 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9929 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9930 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9932 bmap = isl_basic_map_alloc_space(space_result,
9933 bmap1->n_div + bmap2->n_div,
9934 bmap1->n_eq + bmap2->n_eq,
9935 bmap1->n_ineq + bmap2->n_ineq);
9936 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9937 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9938 bmap = isl_basic_map_simplify(bmap);
9939 return isl_basic_map_finalize(bmap);
9940 error:
9941 isl_basic_map_free(bmap1);
9942 isl_basic_map_free(bmap2);
9943 return NULL;
9946 __isl_give isl_basic_map *isl_basic_map_flat_product(
9947 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9949 isl_basic_map *prod;
9951 prod = isl_basic_map_product(bmap1, bmap2);
9952 prod = isl_basic_map_flatten(prod);
9953 return prod;
9956 __isl_give isl_basic_set *isl_basic_set_flat_product(
9957 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9959 return isl_basic_map_flat_range_product(bset1, bset2);
9962 __isl_give isl_basic_map *isl_basic_map_domain_product(
9963 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9965 isl_space *space_result = NULL;
9966 isl_basic_map *bmap;
9967 unsigned in1, in2, out, nparam, total, pos;
9968 struct isl_dim_map *dim_map1, *dim_map2;
9970 if (!bmap1 || !bmap2)
9971 goto error;
9973 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9974 isl_space_copy(bmap2->dim));
9976 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9977 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9978 out = isl_basic_map_dim(bmap1, isl_dim_out);
9979 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9981 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9982 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9983 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9984 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9985 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9986 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9987 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9988 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9989 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9990 isl_dim_map_div(dim_map1, bmap1, pos += out);
9991 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9993 bmap = isl_basic_map_alloc_space(space_result,
9994 bmap1->n_div + bmap2->n_div,
9995 bmap1->n_eq + bmap2->n_eq,
9996 bmap1->n_ineq + bmap2->n_ineq);
9997 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9998 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9999 bmap = isl_basic_map_simplify(bmap);
10000 return isl_basic_map_finalize(bmap);
10001 error:
10002 isl_basic_map_free(bmap1);
10003 isl_basic_map_free(bmap2);
10004 return NULL;
10007 __isl_give isl_basic_map *isl_basic_map_range_product(
10008 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10010 isl_bool rational;
10011 isl_space *space_result = NULL;
10012 isl_basic_map *bmap;
10013 unsigned in, out1, out2, nparam, total, pos;
10014 struct isl_dim_map *dim_map1, *dim_map2;
10016 rational = isl_basic_map_is_rational(bmap1);
10017 if (rational >= 0 && rational)
10018 rational = isl_basic_map_is_rational(bmap2);
10019 if (!bmap1 || !bmap2 || rational < 0)
10020 goto error;
10022 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10023 goto error;
10025 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10026 isl_space_copy(bmap2->dim));
10028 in = isl_basic_map_dim(bmap1, isl_dim_in);
10029 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10030 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10031 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10033 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10034 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10035 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10036 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10037 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10038 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10039 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10040 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10041 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10042 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10043 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10045 bmap = isl_basic_map_alloc_space(space_result,
10046 bmap1->n_div + bmap2->n_div,
10047 bmap1->n_eq + bmap2->n_eq,
10048 bmap1->n_ineq + bmap2->n_ineq);
10049 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10050 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10051 if (rational)
10052 bmap = isl_basic_map_set_rational(bmap);
10053 bmap = isl_basic_map_simplify(bmap);
10054 return isl_basic_map_finalize(bmap);
10055 error:
10056 isl_basic_map_free(bmap1);
10057 isl_basic_map_free(bmap2);
10058 return NULL;
10061 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10062 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10064 isl_basic_map *prod;
10066 prod = isl_basic_map_range_product(bmap1, bmap2);
10067 prod = isl_basic_map_flatten_range(prod);
10068 return prod;
10071 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10072 * and collect the results.
10073 * The result live in the space obtained by calling "space_product"
10074 * on the spaces of "map1" and "map2".
10075 * If "remove_duplicates" is set then the result may contain duplicates
10076 * (even if the inputs do not) and so we try and remove the obvious
10077 * duplicates.
10079 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10080 __isl_take isl_map *map2,
10081 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10082 __isl_take isl_space *right),
10083 __isl_give isl_basic_map *(*basic_map_product)(
10084 __isl_take isl_basic_map *left,
10085 __isl_take isl_basic_map *right),
10086 int remove_duplicates)
10088 unsigned flags = 0;
10089 struct isl_map *result;
10090 int i, j;
10091 isl_bool m;
10093 m = isl_map_has_equal_params(map1, map2);
10094 if (m < 0)
10095 goto error;
10096 if (!m)
10097 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10098 "parameters don't match", goto error);
10100 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10101 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10102 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10104 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10105 isl_space_copy(map2->dim)),
10106 map1->n * map2->n, flags);
10107 if (!result)
10108 goto error;
10109 for (i = 0; i < map1->n; ++i)
10110 for (j = 0; j < map2->n; ++j) {
10111 struct isl_basic_map *part;
10112 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10113 isl_basic_map_copy(map2->p[j]));
10114 if (isl_basic_map_is_empty(part))
10115 isl_basic_map_free(part);
10116 else
10117 result = isl_map_add_basic_map(result, part);
10118 if (!result)
10119 goto error;
10121 if (remove_duplicates)
10122 result = isl_map_remove_obvious_duplicates(result);
10123 isl_map_free(map1);
10124 isl_map_free(map2);
10125 return result;
10126 error:
10127 isl_map_free(map1);
10128 isl_map_free(map2);
10129 return NULL;
10132 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10134 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
10135 __isl_take isl_map *map2)
10137 return map_product(map1, map2, &isl_space_product,
10138 &isl_basic_map_product, 0);
10141 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10142 __isl_take isl_map *map2)
10144 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
10147 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10149 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10150 __isl_take isl_map *map2)
10152 isl_map *prod;
10154 prod = isl_map_product(map1, map2);
10155 prod = isl_map_flatten(prod);
10156 return prod;
10159 /* Given two set A and B, construct its Cartesian product A x B.
10161 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
10163 return isl_map_range_product(set1, set2);
10166 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10167 __isl_take isl_set *set2)
10169 return isl_map_flat_range_product(set1, set2);
10172 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10174 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
10175 __isl_take isl_map *map2)
10177 return map_product(map1, map2, &isl_space_domain_product,
10178 &isl_basic_map_domain_product, 1);
10181 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10183 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
10184 __isl_take isl_map *map2)
10186 return map_product(map1, map2, &isl_space_range_product,
10187 &isl_basic_map_range_product, 1);
10190 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10191 __isl_take isl_map *map2)
10193 return isl_map_align_params_map_map_and(map1, map2,
10194 &map_domain_product_aligned);
10197 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10198 __isl_take isl_map *map2)
10200 return isl_map_align_params_map_map_and(map1, map2,
10201 &map_range_product_aligned);
10204 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10206 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10208 isl_space *space;
10209 int total1, keep1, total2, keep2;
10211 if (!map)
10212 return NULL;
10213 if (!isl_space_domain_is_wrapping(map->dim) ||
10214 !isl_space_range_is_wrapping(map->dim))
10215 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10216 "not a product", return isl_map_free(map));
10218 space = isl_map_get_space(map);
10219 total1 = isl_space_dim(space, isl_dim_in);
10220 total2 = isl_space_dim(space, isl_dim_out);
10221 space = isl_space_factor_domain(space);
10222 keep1 = isl_space_dim(space, isl_dim_in);
10223 keep2 = isl_space_dim(space, isl_dim_out);
10224 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10225 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10226 map = isl_map_reset_space(map, space);
10228 return map;
10231 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10233 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10235 isl_space *space;
10236 int total1, keep1, total2, keep2;
10238 if (!map)
10239 return NULL;
10240 if (!isl_space_domain_is_wrapping(map->dim) ||
10241 !isl_space_range_is_wrapping(map->dim))
10242 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10243 "not a product", return isl_map_free(map));
10245 space = isl_map_get_space(map);
10246 total1 = isl_space_dim(space, isl_dim_in);
10247 total2 = isl_space_dim(space, isl_dim_out);
10248 space = isl_space_factor_range(space);
10249 keep1 = isl_space_dim(space, isl_dim_in);
10250 keep2 = isl_space_dim(space, isl_dim_out);
10251 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10252 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10253 map = isl_map_reset_space(map, space);
10255 return map;
10258 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10260 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10262 isl_space *space;
10263 int total, keep;
10265 if (!map)
10266 return NULL;
10267 if (!isl_space_domain_is_wrapping(map->dim))
10268 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10269 "domain is not a product", return isl_map_free(map));
10271 space = isl_map_get_space(map);
10272 total = isl_space_dim(space, isl_dim_in);
10273 space = isl_space_domain_factor_domain(space);
10274 keep = isl_space_dim(space, isl_dim_in);
10275 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10276 map = isl_map_reset_space(map, space);
10278 return map;
10281 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10283 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10285 isl_space *space;
10286 int total, keep;
10288 if (!map)
10289 return NULL;
10290 if (!isl_space_domain_is_wrapping(map->dim))
10291 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10292 "domain is not a product", return isl_map_free(map));
10294 space = isl_map_get_space(map);
10295 total = isl_space_dim(space, isl_dim_in);
10296 space = isl_space_domain_factor_range(space);
10297 keep = isl_space_dim(space, isl_dim_in);
10298 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10299 map = isl_map_reset_space(map, space);
10301 return map;
10304 /* Given a map A -> [B -> C], extract the map A -> B.
10306 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10308 isl_space *space;
10309 int total, keep;
10311 if (!map)
10312 return NULL;
10313 if (!isl_space_range_is_wrapping(map->dim))
10314 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10315 "range is not a product", return isl_map_free(map));
10317 space = isl_map_get_space(map);
10318 total = isl_space_dim(space, isl_dim_out);
10319 space = isl_space_range_factor_domain(space);
10320 keep = isl_space_dim(space, isl_dim_out);
10321 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10322 map = isl_map_reset_space(map, space);
10324 return map;
10327 /* Given a map A -> [B -> C], extract the map A -> C.
10329 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10331 isl_space *space;
10332 int total, keep;
10334 if (!map)
10335 return NULL;
10336 if (!isl_space_range_is_wrapping(map->dim))
10337 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10338 "range is not a product", return isl_map_free(map));
10340 space = isl_map_get_space(map);
10341 total = isl_space_dim(space, isl_dim_out);
10342 space = isl_space_range_factor_range(space);
10343 keep = isl_space_dim(space, isl_dim_out);
10344 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10345 map = isl_map_reset_space(map, space);
10347 return map;
10350 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10352 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10353 __isl_take isl_map *map2)
10355 isl_map *prod;
10357 prod = isl_map_domain_product(map1, map2);
10358 prod = isl_map_flatten_domain(prod);
10359 return prod;
10362 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10364 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10365 __isl_take isl_map *map2)
10367 isl_map *prod;
10369 prod = isl_map_range_product(map1, map2);
10370 prod = isl_map_flatten_range(prod);
10371 return prod;
10374 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10376 int i;
10377 uint32_t hash = isl_hash_init();
10378 unsigned total;
10380 if (!bmap)
10381 return 0;
10382 bmap = isl_basic_map_copy(bmap);
10383 bmap = isl_basic_map_normalize(bmap);
10384 if (!bmap)
10385 return 0;
10386 total = isl_basic_map_total_dim(bmap);
10387 isl_hash_byte(hash, bmap->n_eq & 0xFF);
10388 for (i = 0; i < bmap->n_eq; ++i) {
10389 uint32_t c_hash;
10390 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
10391 isl_hash_hash(hash, c_hash);
10393 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
10394 for (i = 0; i < bmap->n_ineq; ++i) {
10395 uint32_t c_hash;
10396 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
10397 isl_hash_hash(hash, c_hash);
10399 isl_hash_byte(hash, bmap->n_div & 0xFF);
10400 for (i = 0; i < bmap->n_div; ++i) {
10401 uint32_t c_hash;
10402 if (isl_int_is_zero(bmap->div[i][0]))
10403 continue;
10404 isl_hash_byte(hash, i & 0xFF);
10405 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
10406 isl_hash_hash(hash, c_hash);
10408 isl_basic_map_free(bmap);
10409 return hash;
10412 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
10414 return isl_basic_map_get_hash(bset_to_bmap(bset));
10417 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
10419 int i;
10420 uint32_t hash;
10422 if (!map)
10423 return 0;
10424 map = isl_map_copy(map);
10425 map = isl_map_normalize(map);
10426 if (!map)
10427 return 0;
10429 hash = isl_hash_init();
10430 for (i = 0; i < map->n; ++i) {
10431 uint32_t bmap_hash;
10432 bmap_hash = isl_basic_map_get_hash(map->p[i]);
10433 isl_hash_hash(hash, bmap_hash);
10436 isl_map_free(map);
10438 return hash;
10441 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
10443 return isl_map_get_hash(set_to_map(set));
10446 /* Return the number of basic maps in the (current) representation of "map".
10448 int isl_map_n_basic_map(__isl_keep isl_map *map)
10450 return map ? map->n : 0;
10453 int isl_set_n_basic_set(__isl_keep isl_set *set)
10455 return set ? set->n : 0;
10458 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
10459 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10461 int i;
10463 if (!map)
10464 return isl_stat_error;
10466 for (i = 0; i < map->n; ++i)
10467 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10468 return isl_stat_error;
10470 return isl_stat_ok;
10473 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10474 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10476 int i;
10478 if (!set)
10479 return isl_stat_error;
10481 for (i = 0; i < set->n; ++i)
10482 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10483 return isl_stat_error;
10485 return isl_stat_ok;
10488 /* Return a list of basic sets, the union of which is equal to "set".
10490 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10491 __isl_keep isl_set *set)
10493 int i;
10494 isl_basic_set_list *list;
10496 if (!set)
10497 return NULL;
10499 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10500 for (i = 0; i < set->n; ++i) {
10501 isl_basic_set *bset;
10503 bset = isl_basic_set_copy(set->p[i]);
10504 list = isl_basic_set_list_add(list, bset);
10507 return list;
10510 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10512 isl_space *space;
10514 if (!bset)
10515 return NULL;
10517 bset = isl_basic_set_cow(bset);
10518 if (!bset)
10519 return NULL;
10521 space = isl_basic_set_get_space(bset);
10522 space = isl_space_lift(space, bset->n_div);
10523 if (!space)
10524 goto error;
10525 isl_space_free(bset->dim);
10526 bset->dim = space;
10527 bset->extra -= bset->n_div;
10528 bset->n_div = 0;
10530 bset = isl_basic_set_finalize(bset);
10532 return bset;
10533 error:
10534 isl_basic_set_free(bset);
10535 return NULL;
10538 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10540 int i;
10541 isl_space *space;
10542 unsigned n_div;
10544 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10546 if (!set)
10547 return NULL;
10549 set = isl_set_cow(set);
10550 if (!set)
10551 return NULL;
10553 n_div = set->p[0]->n_div;
10554 space = isl_set_get_space(set);
10555 space = isl_space_lift(space, n_div);
10556 if (!space)
10557 goto error;
10558 isl_space_free(set->dim);
10559 set->dim = space;
10561 for (i = 0; i < set->n; ++i) {
10562 set->p[i] = isl_basic_set_lift(set->p[i]);
10563 if (!set->p[i])
10564 goto error;
10567 return set;
10568 error:
10569 isl_set_free(set);
10570 return NULL;
10573 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10575 unsigned dim;
10576 int size = 0;
10578 if (!bset)
10579 return -1;
10581 dim = isl_basic_set_total_dim(bset);
10582 size += bset->n_eq * (1 + dim);
10583 size += bset->n_ineq * (1 + dim);
10584 size += bset->n_div * (2 + dim);
10586 return size;
10589 int isl_set_size(__isl_keep isl_set *set)
10591 int i;
10592 int size = 0;
10594 if (!set)
10595 return -1;
10597 for (i = 0; i < set->n; ++i)
10598 size += isl_basic_set_size(set->p[i]);
10600 return size;
10603 /* Check if there is any lower bound (if lower == 0) and/or upper
10604 * bound (if upper == 0) on the specified dim.
10606 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10607 enum isl_dim_type type, unsigned pos, int lower, int upper)
10609 int i;
10611 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10612 return isl_bool_error;
10614 pos += isl_basic_map_offset(bmap, type);
10616 for (i = 0; i < bmap->n_div; ++i) {
10617 if (isl_int_is_zero(bmap->div[i][0]))
10618 continue;
10619 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10620 return isl_bool_true;
10623 for (i = 0; i < bmap->n_eq; ++i)
10624 if (!isl_int_is_zero(bmap->eq[i][pos]))
10625 return isl_bool_true;
10627 for (i = 0; i < bmap->n_ineq; ++i) {
10628 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10629 if (sgn > 0)
10630 lower = 1;
10631 if (sgn < 0)
10632 upper = 1;
10635 return lower && upper;
10638 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10639 enum isl_dim_type type, unsigned pos)
10641 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10644 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10645 enum isl_dim_type type, unsigned pos)
10647 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10650 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10651 enum isl_dim_type type, unsigned pos)
10653 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10656 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10657 enum isl_dim_type type, unsigned pos)
10659 int i;
10661 if (!map)
10662 return isl_bool_error;
10664 for (i = 0; i < map->n; ++i) {
10665 isl_bool bounded;
10666 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10667 if (bounded < 0 || !bounded)
10668 return bounded;
10671 return isl_bool_true;
10674 /* Return true if the specified dim is involved in both an upper bound
10675 * and a lower bound.
10677 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10678 enum isl_dim_type type, unsigned pos)
10680 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10683 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10685 static isl_bool has_any_bound(__isl_keep isl_map *map,
10686 enum isl_dim_type type, unsigned pos,
10687 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10688 enum isl_dim_type type, unsigned pos))
10690 int i;
10692 if (!map)
10693 return isl_bool_error;
10695 for (i = 0; i < map->n; ++i) {
10696 isl_bool bounded;
10697 bounded = fn(map->p[i], type, pos);
10698 if (bounded < 0 || bounded)
10699 return bounded;
10702 return isl_bool_false;
10705 /* Return 1 if the specified dim is involved in any lower bound.
10707 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10708 enum isl_dim_type type, unsigned pos)
10710 return has_any_bound(set, type, pos,
10711 &isl_basic_map_dim_has_lower_bound);
10714 /* Return 1 if the specified dim is involved in any upper bound.
10716 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10717 enum isl_dim_type type, unsigned pos)
10719 return has_any_bound(set, type, pos,
10720 &isl_basic_map_dim_has_upper_bound);
10723 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10725 static isl_bool has_bound(__isl_keep isl_map *map,
10726 enum isl_dim_type type, unsigned pos,
10727 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10728 enum isl_dim_type type, unsigned pos))
10730 int i;
10732 if (!map)
10733 return isl_bool_error;
10735 for (i = 0; i < map->n; ++i) {
10736 isl_bool bounded;
10737 bounded = fn(map->p[i], type, pos);
10738 if (bounded < 0 || !bounded)
10739 return bounded;
10742 return isl_bool_true;
10745 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10747 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10748 enum isl_dim_type type, unsigned pos)
10750 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10753 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10755 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10756 enum isl_dim_type type, unsigned pos)
10758 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10761 /* For each of the "n" variables starting at "first", determine
10762 * the sign of the variable and put the results in the first "n"
10763 * elements of the array "signs".
10764 * Sign
10765 * 1 means that the variable is non-negative
10766 * -1 means that the variable is non-positive
10767 * 0 means the variable attains both positive and negative values.
10769 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10770 unsigned first, unsigned n, int *signs)
10772 isl_vec *bound = NULL;
10773 struct isl_tab *tab = NULL;
10774 struct isl_tab_undo *snap;
10775 int i;
10777 if (!bset || !signs)
10778 return isl_stat_error;
10780 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10781 tab = isl_tab_from_basic_set(bset, 0);
10782 if (!bound || !tab)
10783 goto error;
10785 isl_seq_clr(bound->el, bound->size);
10786 isl_int_set_si(bound->el[0], -1);
10788 snap = isl_tab_snap(tab);
10789 for (i = 0; i < n; ++i) {
10790 int empty;
10792 isl_int_set_si(bound->el[1 + first + i], -1);
10793 if (isl_tab_add_ineq(tab, bound->el) < 0)
10794 goto error;
10795 empty = tab->empty;
10796 isl_int_set_si(bound->el[1 + first + i], 0);
10797 if (isl_tab_rollback(tab, snap) < 0)
10798 goto error;
10800 if (empty) {
10801 signs[i] = 1;
10802 continue;
10805 isl_int_set_si(bound->el[1 + first + i], 1);
10806 if (isl_tab_add_ineq(tab, bound->el) < 0)
10807 goto error;
10808 empty = tab->empty;
10809 isl_int_set_si(bound->el[1 + first + i], 0);
10810 if (isl_tab_rollback(tab, snap) < 0)
10811 goto error;
10813 signs[i] = empty ? -1 : 0;
10816 isl_tab_free(tab);
10817 isl_vec_free(bound);
10818 return isl_stat_ok;
10819 error:
10820 isl_tab_free(tab);
10821 isl_vec_free(bound);
10822 return isl_stat_error;
10825 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10826 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10828 if (!bset || !signs)
10829 return isl_stat_error;
10830 if (isl_basic_set_check_range(bset, type, first, n) < 0)
10831 return isl_stat_error;
10833 first += pos(bset->dim, type) - 1;
10834 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10837 /* Is it possible for the integer division "div" to depend (possibly
10838 * indirectly) on any output dimensions?
10840 * If the div is undefined, then we conservatively assume that it
10841 * may depend on them.
10842 * Otherwise, we check if it actually depends on them or on any integer
10843 * divisions that may depend on them.
10845 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10847 int i;
10848 unsigned n_out, o_out;
10849 unsigned n_div, o_div;
10851 if (isl_int_is_zero(bmap->div[div][0]))
10852 return isl_bool_true;
10854 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10855 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10857 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10858 return isl_bool_true;
10860 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10861 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10863 for (i = 0; i < n_div; ++i) {
10864 isl_bool may_involve;
10866 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10867 continue;
10868 may_involve = div_may_involve_output(bmap, i);
10869 if (may_involve < 0 || may_involve)
10870 return may_involve;
10873 return isl_bool_false;
10876 /* Return the first integer division of "bmap" in the range
10877 * [first, first + n[ that may depend on any output dimensions and
10878 * that has a non-zero coefficient in "c" (where the first coefficient
10879 * in "c" corresponds to integer division "first").
10881 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10882 isl_int *c, int first, int n)
10884 int k;
10886 if (!bmap)
10887 return -1;
10889 for (k = first; k < first + n; ++k) {
10890 isl_bool may_involve;
10892 if (isl_int_is_zero(c[k]))
10893 continue;
10894 may_involve = div_may_involve_output(bmap, k);
10895 if (may_involve < 0)
10896 return -1;
10897 if (may_involve)
10898 return k;
10901 return first + n;
10904 /* Look for a pair of inequality constraints in "bmap" of the form
10906 * -l + i >= 0 or i >= l
10907 * and
10908 * n + l - i >= 0 or i <= l + n
10910 * with n < "m" and i the output dimension at position "pos".
10911 * (Note that n >= 0 as otherwise the two constraints would conflict.)
10912 * Furthermore, "l" is only allowed to involve parameters, input dimensions
10913 * and earlier output dimensions, as well as integer divisions that do
10914 * not involve any of the output dimensions.
10916 * Return the index of the first inequality constraint or bmap->n_ineq
10917 * if no such pair can be found.
10919 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10920 int pos, isl_int m)
10922 int i, j;
10923 isl_ctx *ctx;
10924 unsigned total;
10925 unsigned n_div, o_div;
10926 unsigned n_out, o_out;
10927 int less;
10929 if (!bmap)
10930 return -1;
10932 ctx = isl_basic_map_get_ctx(bmap);
10933 total = isl_basic_map_total_dim(bmap);
10934 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10935 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10936 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10937 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10938 for (i = 0; i < bmap->n_ineq; ++i) {
10939 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
10940 continue;
10941 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
10942 n_out - (pos + 1)) != -1)
10943 continue;
10944 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
10945 0, n_div) < n_div)
10946 continue;
10947 for (j = i + 1; j < bmap->n_ineq; ++j) {
10948 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
10949 ctx->one))
10950 continue;
10951 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
10952 bmap->ineq[j] + 1, total))
10953 continue;
10954 break;
10956 if (j >= bmap->n_ineq)
10957 continue;
10958 isl_int_add(bmap->ineq[i][0],
10959 bmap->ineq[i][0], bmap->ineq[j][0]);
10960 less = isl_int_abs_lt(bmap->ineq[i][0], m);
10961 isl_int_sub(bmap->ineq[i][0],
10962 bmap->ineq[i][0], bmap->ineq[j][0]);
10963 if (!less)
10964 continue;
10965 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
10966 return i;
10967 else
10968 return j;
10971 return bmap->n_ineq;
10974 /* Return the index of the equality of "bmap" that defines
10975 * the output dimension "pos" in terms of earlier dimensions.
10976 * The equality may also involve integer divisions, as long
10977 * as those integer divisions are defined in terms of
10978 * parameters or input dimensions.
10979 * In this case, *div is set to the number of integer divisions and
10980 * *ineq is set to the number of inequality constraints (provided
10981 * div and ineq are not NULL).
10983 * The equality may also involve a single integer division involving
10984 * the output dimensions (typically only output dimension "pos") as
10985 * long as the coefficient of output dimension "pos" is 1 or -1 and
10986 * there is a pair of constraints i >= l and i <= l + n, with i referring
10987 * to output dimension "pos", l an expression involving only earlier
10988 * dimensions and n smaller than the coefficient of the integer division
10989 * in the equality. In this case, the output dimension can be defined
10990 * in terms of a modulo expression that does not involve the integer division.
10991 * *div is then set to this single integer division and
10992 * *ineq is set to the index of constraint i >= l.
10994 * Return bmap->n_eq if there is no such equality.
10995 * Return -1 on error.
10997 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
10998 int pos, int *div, int *ineq)
11000 int j, k, l;
11001 unsigned n_out, o_out;
11002 unsigned n_div, o_div;
11004 if (!bmap)
11005 return -1;
11007 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11008 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11009 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11010 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11012 if (ineq)
11013 *ineq = bmap->n_ineq;
11014 if (div)
11015 *div = n_div;
11016 for (j = 0; j < bmap->n_eq; ++j) {
11017 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11018 continue;
11019 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11020 n_out - (pos + 1)) != -1)
11021 continue;
11022 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11023 0, n_div);
11024 if (k >= n_div)
11025 return j;
11026 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11027 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11028 continue;
11029 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11030 k + 1, n_div - (k+1)) < n_div)
11031 continue;
11032 l = find_modulo_constraint_pair(bmap, pos,
11033 bmap->eq[j][o_div + k]);
11034 if (l < 0)
11035 return -1;
11036 if (l >= bmap->n_ineq)
11037 continue;
11038 if (div)
11039 *div = k;
11040 if (ineq)
11041 *ineq = l;
11042 return j;
11045 return bmap->n_eq;
11048 /* Check if the given basic map is obviously single-valued.
11049 * In particular, for each output dimension, check that there is
11050 * an equality that defines the output dimension in terms of
11051 * earlier dimensions.
11053 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11055 int i;
11056 unsigned n_out;
11058 if (!bmap)
11059 return isl_bool_error;
11061 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11063 for (i = 0; i < n_out; ++i) {
11064 int eq;
11066 eq = isl_basic_map_output_defining_equality(bmap, i,
11067 NULL, NULL);
11068 if (eq < 0)
11069 return isl_bool_error;
11070 if (eq >= bmap->n_eq)
11071 return isl_bool_false;
11074 return isl_bool_true;
11077 /* Check if the given basic map is single-valued.
11078 * We simply compute
11080 * M \circ M^-1
11082 * and check if the result is a subset of the identity mapping.
11084 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11086 isl_space *space;
11087 isl_basic_map *test;
11088 isl_basic_map *id;
11089 isl_bool sv;
11091 sv = isl_basic_map_plain_is_single_valued(bmap);
11092 if (sv < 0 || sv)
11093 return sv;
11095 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11096 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11098 space = isl_basic_map_get_space(bmap);
11099 space = isl_space_map_from_set(isl_space_range(space));
11100 id = isl_basic_map_identity(space);
11102 sv = isl_basic_map_is_subset(test, id);
11104 isl_basic_map_free(test);
11105 isl_basic_map_free(id);
11107 return sv;
11110 /* Check if the given map is obviously single-valued.
11112 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11114 if (!map)
11115 return isl_bool_error;
11116 if (map->n == 0)
11117 return isl_bool_true;
11118 if (map->n >= 2)
11119 return isl_bool_false;
11121 return isl_basic_map_plain_is_single_valued(map->p[0]);
11124 /* Check if the given map is single-valued.
11125 * We simply compute
11127 * M \circ M^-1
11129 * and check if the result is a subset of the identity mapping.
11131 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11133 isl_space *dim;
11134 isl_map *test;
11135 isl_map *id;
11136 isl_bool sv;
11138 sv = isl_map_plain_is_single_valued(map);
11139 if (sv < 0 || sv)
11140 return sv;
11142 test = isl_map_reverse(isl_map_copy(map));
11143 test = isl_map_apply_range(test, isl_map_copy(map));
11145 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11146 id = isl_map_identity(dim);
11148 sv = isl_map_is_subset(test, id);
11150 isl_map_free(test);
11151 isl_map_free(id);
11153 return sv;
11156 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11158 isl_bool in;
11160 map = isl_map_copy(map);
11161 map = isl_map_reverse(map);
11162 in = isl_map_is_single_valued(map);
11163 isl_map_free(map);
11165 return in;
11168 /* Check if the given map is obviously injective.
11170 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11172 isl_bool in;
11174 map = isl_map_copy(map);
11175 map = isl_map_reverse(map);
11176 in = isl_map_plain_is_single_valued(map);
11177 isl_map_free(map);
11179 return in;
11182 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11184 isl_bool sv;
11186 sv = isl_map_is_single_valued(map);
11187 if (sv < 0 || !sv)
11188 return sv;
11190 return isl_map_is_injective(map);
11193 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11195 return isl_map_is_single_valued(set_to_map(set));
11198 /* Does "map" only map elements to themselves?
11200 * If the domain and range spaces are different, then "map"
11201 * is considered not to be an identity relation, even if it is empty.
11202 * Otherwise, construct the maximal identity relation and
11203 * check whether "map" is a subset of this relation.
11205 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11207 isl_space *space;
11208 isl_map *id;
11209 isl_bool equal, is_identity;
11211 space = isl_map_get_space(map);
11212 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
11213 isl_space_free(space);
11214 if (equal < 0 || !equal)
11215 return equal;
11217 id = isl_map_identity(isl_map_get_space(map));
11218 is_identity = isl_map_is_subset(map, id);
11219 isl_map_free(id);
11221 return is_identity;
11224 int isl_map_is_translation(__isl_keep isl_map *map)
11226 int ok;
11227 isl_set *delta;
11229 delta = isl_map_deltas(isl_map_copy(map));
11230 ok = isl_set_is_singleton(delta);
11231 isl_set_free(delta);
11233 return ok;
11236 static int unique(isl_int *p, unsigned pos, unsigned len)
11238 if (isl_seq_first_non_zero(p, pos) != -1)
11239 return 0;
11240 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11241 return 0;
11242 return 1;
11245 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11247 int i, j;
11248 unsigned nvar;
11249 unsigned ovar;
11251 if (!bset)
11252 return isl_bool_error;
11254 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
11255 return isl_bool_false;
11257 nvar = isl_basic_set_dim(bset, isl_dim_set);
11258 ovar = isl_space_offset(bset->dim, isl_dim_set);
11259 for (j = 0; j < nvar; ++j) {
11260 int lower = 0, upper = 0;
11261 for (i = 0; i < bset->n_eq; ++i) {
11262 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11263 continue;
11264 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11265 return isl_bool_false;
11266 break;
11268 if (i < bset->n_eq)
11269 continue;
11270 for (i = 0; i < bset->n_ineq; ++i) {
11271 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11272 continue;
11273 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11274 return isl_bool_false;
11275 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11276 lower = 1;
11277 else
11278 upper = 1;
11280 if (!lower || !upper)
11281 return isl_bool_false;
11284 return isl_bool_true;
11287 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11289 if (!set)
11290 return isl_bool_error;
11291 if (set->n != 1)
11292 return isl_bool_false;
11294 return isl_basic_set_is_box(set->p[0]);
11297 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11299 if (!bset)
11300 return isl_bool_error;
11302 return isl_space_is_wrapping(bset->dim);
11305 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11307 if (!set)
11308 return isl_bool_error;
11310 return isl_space_is_wrapping(set->dim);
11313 /* Modify the space of "map" through a call to "change".
11314 * If "can_change" is set (not NULL), then first call it to check
11315 * if the modification is allowed, printing the error message "cannot_change"
11316 * if it is not.
11318 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11319 isl_bool (*can_change)(__isl_keep isl_map *map),
11320 const char *cannot_change,
11321 __isl_give isl_space *(*change)(__isl_take isl_space *space))
11323 isl_bool ok;
11324 isl_space *space;
11326 if (!map)
11327 return NULL;
11329 ok = can_change ? can_change(map) : isl_bool_true;
11330 if (ok < 0)
11331 return isl_map_free(map);
11332 if (!ok)
11333 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11334 return isl_map_free(map));
11336 space = change(isl_map_get_space(map));
11337 map = isl_map_reset_space(map, space);
11339 return map;
11342 /* Is the domain of "map" a wrapped relation?
11344 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11346 if (!map)
11347 return isl_bool_error;
11349 return isl_space_domain_is_wrapping(map->dim);
11352 /* Does "map" have a wrapped relation in both domain and range?
11354 isl_bool isl_map_is_product(__isl_keep isl_map *map)
11356 return isl_space_is_product(isl_map_peek_space(map));
11359 /* Is the range of "map" a wrapped relation?
11361 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
11363 if (!map)
11364 return isl_bool_error;
11366 return isl_space_range_is_wrapping(map->dim);
11369 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
11371 bmap = isl_basic_map_cow(bmap);
11372 if (!bmap)
11373 return NULL;
11375 bmap->dim = isl_space_wrap(bmap->dim);
11376 if (!bmap->dim)
11377 goto error;
11379 bmap = isl_basic_map_finalize(bmap);
11381 return bset_from_bmap(bmap);
11382 error:
11383 isl_basic_map_free(bmap);
11384 return NULL;
11387 /* Given a map A -> B, return the set (A -> B).
11389 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
11391 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
11394 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
11396 bset = isl_basic_set_cow(bset);
11397 if (!bset)
11398 return NULL;
11400 bset->dim = isl_space_unwrap(bset->dim);
11401 if (!bset->dim)
11402 goto error;
11404 bset = isl_basic_set_finalize(bset);
11406 return bset_to_bmap(bset);
11407 error:
11408 isl_basic_set_free(bset);
11409 return NULL;
11412 /* Given a set (A -> B), return the map A -> B.
11413 * Error out if "set" is not of the form (A -> B).
11415 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
11417 return isl_map_change_space(set, &isl_set_is_wrapping,
11418 "not a wrapping set", &isl_space_unwrap);
11421 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
11422 enum isl_dim_type type)
11424 if (!bmap)
11425 return NULL;
11427 if (!isl_space_is_named_or_nested(bmap->dim, type))
11428 return bmap;
11430 bmap = isl_basic_map_cow(bmap);
11431 if (!bmap)
11432 return NULL;
11434 bmap->dim = isl_space_reset(bmap->dim, type);
11435 if (!bmap->dim)
11436 goto error;
11438 bmap = isl_basic_map_finalize(bmap);
11440 return bmap;
11441 error:
11442 isl_basic_map_free(bmap);
11443 return NULL;
11446 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
11447 enum isl_dim_type type)
11449 int i;
11451 if (!map)
11452 return NULL;
11454 if (!isl_space_is_named_or_nested(map->dim, type))
11455 return map;
11457 map = isl_map_cow(map);
11458 if (!map)
11459 return NULL;
11461 for (i = 0; i < map->n; ++i) {
11462 map->p[i] = isl_basic_map_reset(map->p[i], type);
11463 if (!map->p[i])
11464 goto error;
11466 map->dim = isl_space_reset(map->dim, type);
11467 if (!map->dim)
11468 goto error;
11470 return map;
11471 error:
11472 isl_map_free(map);
11473 return NULL;
11476 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11478 if (!bmap)
11479 return NULL;
11481 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11482 return bmap;
11484 bmap = isl_basic_map_cow(bmap);
11485 if (!bmap)
11486 return NULL;
11488 bmap->dim = isl_space_flatten(bmap->dim);
11489 if (!bmap->dim)
11490 goto error;
11492 bmap = isl_basic_map_finalize(bmap);
11494 return bmap;
11495 error:
11496 isl_basic_map_free(bmap);
11497 return NULL;
11500 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11502 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11505 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11506 __isl_take isl_basic_map *bmap)
11508 if (!bmap)
11509 return NULL;
11511 if (!bmap->dim->nested[0])
11512 return bmap;
11514 bmap = isl_basic_map_cow(bmap);
11515 if (!bmap)
11516 return NULL;
11518 bmap->dim = isl_space_flatten_domain(bmap->dim);
11519 if (!bmap->dim)
11520 goto error;
11522 bmap = isl_basic_map_finalize(bmap);
11524 return bmap;
11525 error:
11526 isl_basic_map_free(bmap);
11527 return NULL;
11530 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11531 __isl_take isl_basic_map *bmap)
11533 if (!bmap)
11534 return NULL;
11536 if (!bmap->dim->nested[1])
11537 return bmap;
11539 bmap = isl_basic_map_cow(bmap);
11540 if (!bmap)
11541 return NULL;
11543 bmap->dim = isl_space_flatten_range(bmap->dim);
11544 if (!bmap->dim)
11545 goto error;
11547 bmap = isl_basic_map_finalize(bmap);
11549 return bmap;
11550 error:
11551 isl_basic_map_free(bmap);
11552 return NULL;
11555 /* Remove any internal structure from the spaces of domain and range of "map".
11557 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11559 if (!map)
11560 return NULL;
11562 if (!map->dim->nested[0] && !map->dim->nested[1])
11563 return map;
11565 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11568 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11570 return set_from_map(isl_map_flatten(set_to_map(set)));
11573 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11575 isl_space *space, *flat_space;
11576 isl_map *map;
11578 space = isl_set_get_space(set);
11579 flat_space = isl_space_flatten(isl_space_copy(space));
11580 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
11581 flat_space));
11582 map = isl_map_intersect_domain(map, set);
11584 return map;
11587 /* Remove any internal structure from the space of the domain of "map".
11589 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11591 if (!map)
11592 return NULL;
11594 if (!map->dim->nested[0])
11595 return map;
11597 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11600 /* Remove any internal structure from the space of the range of "map".
11602 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11604 if (!map)
11605 return NULL;
11607 if (!map->dim->nested[1])
11608 return map;
11610 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11613 /* Reorder the dimensions of "bmap" according to the given dim_map
11614 * and set the dimension specification to "space" and
11615 * perform Gaussian elimination on the result.
11617 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11618 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
11620 isl_basic_map *res;
11621 unsigned flags;
11622 unsigned n_div;
11624 if (!bmap || !space || !dim_map)
11625 goto error;
11627 flags = bmap->flags;
11628 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11629 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
11630 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11631 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11632 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
11633 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11634 if (res)
11635 res->flags = flags;
11636 res = isl_basic_map_gauss(res, NULL);
11637 res = isl_basic_map_finalize(res);
11638 return res;
11639 error:
11640 isl_dim_map_free(dim_map);
11641 isl_basic_map_free(bmap);
11642 isl_space_free(space);
11643 return NULL;
11646 /* Reorder the dimensions of "map" according to given reordering.
11648 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11649 __isl_take isl_reordering *r)
11651 int i;
11652 struct isl_dim_map *dim_map;
11654 map = isl_map_cow(map);
11655 dim_map = isl_dim_map_from_reordering(r);
11656 if (!map || !r || !dim_map)
11657 goto error;
11659 for (i = 0; i < map->n; ++i) {
11660 struct isl_dim_map *dim_map_i;
11661 isl_space *space;
11663 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11665 space = isl_reordering_get_space(r);
11666 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
11668 if (!map->p[i])
11669 goto error;
11672 map = isl_map_reset_space(map, isl_reordering_get_space(r));
11673 map = isl_map_unmark_normalized(map);
11675 isl_reordering_free(r);
11676 isl_dim_map_free(dim_map);
11677 return map;
11678 error:
11679 isl_dim_map_free(dim_map);
11680 isl_map_free(map);
11681 isl_reordering_free(r);
11682 return NULL;
11685 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11686 __isl_take isl_reordering *r)
11688 return set_from_map(isl_map_realign(set_to_map(set), r));
11691 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11692 __isl_take isl_space *model)
11694 isl_ctx *ctx;
11695 isl_bool aligned;
11697 if (!map || !model)
11698 goto error;
11700 ctx = isl_space_get_ctx(model);
11701 if (!isl_space_has_named_params(model))
11702 isl_die(ctx, isl_error_invalid,
11703 "model has unnamed parameters", goto error);
11704 if (isl_map_check_named_params(map) < 0)
11705 goto error;
11706 aligned = isl_map_space_has_equal_params(map, model);
11707 if (aligned < 0)
11708 goto error;
11709 if (!aligned) {
11710 isl_reordering *exp;
11712 exp = isl_parameter_alignment_reordering(map->dim, model);
11713 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11714 map = isl_map_realign(map, exp);
11717 isl_space_free(model);
11718 return map;
11719 error:
11720 isl_space_free(model);
11721 isl_map_free(map);
11722 return NULL;
11725 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11726 __isl_take isl_space *model)
11728 return isl_map_align_params(set, model);
11731 /* Align the parameters of "bmap" to those of "model", introducing
11732 * additional parameters if needed.
11734 __isl_give isl_basic_map *isl_basic_map_align_params(
11735 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11737 isl_ctx *ctx;
11738 isl_bool equal_params;
11740 if (!bmap || !model)
11741 goto error;
11743 ctx = isl_space_get_ctx(model);
11744 if (!isl_space_has_named_params(model))
11745 isl_die(ctx, isl_error_invalid,
11746 "model has unnamed parameters", goto error);
11747 if (isl_basic_map_check_named_params(bmap) < 0)
11748 goto error;
11749 equal_params = isl_space_has_equal_params(bmap->dim, model);
11750 if (equal_params < 0)
11751 goto error;
11752 if (!equal_params) {
11753 isl_reordering *exp;
11754 struct isl_dim_map *dim_map;
11756 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11757 exp = isl_reordering_extend_space(exp,
11758 isl_basic_map_get_space(bmap));
11759 dim_map = isl_dim_map_from_reordering(exp);
11760 bmap = isl_basic_map_realign(bmap,
11761 isl_reordering_get_space(exp),
11762 isl_dim_map_extend(dim_map, bmap));
11763 isl_reordering_free(exp);
11764 isl_dim_map_free(dim_map);
11767 isl_space_free(model);
11768 return bmap;
11769 error:
11770 isl_space_free(model);
11771 isl_basic_map_free(bmap);
11772 return NULL;
11775 /* Do "bset" and "space" have the same parameters?
11777 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
11778 __isl_keep isl_space *space)
11780 isl_space *bset_space;
11782 bset_space = isl_basic_set_peek_space(bset);
11783 return isl_space_has_equal_params(bset_space, space);
11786 /* Do "map" and "space" have the same parameters?
11788 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
11789 __isl_keep isl_space *space)
11791 isl_space *map_space;
11793 map_space = isl_map_peek_space(map);
11794 return isl_space_has_equal_params(map_space, space);
11797 /* Do "set" and "space" have the same parameters?
11799 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
11800 __isl_keep isl_space *space)
11802 return isl_map_space_has_equal_params(set_to_map(set), space);
11805 /* Align the parameters of "bset" to those of "model", introducing
11806 * additional parameters if needed.
11808 __isl_give isl_basic_set *isl_basic_set_align_params(
11809 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11811 return isl_basic_map_align_params(bset, model);
11814 /* Drop all parameters not referenced by "map".
11816 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
11818 int i;
11820 if (isl_map_check_named_params(map) < 0)
11821 return isl_map_free(map);
11823 for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
11824 isl_bool involves;
11826 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
11827 if (involves < 0)
11828 return isl_map_free(map);
11829 if (!involves)
11830 map = isl_map_project_out(map, isl_dim_param, i, 1);
11833 return map;
11836 /* Drop all parameters not referenced by "set".
11838 __isl_give isl_set *isl_set_drop_unused_params(
11839 __isl_take isl_set *set)
11841 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
11844 /* Drop all parameters not referenced by "bmap".
11846 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
11847 __isl_take isl_basic_map *bmap)
11849 int i;
11851 if (isl_basic_map_check_named_params(bmap) < 0)
11852 return isl_basic_map_free(bmap);
11854 for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
11855 isl_bool involves;
11857 involves = isl_basic_map_involves_dims(bmap,
11858 isl_dim_param, i, 1);
11859 if (involves < 0)
11860 return isl_basic_map_free(bmap);
11861 if (!involves)
11862 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
11865 return bmap;
11868 /* Drop all parameters not referenced by "bset".
11870 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
11871 __isl_take isl_basic_set *bset)
11873 return bset_from_bmap(isl_basic_map_drop_unused_params(
11874 bset_to_bmap(bset)));
11877 __isl_give isl_mat *isl_basic_map_equalities_matrix(
11878 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11879 enum isl_dim_type c2, enum isl_dim_type c3,
11880 enum isl_dim_type c4, enum isl_dim_type c5)
11882 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11883 struct isl_mat *mat;
11884 int i, j, k;
11885 int pos;
11887 if (!bmap)
11888 return NULL;
11889 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11890 isl_basic_map_total_dim(bmap) + 1);
11891 if (!mat)
11892 return NULL;
11893 for (i = 0; i < bmap->n_eq; ++i)
11894 for (j = 0, pos = 0; j < 5; ++j) {
11895 int off = isl_basic_map_offset(bmap, c[j]);
11896 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11897 isl_int_set(mat->row[i][pos],
11898 bmap->eq[i][off + k]);
11899 ++pos;
11903 return mat;
11906 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11907 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11908 enum isl_dim_type c2, enum isl_dim_type c3,
11909 enum isl_dim_type c4, enum isl_dim_type c5)
11911 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11912 struct isl_mat *mat;
11913 int i, j, k;
11914 int pos;
11916 if (!bmap)
11917 return NULL;
11918 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11919 isl_basic_map_total_dim(bmap) + 1);
11920 if (!mat)
11921 return NULL;
11922 for (i = 0; i < bmap->n_ineq; ++i)
11923 for (j = 0, pos = 0; j < 5; ++j) {
11924 int off = isl_basic_map_offset(bmap, c[j]);
11925 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11926 isl_int_set(mat->row[i][pos],
11927 bmap->ineq[i][off + k]);
11928 ++pos;
11932 return mat;
11935 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11936 __isl_take isl_space *space,
11937 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11938 enum isl_dim_type c2, enum isl_dim_type c3,
11939 enum isl_dim_type c4, enum isl_dim_type c5)
11941 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11942 isl_basic_map *bmap = NULL;
11943 unsigned total;
11944 unsigned extra;
11945 int i, j, k, l;
11946 int pos;
11948 if (!space || !eq || !ineq)
11949 goto error;
11951 if (eq->n_col != ineq->n_col)
11952 isl_die(space->ctx, isl_error_invalid,
11953 "equalities and inequalities matrices should have "
11954 "same number of columns", goto error);
11956 total = 1 + isl_space_dim(space, isl_dim_all);
11958 if (eq->n_col < total)
11959 isl_die(space->ctx, isl_error_invalid,
11960 "number of columns too small", goto error);
11962 extra = eq->n_col - total;
11964 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
11965 eq->n_row, ineq->n_row);
11966 if (!bmap)
11967 goto error;
11968 for (i = 0; i < extra; ++i) {
11969 k = isl_basic_map_alloc_div(bmap);
11970 if (k < 0)
11971 goto error;
11972 isl_int_set_si(bmap->div[k][0], 0);
11974 for (i = 0; i < eq->n_row; ++i) {
11975 l = isl_basic_map_alloc_equality(bmap);
11976 if (l < 0)
11977 goto error;
11978 for (j = 0, pos = 0; j < 5; ++j) {
11979 int off = isl_basic_map_offset(bmap, c[j]);
11980 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11981 isl_int_set(bmap->eq[l][off + k],
11982 eq->row[i][pos]);
11983 ++pos;
11987 for (i = 0; i < ineq->n_row; ++i) {
11988 l = isl_basic_map_alloc_inequality(bmap);
11989 if (l < 0)
11990 goto error;
11991 for (j = 0, pos = 0; j < 5; ++j) {
11992 int off = isl_basic_map_offset(bmap, c[j]);
11993 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11994 isl_int_set(bmap->ineq[l][off + k],
11995 ineq->row[i][pos]);
11996 ++pos;
12001 isl_space_free(space);
12002 isl_mat_free(eq);
12003 isl_mat_free(ineq);
12005 bmap = isl_basic_map_simplify(bmap);
12006 return isl_basic_map_finalize(bmap);
12007 error:
12008 isl_space_free(space);
12009 isl_mat_free(eq);
12010 isl_mat_free(ineq);
12011 isl_basic_map_free(bmap);
12012 return NULL;
12015 __isl_give isl_mat *isl_basic_set_equalities_matrix(
12016 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12017 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12019 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12020 c1, c2, c3, c4, isl_dim_in);
12023 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12024 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12025 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12027 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12028 c1, c2, c3, c4, isl_dim_in);
12031 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12032 __isl_take isl_space *dim,
12033 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12034 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12036 isl_basic_map *bmap;
12037 bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
12038 c1, c2, c3, c4, isl_dim_in);
12039 return bset_from_bmap(bmap);
12042 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12044 if (!bmap)
12045 return isl_bool_error;
12047 return isl_space_can_zip(bmap->dim);
12050 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12052 if (!map)
12053 return isl_bool_error;
12055 return isl_space_can_zip(map->dim);
12058 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12059 * (A -> C) -> (B -> D).
12061 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12063 unsigned pos;
12064 unsigned n1;
12065 unsigned n2;
12067 if (!bmap)
12068 return NULL;
12070 if (!isl_basic_map_can_zip(bmap))
12071 isl_die(bmap->ctx, isl_error_invalid,
12072 "basic map cannot be zipped", goto error);
12073 pos = isl_basic_map_offset(bmap, isl_dim_in) +
12074 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12075 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12076 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12077 bmap = isl_basic_map_cow(bmap);
12078 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12079 if (!bmap)
12080 return NULL;
12081 bmap->dim = isl_space_zip(bmap->dim);
12082 if (!bmap->dim)
12083 goto error;
12084 bmap = isl_basic_map_mark_final(bmap);
12085 return bmap;
12086 error:
12087 isl_basic_map_free(bmap);
12088 return NULL;
12091 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12092 * (A -> C) -> (B -> D).
12094 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12096 int i;
12098 if (!map)
12099 return NULL;
12101 if (!isl_map_can_zip(map))
12102 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12103 goto error);
12105 map = isl_map_cow(map);
12106 if (!map)
12107 return NULL;
12109 for (i = 0; i < map->n; ++i) {
12110 map->p[i] = isl_basic_map_zip(map->p[i]);
12111 if (!map->p[i])
12112 goto error;
12115 map->dim = isl_space_zip(map->dim);
12116 if (!map->dim)
12117 goto error;
12119 return map;
12120 error:
12121 isl_map_free(map);
12122 return NULL;
12125 /* Can we apply isl_basic_map_curry to "bmap"?
12126 * That is, does it have a nested relation in its domain?
12128 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12130 if (!bmap)
12131 return isl_bool_error;
12133 return isl_space_can_curry(bmap->dim);
12136 /* Can we apply isl_map_curry to "map"?
12137 * That is, does it have a nested relation in its domain?
12139 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12141 if (!map)
12142 return isl_bool_error;
12144 return isl_space_can_curry(map->dim);
12147 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12148 * A -> (B -> C).
12150 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12153 if (!bmap)
12154 return NULL;
12156 if (!isl_basic_map_can_curry(bmap))
12157 isl_die(bmap->ctx, isl_error_invalid,
12158 "basic map cannot be curried", goto error);
12159 bmap = isl_basic_map_cow(bmap);
12160 if (!bmap)
12161 return NULL;
12162 bmap->dim = isl_space_curry(bmap->dim);
12163 if (!bmap->dim)
12164 goto error;
12165 bmap = isl_basic_map_mark_final(bmap);
12166 return bmap;
12167 error:
12168 isl_basic_map_free(bmap);
12169 return NULL;
12172 /* Given a map (A -> B) -> C, return the corresponding map
12173 * A -> (B -> C).
12175 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
12177 return isl_map_change_space(map, &isl_map_can_curry,
12178 "map cannot be curried", &isl_space_curry);
12181 /* Can isl_map_range_curry be applied to "map"?
12182 * That is, does it have a nested relation in its range,
12183 * the domain of which is itself a nested relation?
12185 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
12187 if (!map)
12188 return isl_bool_error;
12190 return isl_space_can_range_curry(map->dim);
12193 /* Given a map A -> ((B -> C) -> D), return the corresponding map
12194 * A -> (B -> (C -> D)).
12196 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
12198 return isl_map_change_space(map, &isl_map_can_range_curry,
12199 "map range cannot be curried",
12200 &isl_space_range_curry);
12203 /* Can we apply isl_basic_map_uncurry to "bmap"?
12204 * That is, does it have a nested relation in its domain?
12206 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
12208 if (!bmap)
12209 return isl_bool_error;
12211 return isl_space_can_uncurry(bmap->dim);
12214 /* Can we apply isl_map_uncurry to "map"?
12215 * That is, does it have a nested relation in its domain?
12217 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
12219 if (!map)
12220 return isl_bool_error;
12222 return isl_space_can_uncurry(map->dim);
12225 /* Given a basic map A -> (B -> C), return the corresponding basic map
12226 * (A -> B) -> C.
12228 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
12231 if (!bmap)
12232 return NULL;
12234 if (!isl_basic_map_can_uncurry(bmap))
12235 isl_die(bmap->ctx, isl_error_invalid,
12236 "basic map cannot be uncurried",
12237 return isl_basic_map_free(bmap));
12238 bmap = isl_basic_map_cow(bmap);
12239 if (!bmap)
12240 return NULL;
12241 bmap->dim = isl_space_uncurry(bmap->dim);
12242 if (!bmap->dim)
12243 return isl_basic_map_free(bmap);
12244 bmap = isl_basic_map_mark_final(bmap);
12245 return bmap;
12248 /* Given a map A -> (B -> C), return the corresponding map
12249 * (A -> B) -> C.
12251 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
12253 return isl_map_change_space(map, &isl_map_can_uncurry,
12254 "map cannot be uncurried", &isl_space_uncurry);
12257 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
12258 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12260 return isl_map_equate(set, type1, pos1, type2, pos2);
12263 /* Construct a basic map where the given dimensions are equal to each other.
12265 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
12266 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12268 isl_basic_map *bmap = NULL;
12269 int i;
12271 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12272 isl_space_check_range(space, type2, pos2, 1) < 0)
12273 goto error;
12275 if (type1 == type2 && pos1 == pos2)
12276 return isl_basic_map_universe(space);
12278 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
12279 i = isl_basic_map_alloc_equality(bmap);
12280 if (i < 0)
12281 goto error;
12282 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12283 pos1 += isl_basic_map_offset(bmap, type1);
12284 pos2 += isl_basic_map_offset(bmap, type2);
12285 isl_int_set_si(bmap->eq[i][pos1], -1);
12286 isl_int_set_si(bmap->eq[i][pos2], 1);
12287 bmap = isl_basic_map_finalize(bmap);
12288 isl_space_free(space);
12289 return bmap;
12290 error:
12291 isl_space_free(space);
12292 isl_basic_map_free(bmap);
12293 return NULL;
12296 /* Add a constraint imposing that the given two dimensions are equal.
12298 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
12299 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12301 isl_basic_map *eq;
12303 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12305 bmap = isl_basic_map_intersect(bmap, eq);
12307 return bmap;
12310 /* Add a constraint imposing that the given two dimensions are equal.
12312 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
12313 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12315 isl_basic_map *bmap;
12317 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
12319 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12321 return map;
12324 /* Add a constraint imposing that the given two dimensions have opposite values.
12326 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
12327 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12329 isl_basic_map *bmap = NULL;
12330 int i;
12332 if (isl_map_check_range(map, type1, pos1, 1) < 0)
12333 return isl_map_free(map);
12334 if (isl_map_check_range(map, type2, pos2, 1) < 0)
12335 return isl_map_free(map);
12337 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
12338 i = isl_basic_map_alloc_equality(bmap);
12339 if (i < 0)
12340 goto error;
12341 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12342 pos1 += isl_basic_map_offset(bmap, type1);
12343 pos2 += isl_basic_map_offset(bmap, type2);
12344 isl_int_set_si(bmap->eq[i][pos1], 1);
12345 isl_int_set_si(bmap->eq[i][pos2], 1);
12346 bmap = isl_basic_map_finalize(bmap);
12348 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12350 return map;
12351 error:
12352 isl_basic_map_free(bmap);
12353 isl_map_free(map);
12354 return NULL;
12357 /* Construct a constraint imposing that the value of the first dimension is
12358 * greater than or equal to that of the second.
12360 static __isl_give isl_constraint *constraint_order_ge(
12361 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
12362 enum isl_dim_type type2, int pos2)
12364 isl_constraint *c;
12366 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12367 isl_space_check_range(space, type2, pos2, 1) < 0)
12368 space = isl_space_free(space);
12369 if (!space)
12370 return NULL;
12372 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
12374 if (type1 == type2 && pos1 == pos2)
12375 return c;
12377 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
12378 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
12380 return c;
12383 /* Add a constraint imposing that the value of the first dimension is
12384 * greater than or equal to that of the second.
12386 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
12387 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12389 isl_constraint *c;
12390 isl_space *space;
12392 if (type1 == type2 && pos1 == pos2)
12393 return bmap;
12394 space = isl_basic_map_get_space(bmap);
12395 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12396 bmap = isl_basic_map_add_constraint(bmap, c);
12398 return bmap;
12401 /* Add a constraint imposing that the value of the first dimension is
12402 * greater than or equal to that of the second.
12404 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12405 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12407 isl_constraint *c;
12408 isl_space *space;
12410 if (type1 == type2 && pos1 == pos2)
12411 return map;
12412 space = isl_map_get_space(map);
12413 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12414 map = isl_map_add_constraint(map, c);
12416 return map;
12419 /* Add a constraint imposing that the value of the first dimension is
12420 * less than or equal to that of the second.
12422 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12423 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12425 return isl_map_order_ge(map, type2, pos2, type1, pos1);
12428 /* Construct a basic map where the value of the first dimension is
12429 * greater than that of the second.
12431 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12432 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12434 isl_basic_map *bmap = NULL;
12435 int i;
12437 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12438 isl_space_check_range(space, type2, pos2, 1) < 0)
12439 goto error;
12441 if (type1 == type2 && pos1 == pos2)
12442 return isl_basic_map_empty(space);
12444 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12445 i = isl_basic_map_alloc_inequality(bmap);
12446 if (i < 0)
12447 return isl_basic_map_free(bmap);
12448 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12449 pos1 += isl_basic_map_offset(bmap, type1);
12450 pos2 += isl_basic_map_offset(bmap, type2);
12451 isl_int_set_si(bmap->ineq[i][pos1], 1);
12452 isl_int_set_si(bmap->ineq[i][pos2], -1);
12453 isl_int_set_si(bmap->ineq[i][0], -1);
12454 bmap = isl_basic_map_finalize(bmap);
12456 return bmap;
12457 error:
12458 isl_space_free(space);
12459 isl_basic_map_free(bmap);
12460 return NULL;
12463 /* Add a constraint imposing that the value of the first dimension is
12464 * greater than that of the second.
12466 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12467 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12469 isl_basic_map *gt;
12471 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12473 bmap = isl_basic_map_intersect(bmap, gt);
12475 return bmap;
12478 /* Add a constraint imposing that the value of the first dimension is
12479 * greater than that of the second.
12481 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12482 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12484 isl_basic_map *bmap;
12486 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12488 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12490 return map;
12493 /* Add a constraint imposing that the value of the first dimension is
12494 * smaller than that of the second.
12496 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12497 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12499 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12502 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12503 int pos)
12505 isl_aff *div;
12506 isl_local_space *ls;
12508 if (!bmap)
12509 return NULL;
12511 if (!isl_basic_map_divs_known(bmap))
12512 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12513 "some divs are unknown", return NULL);
12515 ls = isl_basic_map_get_local_space(bmap);
12516 div = isl_local_space_get_div(ls, pos);
12517 isl_local_space_free(ls);
12519 return div;
12522 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12523 int pos)
12525 return isl_basic_map_get_div(bset, pos);
12528 /* Plug in "subs" for dimension "type", "pos" of "bset".
12530 * Let i be the dimension to replace and let "subs" be of the form
12532 * f/d
12534 * Any integer division with a non-zero coefficient for i,
12536 * floor((a i + g)/m)
12538 * is replaced by
12540 * floor((a f + d g)/(m d))
12542 * Constraints of the form
12544 * a i + g
12546 * are replaced by
12548 * a f + d g
12550 * We currently require that "subs" is an integral expression.
12551 * Handling rational expressions may require us to add stride constraints
12552 * as we do in isl_basic_set_preimage_multi_aff.
12554 __isl_give isl_basic_set *isl_basic_set_substitute(
12555 __isl_take isl_basic_set *bset,
12556 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12558 int i;
12559 isl_int v;
12560 isl_ctx *ctx;
12562 if (bset && isl_basic_set_plain_is_empty(bset))
12563 return bset;
12565 bset = isl_basic_set_cow(bset);
12566 if (!bset || !subs)
12567 goto error;
12569 ctx = isl_basic_set_get_ctx(bset);
12570 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12571 isl_die(ctx, isl_error_invalid,
12572 "spaces don't match", goto error);
12573 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12574 isl_die(ctx, isl_error_unsupported,
12575 "cannot handle divs yet", goto error);
12576 if (!isl_int_is_one(subs->v->el[0]))
12577 isl_die(ctx, isl_error_invalid,
12578 "can only substitute integer expressions", goto error);
12580 pos += isl_basic_set_offset(bset, type);
12582 isl_int_init(v);
12584 for (i = 0; i < bset->n_eq; ++i) {
12585 if (isl_int_is_zero(bset->eq[i][pos]))
12586 continue;
12587 isl_int_set(v, bset->eq[i][pos]);
12588 isl_int_set_si(bset->eq[i][pos], 0);
12589 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12590 v, subs->v->el + 1, subs->v->size - 1);
12593 for (i = 0; i < bset->n_ineq; ++i) {
12594 if (isl_int_is_zero(bset->ineq[i][pos]))
12595 continue;
12596 isl_int_set(v, bset->ineq[i][pos]);
12597 isl_int_set_si(bset->ineq[i][pos], 0);
12598 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12599 v, subs->v->el + 1, subs->v->size - 1);
12602 for (i = 0; i < bset->n_div; ++i) {
12603 if (isl_int_is_zero(bset->div[i][1 + pos]))
12604 continue;
12605 isl_int_set(v, bset->div[i][1 + pos]);
12606 isl_int_set_si(bset->div[i][1 + pos], 0);
12607 isl_seq_combine(bset->div[i] + 1,
12608 subs->v->el[0], bset->div[i] + 1,
12609 v, subs->v->el + 1, subs->v->size - 1);
12610 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12613 isl_int_clear(v);
12615 bset = isl_basic_set_simplify(bset);
12616 return isl_basic_set_finalize(bset);
12617 error:
12618 isl_basic_set_free(bset);
12619 return NULL;
12622 /* Plug in "subs" for dimension "type", "pos" of "set".
12624 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12625 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12627 int i;
12629 if (set && isl_set_plain_is_empty(set))
12630 return set;
12632 set = isl_set_cow(set);
12633 if (!set || !subs)
12634 goto error;
12636 for (i = set->n - 1; i >= 0; --i) {
12637 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12638 set = set_from_map(remove_if_empty(set_to_map(set), i));
12639 if (!set)
12640 return NULL;
12643 return set;
12644 error:
12645 isl_set_free(set);
12646 return NULL;
12649 /* Check if the range of "ma" is compatible with the domain or range
12650 * (depending on "type") of "bmap".
12652 static isl_stat check_basic_map_compatible_range_multi_aff(
12653 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12654 __isl_keep isl_multi_aff *ma)
12656 isl_bool m;
12657 isl_space *ma_space;
12659 ma_space = isl_multi_aff_get_space(ma);
12661 m = isl_space_has_equal_params(bmap->dim, ma_space);
12662 if (m < 0)
12663 goto error;
12664 if (!m)
12665 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12666 "parameters don't match", goto error);
12667 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12668 if (m < 0)
12669 goto error;
12670 if (!m)
12671 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12672 "spaces don't match", goto error);
12674 isl_space_free(ma_space);
12675 return isl_stat_ok;
12676 error:
12677 isl_space_free(ma_space);
12678 return isl_stat_error;
12681 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12682 * coefficients before the transformed range of dimensions,
12683 * the "n_after" coefficients after the transformed range of dimensions
12684 * and the coefficients of the other divs in "bmap".
12686 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
12687 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12689 int i;
12690 int n_param;
12691 int n_set;
12692 isl_local_space *ls;
12694 if (n_div == 0)
12695 return bmap;
12697 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
12698 if (!ls)
12699 return isl_basic_map_free(bmap);
12701 n_param = isl_local_space_dim(ls, isl_dim_param);
12702 n_set = isl_local_space_dim(ls, isl_dim_set);
12703 for (i = 0; i < n_div; ++i) {
12704 int o_bmap = 0, o_ls = 0;
12706 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12707 o_bmap += 1 + 1 + n_param;
12708 o_ls += 1 + 1 + n_param;
12709 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12710 o_bmap += n_before;
12711 isl_seq_cpy(bmap->div[i] + o_bmap,
12712 ls->div->row[i] + o_ls, n_set);
12713 o_bmap += n_set;
12714 o_ls += n_set;
12715 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12716 o_bmap += n_after;
12717 isl_seq_cpy(bmap->div[i] + o_bmap,
12718 ls->div->row[i] + o_ls, n_div);
12719 o_bmap += n_div;
12720 o_ls += n_div;
12721 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12722 bmap = isl_basic_map_add_div_constraints(bmap, i);
12723 if (!bmap)
12724 goto error;
12727 isl_local_space_free(ls);
12728 return bmap;
12729 error:
12730 isl_local_space_free(ls);
12731 return isl_basic_map_free(bmap);
12734 /* How many stride constraints does "ma" enforce?
12735 * That is, how many of the affine expressions have a denominator
12736 * different from one?
12738 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12740 int i;
12741 int strides = 0;
12743 for (i = 0; i < ma->n; ++i)
12744 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
12745 strides++;
12747 return strides;
12750 /* For each affine expression in ma of the form
12752 * x_i = (f_i y + h_i)/m_i
12754 * with m_i different from one, add a constraint to "bmap"
12755 * of the form
12757 * f_i y + h_i = m_i alpha_i
12759 * with alpha_i an additional existentially quantified variable.
12761 * The input variables of "ma" correspond to a subset of the variables
12762 * of "bmap". There are "n_before" variables in "bmap" before this
12763 * subset and "n_after" variables after this subset.
12764 * The integer divisions of the affine expressions in "ma" are assumed
12765 * to have been aligned. There are "n_div_ma" of them and
12766 * they appear first in "bmap", straight after the "n_after" variables.
12768 static __isl_give isl_basic_map *add_ma_strides(
12769 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12770 int n_before, int n_after, int n_div_ma)
12772 int i, k;
12773 int div;
12774 int total;
12775 int n_param;
12776 int n_in;
12778 total = isl_basic_map_total_dim(bmap);
12779 n_param = isl_multi_aff_dim(ma, isl_dim_param);
12780 n_in = isl_multi_aff_dim(ma, isl_dim_in);
12781 for (i = 0; i < ma->n; ++i) {
12782 int o_bmap = 0, o_ma = 1;
12784 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
12785 continue;
12786 div = isl_basic_map_alloc_div(bmap);
12787 k = isl_basic_map_alloc_equality(bmap);
12788 if (div < 0 || k < 0)
12789 goto error;
12790 isl_int_set_si(bmap->div[div][0], 0);
12791 isl_seq_cpy(bmap->eq[k] + o_bmap,
12792 ma->u.p[i]->v->el + o_ma, 1 + n_param);
12793 o_bmap += 1 + n_param;
12794 o_ma += 1 + n_param;
12795 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12796 o_bmap += n_before;
12797 isl_seq_cpy(bmap->eq[k] + o_bmap,
12798 ma->u.p[i]->v->el + o_ma, n_in);
12799 o_bmap += n_in;
12800 o_ma += n_in;
12801 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12802 o_bmap += n_after;
12803 isl_seq_cpy(bmap->eq[k] + o_bmap,
12804 ma->u.p[i]->v->el + o_ma, n_div_ma);
12805 o_bmap += n_div_ma;
12806 o_ma += n_div_ma;
12807 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12808 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
12809 total++;
12812 return bmap;
12813 error:
12814 isl_basic_map_free(bmap);
12815 return NULL;
12818 /* Replace the domain or range space (depending on "type) of "space" by "set".
12820 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12821 enum isl_dim_type type, __isl_take isl_space *set)
12823 if (type == isl_dim_in) {
12824 space = isl_space_range(space);
12825 space = isl_space_map_from_domain_and_range(set, space);
12826 } else {
12827 space = isl_space_domain(space);
12828 space = isl_space_map_from_domain_and_range(space, set);
12831 return space;
12834 /* Compute the preimage of the domain or range (depending on "type")
12835 * of "bmap" under the function represented by "ma".
12836 * In other words, plug in "ma" in the domain or range of "bmap".
12837 * The result is a basic map that lives in the same space as "bmap"
12838 * except that the domain or range has been replaced by
12839 * the domain space of "ma".
12841 * If bmap is represented by
12843 * A(p) + S u + B x + T v + C(divs) >= 0,
12845 * where u and x are input and output dimensions if type == isl_dim_out
12846 * while x and v are input and output dimensions if type == isl_dim_in,
12847 * and ma is represented by
12849 * x = D(p) + F(y) + G(divs')
12851 * then the result is
12853 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12855 * The divs in the input set are similarly adjusted.
12856 * In particular
12858 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12860 * becomes
12862 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12863 * B_i G(divs') + c_i(divs))/n_i)
12865 * If bmap is not a rational map and if F(y) involves any denominators
12867 * x_i = (f_i y + h_i)/m_i
12869 * then additional constraints are added to ensure that we only
12870 * map back integer points. That is we enforce
12872 * f_i y + h_i = m_i alpha_i
12874 * with alpha_i an additional existentially quantified variable.
12876 * We first copy over the divs from "ma".
12877 * Then we add the modified constraints and divs from "bmap".
12878 * Finally, we add the stride constraints, if needed.
12880 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12881 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12882 __isl_take isl_multi_aff *ma)
12884 int i, k;
12885 isl_space *space;
12886 isl_basic_map *res = NULL;
12887 int n_before, n_after, n_div_bmap, n_div_ma;
12888 isl_int f, c1, c2, g;
12889 isl_bool rational;
12890 int strides;
12892 isl_int_init(f);
12893 isl_int_init(c1);
12894 isl_int_init(c2);
12895 isl_int_init(g);
12897 ma = isl_multi_aff_align_divs(ma);
12898 if (!bmap || !ma)
12899 goto error;
12900 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12901 goto error;
12903 if (type == isl_dim_in) {
12904 n_before = 0;
12905 n_after = isl_basic_map_dim(bmap, isl_dim_out);
12906 } else {
12907 n_before = isl_basic_map_dim(bmap, isl_dim_in);
12908 n_after = 0;
12910 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12911 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
12913 space = isl_multi_aff_get_domain_space(ma);
12914 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12915 rational = isl_basic_map_is_rational(bmap);
12916 strides = rational ? 0 : multi_aff_strides(ma);
12917 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12918 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12919 if (rational)
12920 res = isl_basic_map_set_rational(res);
12922 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12923 if (isl_basic_map_alloc_div(res) < 0)
12924 goto error;
12926 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
12927 if (!res)
12928 goto error;
12930 for (i = 0; i < bmap->n_eq; ++i) {
12931 k = isl_basic_map_alloc_equality(res);
12932 if (k < 0)
12933 goto error;
12934 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
12935 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12938 for (i = 0; i < bmap->n_ineq; ++i) {
12939 k = isl_basic_map_alloc_inequality(res);
12940 if (k < 0)
12941 goto error;
12942 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
12943 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12946 for (i = 0; i < bmap->n_div; ++i) {
12947 if (isl_int_is_zero(bmap->div[i][0])) {
12948 isl_int_set_si(res->div[n_div_ma + i][0], 0);
12949 continue;
12951 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
12952 n_before, n_after, n_div_ma, n_div_bmap,
12953 f, c1, c2, g, 1);
12956 if (strides)
12957 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
12959 isl_int_clear(f);
12960 isl_int_clear(c1);
12961 isl_int_clear(c2);
12962 isl_int_clear(g);
12963 isl_basic_map_free(bmap);
12964 isl_multi_aff_free(ma);
12965 res = isl_basic_map_simplify(res);
12966 return isl_basic_map_finalize(res);
12967 error:
12968 isl_int_clear(f);
12969 isl_int_clear(c1);
12970 isl_int_clear(c2);
12971 isl_int_clear(g);
12972 isl_basic_map_free(bmap);
12973 isl_multi_aff_free(ma);
12974 isl_basic_map_free(res);
12975 return NULL;
12978 /* Compute the preimage of "bset" under the function represented by "ma".
12979 * In other words, plug in "ma" in "bset". The result is a basic set
12980 * that lives in the domain space of "ma".
12982 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
12983 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
12985 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
12988 /* Compute the preimage of the domain of "bmap" under the function
12989 * represented by "ma".
12990 * In other words, plug in "ma" in the domain of "bmap".
12991 * The result is a basic map that lives in the same space as "bmap"
12992 * except that the domain has been replaced by the domain space of "ma".
12994 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
12995 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12997 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13000 /* Compute the preimage of the range of "bmap" under the function
13001 * represented by "ma".
13002 * In other words, plug in "ma" in the range of "bmap".
13003 * The result is a basic map that lives in the same space as "bmap"
13004 * except that the range has been replaced by the domain space of "ma".
13006 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13007 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13009 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13012 /* Check if the range of "ma" is compatible with the domain or range
13013 * (depending on "type") of "map".
13014 * Return isl_stat_error if anything is wrong.
13016 static isl_stat check_map_compatible_range_multi_aff(
13017 __isl_keep isl_map *map, enum isl_dim_type type,
13018 __isl_keep isl_multi_aff *ma)
13020 isl_bool m;
13021 isl_space *ma_space;
13023 ma_space = isl_multi_aff_get_space(ma);
13024 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
13025 isl_space_free(ma_space);
13026 if (m < 0)
13027 return isl_stat_error;
13028 if (!m)
13029 isl_die(isl_map_get_ctx(map), isl_error_invalid,
13030 "spaces don't match", return isl_stat_error);
13031 return isl_stat_ok;
13034 /* Compute the preimage of the domain or range (depending on "type")
13035 * of "map" under the function represented by "ma".
13036 * In other words, plug in "ma" in the domain or range of "map".
13037 * The result is a map that lives in the same space as "map"
13038 * except that the domain or range has been replaced by
13039 * the domain space of "ma".
13041 * The parameters are assumed to have been aligned.
13043 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13044 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13046 int i;
13047 isl_space *space;
13049 map = isl_map_cow(map);
13050 ma = isl_multi_aff_align_divs(ma);
13051 if (!map || !ma)
13052 goto error;
13053 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13054 goto error;
13056 for (i = 0; i < map->n; ++i) {
13057 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13058 isl_multi_aff_copy(ma));
13059 if (!map->p[i])
13060 goto error;
13063 space = isl_multi_aff_get_domain_space(ma);
13064 space = isl_space_set(isl_map_get_space(map), type, space);
13066 isl_space_free(map->dim);
13067 map->dim = space;
13068 if (!map->dim)
13069 goto error;
13071 isl_multi_aff_free(ma);
13072 if (map->n > 1)
13073 ISL_F_CLR(map, ISL_MAP_DISJOINT);
13074 ISL_F_CLR(map, ISL_SET_NORMALIZED);
13075 return map;
13076 error:
13077 isl_multi_aff_free(ma);
13078 isl_map_free(map);
13079 return NULL;
13082 /* Compute the preimage of the domain or range (depending on "type")
13083 * of "map" under the function represented by "ma".
13084 * In other words, plug in "ma" in the domain or range of "map".
13085 * The result is a map that lives in the same space as "map"
13086 * except that the domain or range has been replaced by
13087 * the domain space of "ma".
13089 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13090 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13092 isl_bool aligned;
13094 if (!map || !ma)
13095 goto error;
13097 aligned = isl_map_space_has_equal_params(map, ma->space);
13098 if (aligned < 0)
13099 goto error;
13100 if (aligned)
13101 return map_preimage_multi_aff(map, type, ma);
13103 if (isl_map_check_named_params(map) < 0)
13104 goto error;
13105 if (!isl_space_has_named_params(ma->space))
13106 isl_die(map->ctx, isl_error_invalid,
13107 "unaligned unnamed parameters", goto error);
13108 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13109 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13111 return map_preimage_multi_aff(map, type, ma);
13112 error:
13113 isl_multi_aff_free(ma);
13114 return isl_map_free(map);
13117 /* Compute the preimage of "set" under the function represented by "ma".
13118 * In other words, plug in "ma" in "set". The result is a set
13119 * that lives in the domain space of "ma".
13121 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13122 __isl_take isl_multi_aff *ma)
13124 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13127 /* Compute the preimage of the domain of "map" under the function
13128 * represented by "ma".
13129 * In other words, plug in "ma" in the domain of "map".
13130 * The result is a map that lives in the same space as "map"
13131 * except that the domain has been replaced by the domain space of "ma".
13133 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13134 __isl_take isl_multi_aff *ma)
13136 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13139 /* Compute the preimage of the range of "map" under the function
13140 * represented by "ma".
13141 * In other words, plug in "ma" in the range of "map".
13142 * The result is a map that lives in the same space as "map"
13143 * except that the range has been replaced by the domain space of "ma".
13145 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13146 __isl_take isl_multi_aff *ma)
13148 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
13151 /* Compute the preimage of "map" under the function represented by "pma".
13152 * In other words, plug in "pma" in the domain or range of "map".
13153 * The result is a map that lives in the same space as "map",
13154 * except that the space of type "type" has been replaced by
13155 * the domain space of "pma".
13157 * The parameters of "map" and "pma" are assumed to have been aligned.
13159 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
13160 __isl_take isl_map *map, enum isl_dim_type type,
13161 __isl_take isl_pw_multi_aff *pma)
13163 int i;
13164 isl_map *res;
13166 if (!pma)
13167 goto error;
13169 if (pma->n == 0) {
13170 isl_pw_multi_aff_free(pma);
13171 res = isl_map_empty(isl_map_get_space(map));
13172 isl_map_free(map);
13173 return res;
13176 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13177 isl_multi_aff_copy(pma->p[0].maff));
13178 if (type == isl_dim_in)
13179 res = isl_map_intersect_domain(res,
13180 isl_map_copy(pma->p[0].set));
13181 else
13182 res = isl_map_intersect_range(res,
13183 isl_map_copy(pma->p[0].set));
13185 for (i = 1; i < pma->n; ++i) {
13186 isl_map *res_i;
13188 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13189 isl_multi_aff_copy(pma->p[i].maff));
13190 if (type == isl_dim_in)
13191 res_i = isl_map_intersect_domain(res_i,
13192 isl_map_copy(pma->p[i].set));
13193 else
13194 res_i = isl_map_intersect_range(res_i,
13195 isl_map_copy(pma->p[i].set));
13196 res = isl_map_union(res, res_i);
13199 isl_pw_multi_aff_free(pma);
13200 isl_map_free(map);
13201 return res;
13202 error:
13203 isl_pw_multi_aff_free(pma);
13204 isl_map_free(map);
13205 return NULL;
13208 /* Compute the preimage of "map" under the function represented by "pma".
13209 * In other words, plug in "pma" in the domain or range of "map".
13210 * The result is a map that lives in the same space as "map",
13211 * except that the space of type "type" has been replaced by
13212 * the domain space of "pma".
13214 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
13215 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
13217 isl_bool aligned;
13219 if (!map || !pma)
13220 goto error;
13222 aligned = isl_map_space_has_equal_params(map, pma->dim);
13223 if (aligned < 0)
13224 goto error;
13225 if (aligned)
13226 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13228 if (isl_map_check_named_params(map) < 0)
13229 goto error;
13230 if (isl_pw_multi_aff_check_named_params(pma) < 0)
13231 goto error;
13232 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
13233 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
13235 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13236 error:
13237 isl_pw_multi_aff_free(pma);
13238 return isl_map_free(map);
13241 /* Compute the preimage of "set" under the function represented by "pma".
13242 * In other words, plug in "pma" in "set". The result is a set
13243 * that lives in the domain space of "pma".
13245 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
13246 __isl_take isl_pw_multi_aff *pma)
13248 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
13251 /* Compute the preimage of the domain of "map" under the function
13252 * represented by "pma".
13253 * In other words, plug in "pma" in the domain of "map".
13254 * The result is a map that lives in the same space as "map",
13255 * except that domain space has been replaced by the domain space of "pma".
13257 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
13258 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13260 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
13263 /* Compute the preimage of the range of "map" under the function
13264 * represented by "pma".
13265 * In other words, plug in "pma" in the range of "map".
13266 * The result is a map that lives in the same space as "map",
13267 * except that range space has been replaced by the domain space of "pma".
13269 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
13270 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13272 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
13275 /* Compute the preimage of "map" under the function represented by "mpa".
13276 * In other words, plug in "mpa" in the domain or range of "map".
13277 * The result is a map that lives in the same space as "map",
13278 * except that the space of type "type" has been replaced by
13279 * the domain space of "mpa".
13281 * If the map does not involve any constraints that refer to the
13282 * dimensions of the substituted space, then the only possible
13283 * effect of "mpa" on the map is to map the space to a different space.
13284 * We create a separate isl_multi_aff to effectuate this change
13285 * in order to avoid spurious splitting of the map along the pieces
13286 * of "mpa".
13287 * If "mpa" has a non-trivial explicit domain, however,
13288 * then the full substitution should be performed.
13290 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
13291 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
13293 int n;
13294 isl_bool full;
13295 isl_pw_multi_aff *pma;
13297 if (!map || !mpa)
13298 goto error;
13300 n = isl_map_dim(map, type);
13301 full = isl_map_involves_dims(map, type, 0, n);
13302 if (full >= 0 && !full)
13303 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
13304 if (full < 0)
13305 goto error;
13306 if (!full) {
13307 isl_space *space;
13308 isl_multi_aff *ma;
13310 space = isl_multi_pw_aff_get_space(mpa);
13311 isl_multi_pw_aff_free(mpa);
13312 ma = isl_multi_aff_zero(space);
13313 return isl_map_preimage_multi_aff(map, type, ma);
13316 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
13317 return isl_map_preimage_pw_multi_aff(map, type, pma);
13318 error:
13319 isl_map_free(map);
13320 isl_multi_pw_aff_free(mpa);
13321 return NULL;
13324 /* Compute the preimage of "map" under the function represented by "mpa".
13325 * In other words, plug in "mpa" in the domain "map".
13326 * The result is a map that lives in the same space as "map",
13327 * except that domain space has been replaced by the domain space of "mpa".
13329 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
13330 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
13332 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
13335 /* Compute the preimage of "set" by the function represented by "mpa".
13336 * In other words, plug in "mpa" in "set".
13338 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
13339 __isl_take isl_multi_pw_aff *mpa)
13341 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
13344 /* Return a copy of the equality constraints of "bset" as a matrix.
13346 __isl_give isl_mat *isl_basic_set_extract_equalities(
13347 __isl_keep isl_basic_set *bset)
13349 isl_ctx *ctx;
13350 unsigned total;
13352 if (!bset)
13353 return NULL;
13355 ctx = isl_basic_set_get_ctx(bset);
13356 total = 1 + isl_basic_set_dim(bset, isl_dim_all);
13357 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
13360 /* Are the "n" "coefficients" starting at "first" of the integer division
13361 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
13362 * to each other?
13363 * The "coefficient" at position 0 is the denominator.
13364 * The "coefficient" at position 1 is the constant term.
13366 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
13367 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
13368 unsigned first, unsigned n)
13370 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
13371 return isl_bool_error;
13372 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
13373 return isl_bool_error;
13374 return isl_seq_eq(bmap1->div[pos1] + first,
13375 bmap2->div[pos2] + first, n);
13378 /* Are the integer division expressions at position "pos1" in "bmap1" and
13379 * "pos2" in "bmap2" equal to each other, except that the constant terms
13380 * are different?
13382 isl_bool isl_basic_map_equal_div_expr_except_constant(
13383 __isl_keep isl_basic_map *bmap1, int pos1,
13384 __isl_keep isl_basic_map *bmap2, int pos2)
13386 isl_bool equal;
13387 unsigned total;
13389 if (!bmap1 || !bmap2)
13390 return isl_bool_error;
13391 total = isl_basic_map_total_dim(bmap1);
13392 if (total != isl_basic_map_total_dim(bmap2))
13393 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
13394 "incomparable div expressions", return isl_bool_error);
13395 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13396 0, 1);
13397 if (equal < 0 || !equal)
13398 return equal;
13399 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13400 1, 1);
13401 if (equal < 0 || equal)
13402 return isl_bool_not(equal);
13403 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13404 2, total);
13407 /* Replace the numerator of the constant term of the integer division
13408 * expression at position "div" in "bmap" by "value".
13409 * The caller guarantees that this does not change the meaning
13410 * of the input.
13412 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
13413 __isl_take isl_basic_map *bmap, int div, int value)
13415 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
13416 return isl_basic_map_free(bmap);
13418 isl_int_set_si(bmap->div[div][1], value);
13420 return bmap;
13423 /* Is the point "inner" internal to inequality constraint "ineq"
13424 * of "bset"?
13425 * The point is considered to be internal to the inequality constraint,
13426 * if it strictly lies on the positive side of the inequality constraint,
13427 * or if it lies on the constraint and the constraint is lexico-positive.
13429 static isl_bool is_internal(__isl_keep isl_vec *inner,
13430 __isl_keep isl_basic_set *bset, int ineq)
13432 isl_ctx *ctx;
13433 int pos;
13434 unsigned total;
13436 if (!inner || !bset)
13437 return isl_bool_error;
13439 ctx = isl_basic_set_get_ctx(bset);
13440 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13441 &ctx->normalize_gcd);
13442 if (!isl_int_is_zero(ctx->normalize_gcd))
13443 return isl_int_is_nonneg(ctx->normalize_gcd);
13445 total = isl_basic_set_dim(bset, isl_dim_all);
13446 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13447 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13450 /* Tighten the inequality constraints of "bset" that are outward with respect
13451 * to the point "vec".
13452 * That is, tighten the constraints that are not satisfied by "vec".
13454 * "vec" is a point internal to some superset S of "bset" that is used
13455 * to make the subsets of S disjoint, by tightening one half of the constraints
13456 * that separate two subsets. In particular, the constraints of S
13457 * are all satisfied by "vec" and should not be tightened.
13458 * Of the internal constraints, those that have "vec" on the outside
13459 * are tightened. The shared facet is included in the adjacent subset
13460 * with the opposite constraint.
13461 * For constraints that saturate "vec", this criterion cannot be used
13462 * to determine which of the two sides should be tightened.
13463 * Instead, the sign of the first non-zero coefficient is used
13464 * to make this choice. Note that this second criterion is never used
13465 * on the constraints of S since "vec" is interior to "S".
13467 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13468 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13470 int j;
13472 bset = isl_basic_set_cow(bset);
13473 if (!bset)
13474 return NULL;
13475 for (j = 0; j < bset->n_ineq; ++j) {
13476 isl_bool internal;
13478 internal = is_internal(vec, bset, j);
13479 if (internal < 0)
13480 return isl_basic_set_free(bset);
13481 if (internal)
13482 continue;
13483 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13486 return bset;
13489 /* Replace the variables x of type "type" starting at "first" in "bmap"
13490 * by x' with x = M x' with M the matrix trans.
13491 * That is, replace the corresponding coefficients c by c M.
13493 * The transformation matrix should be a square matrix.
13495 __isl_give isl_basic_map *isl_basic_map_transform_dims(
13496 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
13497 __isl_take isl_mat *trans)
13499 unsigned pos;
13501 bmap = isl_basic_map_cow(bmap);
13502 if (!bmap || !trans)
13503 goto error;
13505 if (trans->n_row != trans->n_col)
13506 isl_die(trans->ctx, isl_error_invalid,
13507 "expecting square transformation matrix", goto error);
13508 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
13509 goto error;
13511 pos = isl_basic_map_offset(bmap, type) + first;
13513 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
13514 isl_mat_copy(trans)) < 0)
13515 goto error;
13516 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
13517 isl_mat_copy(trans)) < 0)
13518 goto error;
13519 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
13520 isl_mat_copy(trans)) < 0)
13521 goto error;
13523 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
13524 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
13526 isl_mat_free(trans);
13527 return bmap;
13528 error:
13529 isl_mat_free(trans);
13530 isl_basic_map_free(bmap);
13531 return NULL;
13534 /* Replace the variables x of type "type" starting at "first" in "bset"
13535 * by x' with x = M x' with M the matrix trans.
13536 * That is, replace the corresponding coefficients c by c M.
13538 * The transformation matrix should be a square matrix.
13540 __isl_give isl_basic_set *isl_basic_set_transform_dims(
13541 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
13542 __isl_take isl_mat *trans)
13544 return isl_basic_map_transform_dims(bset, type, first, trans);