extract out shared isl_term_check_range
[isl.git] / isl_map.c
blob59ac63cbfe2fc05da2036fe1b1ef12533c739302
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 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
488 return isl_basic_map_free(bmap);
491 return bmap;
494 __isl_give isl_basic_map *isl_basic_map_from_local_space(
495 __isl_take isl_local_space *ls)
497 int i;
498 int n_div;
499 isl_basic_map *bmap;
501 if (!ls)
502 return NULL;
504 n_div = isl_local_space_dim(ls, isl_dim_div);
505 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
506 n_div, 0, 2 * n_div);
508 for (i = 0; i < n_div; ++i)
509 if (isl_basic_map_alloc_div(bmap) < 0)
510 goto error;
512 for (i = 0; i < n_div; ++i)
513 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
514 bmap = add_known_div_constraints(bmap);
516 isl_local_space_free(ls);
517 return bmap;
518 error:
519 isl_local_space_free(ls);
520 isl_basic_map_free(bmap);
521 return NULL;
524 __isl_give isl_basic_set *isl_basic_set_from_local_space(
525 __isl_take isl_local_space *ls)
527 return isl_basic_map_from_local_space(ls);
530 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
532 return isl_space_copy(isl_map_peek_space(map));
535 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
537 if (!set)
538 return NULL;
539 return isl_space_copy(set->dim);
542 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
543 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
545 bmap = isl_basic_map_cow(bmap);
546 if (!bmap)
547 return NULL;
548 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
549 if (!bmap->dim)
550 goto error;
551 bmap = isl_basic_map_finalize(bmap);
552 return bmap;
553 error:
554 isl_basic_map_free(bmap);
555 return NULL;
558 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
559 __isl_take isl_basic_set *bset, const char *s)
561 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
564 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
565 enum isl_dim_type type)
567 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
570 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
571 enum isl_dim_type type, const char *s)
573 int i;
575 map = isl_map_cow(map);
576 if (!map)
577 return NULL;
579 map->dim = isl_space_set_tuple_name(map->dim, type, s);
580 if (!map->dim)
581 goto error;
583 for (i = 0; i < map->n; ++i) {
584 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
585 if (!map->p[i])
586 goto error;
589 return map;
590 error:
591 isl_map_free(map);
592 return NULL;
595 /* Replace the identifier of the tuple of type "type" by "id".
597 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
598 __isl_take isl_basic_map *bmap,
599 enum isl_dim_type type, __isl_take isl_id *id)
601 bmap = isl_basic_map_cow(bmap);
602 if (!bmap)
603 goto error;
604 bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
605 if (!bmap->dim)
606 return isl_basic_map_free(bmap);
607 bmap = isl_basic_map_finalize(bmap);
608 return bmap;
609 error:
610 isl_id_free(id);
611 return NULL;
614 /* Replace the identifier of the tuple by "id".
616 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
617 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
619 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
622 /* Does the input or output tuple have a name?
624 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
626 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
629 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
630 enum isl_dim_type type)
632 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
635 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
636 const char *s)
638 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
639 isl_dim_set, s));
642 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
643 enum isl_dim_type type, __isl_take isl_id *id)
645 map = isl_map_cow(map);
646 if (!map)
647 goto error;
649 map->dim = isl_space_set_tuple_id(map->dim, type, id);
651 return isl_map_reset_space(map, isl_space_copy(map->dim));
652 error:
653 isl_id_free(id);
654 return NULL;
657 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
658 __isl_take isl_id *id)
660 return isl_map_set_tuple_id(set, isl_dim_set, id);
663 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
664 enum isl_dim_type type)
666 map = isl_map_cow(map);
667 if (!map)
668 return NULL;
670 map->dim = isl_space_reset_tuple_id(map->dim, type);
672 return isl_map_reset_space(map, isl_space_copy(map->dim));
675 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
677 return isl_map_reset_tuple_id(set, isl_dim_set);
680 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
682 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
685 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
686 enum isl_dim_type type)
688 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
691 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
693 return isl_map_has_tuple_id(set, isl_dim_set);
696 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
698 return isl_map_get_tuple_id(set, isl_dim_set);
701 /* Does the set tuple have a name?
703 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
705 if (!set)
706 return isl_bool_error;
707 return isl_space_has_tuple_name(set->dim, isl_dim_set);
711 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
713 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
716 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
718 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
721 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
722 enum isl_dim_type type, unsigned pos)
724 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
727 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
728 enum isl_dim_type type, unsigned pos)
730 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
733 /* Does the given dimension have a name?
735 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
736 enum isl_dim_type type, unsigned pos)
738 if (!map)
739 return isl_bool_error;
740 return isl_space_has_dim_name(map->dim, type, pos);
743 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
744 enum isl_dim_type type, unsigned pos)
746 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
749 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
750 enum isl_dim_type type, unsigned pos)
752 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
755 /* Does the given dimension have a name?
757 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
758 enum isl_dim_type type, unsigned pos)
760 if (!set)
761 return isl_bool_error;
762 return isl_space_has_dim_name(set->dim, type, pos);
765 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
766 __isl_take isl_basic_map *bmap,
767 enum isl_dim_type type, unsigned pos, const char *s)
769 bmap = isl_basic_map_cow(bmap);
770 if (!bmap)
771 return NULL;
772 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
773 if (!bmap->dim)
774 goto error;
775 return isl_basic_map_finalize(bmap);
776 error:
777 isl_basic_map_free(bmap);
778 return NULL;
781 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
782 enum isl_dim_type type, unsigned pos, const char *s)
784 int i;
786 map = isl_map_cow(map);
787 if (!map)
788 return NULL;
790 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
791 if (!map->dim)
792 goto error;
794 for (i = 0; i < map->n; ++i) {
795 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
796 if (!map->p[i])
797 goto error;
800 return map;
801 error:
802 isl_map_free(map);
803 return NULL;
806 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
807 __isl_take isl_basic_set *bset,
808 enum isl_dim_type type, unsigned pos, const char *s)
810 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
811 type, pos, s));
814 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
815 enum isl_dim_type type, unsigned pos, const char *s)
817 return set_from_map(isl_map_set_dim_name(set_to_map(set),
818 type, pos, s));
821 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
822 enum isl_dim_type type, unsigned pos)
824 if (!bmap)
825 return isl_bool_error;
826 return isl_space_has_dim_id(bmap->dim, type, pos);
829 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
830 enum isl_dim_type type, unsigned pos)
832 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
835 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
836 enum isl_dim_type type, unsigned pos)
838 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
841 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
842 enum isl_dim_type type, unsigned pos)
844 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
847 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
848 enum isl_dim_type type, unsigned pos)
850 return isl_map_has_dim_id(set, type, pos);
853 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
854 enum isl_dim_type type, unsigned pos)
856 return isl_map_get_dim_id(set, type, pos);
859 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
860 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
862 map = isl_map_cow(map);
863 if (!map)
864 goto error;
866 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
868 return isl_map_reset_space(map, isl_space_copy(map->dim));
869 error:
870 isl_id_free(id);
871 return NULL;
874 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
875 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
877 return isl_map_set_dim_id(set, type, pos, id);
880 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
881 __isl_keep isl_id *id)
883 if (!map)
884 return -1;
885 return isl_space_find_dim_by_id(map->dim, type, id);
888 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
889 __isl_keep isl_id *id)
891 return isl_map_find_dim_by_id(set, type, id);
894 /* Return the position of the dimension of the given type and name
895 * in "bmap".
896 * Return -1 if no such dimension can be found.
898 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
899 enum isl_dim_type type, const char *name)
901 if (!bmap)
902 return -1;
903 return isl_space_find_dim_by_name(bmap->dim, type, name);
906 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
907 const char *name)
909 if (!map)
910 return -1;
911 return isl_space_find_dim_by_name(map->dim, type, name);
914 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
915 const char *name)
917 return isl_map_find_dim_by_name(set, type, name);
920 /* Check whether equality i of bset is a pure stride constraint
921 * on a single dimension, i.e., of the form
923 * v = k e
925 * with k a constant and e an existentially quantified variable.
927 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
929 unsigned nparam;
930 unsigned d;
931 unsigned n_div;
932 int pos1;
933 int pos2;
935 if (!bset)
936 return isl_bool_error;
938 if (!isl_int_is_zero(bset->eq[i][0]))
939 return isl_bool_false;
941 nparam = isl_basic_set_dim(bset, isl_dim_param);
942 d = isl_basic_set_dim(bset, isl_dim_set);
943 n_div = isl_basic_set_dim(bset, isl_dim_div);
945 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
946 return isl_bool_false;
947 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
948 if (pos1 == -1)
949 return isl_bool_false;
950 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
951 d - pos1 - 1) != -1)
952 return isl_bool_false;
954 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
955 if (pos2 == -1)
956 return isl_bool_false;
957 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
958 n_div - pos2 - 1) != -1)
959 return isl_bool_false;
960 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
961 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
962 return isl_bool_false;
964 return isl_bool_true;
967 /* Reset the user pointer on all identifiers of parameters and tuples
968 * of the space of "map".
970 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
972 isl_space *space;
974 space = isl_map_get_space(map);
975 space = isl_space_reset_user(space);
976 map = isl_map_reset_space(map, space);
978 return map;
981 /* Reset the user pointer on all identifiers of parameters and tuples
982 * of the space of "set".
984 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
986 return isl_map_reset_user(set);
989 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
991 if (!bmap)
992 return isl_bool_error;
993 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
996 /* Has "map" been marked as a rational map?
997 * In particular, have all basic maps in "map" been marked this way?
998 * An empty map is not considered to be rational.
999 * Maps where only some of the basic maps are marked rational
1000 * are not allowed.
1002 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
1004 int i;
1005 isl_bool rational;
1007 if (!map)
1008 return isl_bool_error;
1009 if (map->n == 0)
1010 return isl_bool_false;
1011 rational = isl_basic_map_is_rational(map->p[0]);
1012 if (rational < 0)
1013 return rational;
1014 for (i = 1; i < map->n; ++i) {
1015 isl_bool rational_i;
1017 rational_i = isl_basic_map_is_rational(map->p[i]);
1018 if (rational_i < 0)
1019 return rational_i;
1020 if (rational != rational_i)
1021 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1022 "mixed rational and integer basic maps "
1023 "not supported", return isl_bool_error);
1026 return rational;
1029 /* Has "set" been marked as a rational set?
1030 * In particular, have all basic set in "set" been marked this way?
1031 * An empty set is not considered to be rational.
1032 * Sets where only some of the basic sets are marked rational
1033 * are not allowed.
1035 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1037 return isl_map_is_rational(set);
1040 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1042 return isl_basic_map_is_rational(bset);
1045 /* Does "bmap" contain any rational points?
1047 * If "bmap" has an equality for each dimension, equating the dimension
1048 * to an integer constant, then it has no rational points, even if it
1049 * is marked as rational.
1051 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1053 isl_bool has_rational = isl_bool_true;
1054 unsigned total;
1056 if (!bmap)
1057 return isl_bool_error;
1058 if (isl_basic_map_plain_is_empty(bmap))
1059 return isl_bool_false;
1060 if (!isl_basic_map_is_rational(bmap))
1061 return isl_bool_false;
1062 bmap = isl_basic_map_copy(bmap);
1063 bmap = isl_basic_map_implicit_equalities(bmap);
1064 if (!bmap)
1065 return isl_bool_error;
1066 total = isl_basic_map_total_dim(bmap);
1067 if (bmap->n_eq == total) {
1068 int i, j;
1069 for (i = 0; i < bmap->n_eq; ++i) {
1070 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1071 if (j < 0)
1072 break;
1073 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1074 !isl_int_is_negone(bmap->eq[i][1 + j]))
1075 break;
1076 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1077 total - j - 1);
1078 if (j >= 0)
1079 break;
1081 if (i == bmap->n_eq)
1082 has_rational = isl_bool_false;
1084 isl_basic_map_free(bmap);
1086 return has_rational;
1089 /* Does "map" contain any rational points?
1091 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1093 int i;
1094 isl_bool has_rational;
1096 if (!map)
1097 return isl_bool_error;
1098 for (i = 0; i < map->n; ++i) {
1099 has_rational = isl_basic_map_has_rational(map->p[i]);
1100 if (has_rational < 0 || has_rational)
1101 return has_rational;
1103 return isl_bool_false;
1106 /* Does "set" contain any rational points?
1108 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1110 return isl_map_has_rational(set);
1113 /* Is this basic set a parameter domain?
1115 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1117 if (!bset)
1118 return isl_bool_error;
1119 return isl_space_is_params(bset->dim);
1122 /* Is this set a parameter domain?
1124 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1126 if (!set)
1127 return isl_bool_error;
1128 return isl_space_is_params(set->dim);
1131 /* Is this map actually a parameter domain?
1132 * Users should never call this function. Outside of isl,
1133 * a map can never be a parameter domain.
1135 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1137 if (!map)
1138 return isl_bool_error;
1139 return isl_space_is_params(map->dim);
1142 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1143 __isl_take isl_basic_map *bmap, unsigned extra,
1144 unsigned n_eq, unsigned n_ineq)
1146 int i;
1147 size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
1149 bmap->ctx = ctx;
1150 isl_ctx_ref(ctx);
1152 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1153 if (isl_blk_is_error(bmap->block))
1154 goto error;
1156 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1157 if ((n_ineq + n_eq) && !bmap->ineq)
1158 goto error;
1160 if (extra == 0) {
1161 bmap->block2 = isl_blk_empty();
1162 bmap->div = NULL;
1163 } else {
1164 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1165 if (isl_blk_is_error(bmap->block2))
1166 goto error;
1168 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1169 if (!bmap->div)
1170 goto error;
1173 for (i = 0; i < n_ineq + n_eq; ++i)
1174 bmap->ineq[i] = bmap->block.data + i * row_size;
1176 for (i = 0; i < extra; ++i)
1177 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1179 bmap->ref = 1;
1180 bmap->flags = 0;
1181 bmap->c_size = n_eq + n_ineq;
1182 bmap->eq = bmap->ineq + n_ineq;
1183 bmap->extra = extra;
1184 bmap->n_eq = 0;
1185 bmap->n_ineq = 0;
1186 bmap->n_div = 0;
1187 bmap->sample = NULL;
1189 return bmap;
1190 error:
1191 isl_basic_map_free(bmap);
1192 return NULL;
1195 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1196 unsigned nparam, unsigned dim, unsigned extra,
1197 unsigned n_eq, unsigned n_ineq)
1199 struct isl_basic_map *bmap;
1200 isl_space *space;
1202 space = isl_space_set_alloc(ctx, nparam, dim);
1203 if (!space)
1204 return NULL;
1206 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1207 return bset_from_bmap(bmap);
1210 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1211 unsigned extra, unsigned n_eq, unsigned n_ineq)
1213 struct isl_basic_map *bmap;
1214 if (!dim)
1215 return NULL;
1216 isl_assert(dim->ctx, dim->n_in == 0, goto error);
1217 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1218 return bset_from_bmap(bmap);
1219 error:
1220 isl_space_free(dim);
1221 return NULL;
1224 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1225 unsigned extra, unsigned n_eq, unsigned n_ineq)
1227 struct isl_basic_map *bmap;
1229 if (!space)
1230 return NULL;
1231 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1232 if (!bmap)
1233 goto error;
1234 bmap->dim = space;
1236 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1237 error:
1238 isl_space_free(space);
1239 return NULL;
1242 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1243 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1244 unsigned n_eq, unsigned n_ineq)
1246 struct isl_basic_map *bmap;
1247 isl_space *dim;
1249 dim = isl_space_alloc(ctx, nparam, in, out);
1250 if (!dim)
1251 return NULL;
1253 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1254 return bmap;
1257 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1258 __isl_keep isl_basic_map *src)
1260 int i;
1261 unsigned total = isl_basic_map_total_dim(src);
1263 if (!dst)
1264 return NULL;
1266 for (i = 0; i < src->n_eq; ++i) {
1267 int j = isl_basic_map_alloc_equality(dst);
1268 if (j < 0)
1269 return isl_basic_map_free(dst);
1270 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1273 for (i = 0; i < src->n_ineq; ++i) {
1274 int j = isl_basic_map_alloc_inequality(dst);
1275 if (j < 0)
1276 return isl_basic_map_free(dst);
1277 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1280 for (i = 0; i < src->n_div; ++i) {
1281 int j = isl_basic_map_alloc_div(dst);
1282 if (j < 0)
1283 return isl_basic_map_free(dst);
1284 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1286 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1287 return dst;
1290 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1292 struct isl_basic_map *dup;
1294 if (!bmap)
1295 return NULL;
1296 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1297 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1298 dup = dup_constraints(dup, bmap);
1299 if (!dup)
1300 return NULL;
1301 dup->flags = bmap->flags;
1302 dup->sample = isl_vec_copy(bmap->sample);
1303 return dup;
1306 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1308 struct isl_basic_map *dup;
1310 dup = isl_basic_map_dup(bset_to_bmap(bset));
1311 return bset_from_bmap(dup);
1314 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1316 if (!bset)
1317 return NULL;
1319 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1320 bset->ref++;
1321 return bset;
1323 return isl_basic_set_dup(bset);
1326 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1328 if (!set)
1329 return NULL;
1331 set->ref++;
1332 return set;
1335 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1337 if (!bmap)
1338 return NULL;
1340 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1341 bmap->ref++;
1342 return bmap;
1344 bmap = isl_basic_map_dup(bmap);
1345 if (bmap)
1346 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1347 return bmap;
1350 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1352 if (!map)
1353 return NULL;
1355 map->ref++;
1356 return map;
1359 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1361 if (!bmap)
1362 return NULL;
1364 if (--bmap->ref > 0)
1365 return NULL;
1367 isl_ctx_deref(bmap->ctx);
1368 free(bmap->div);
1369 isl_blk_free(bmap->ctx, bmap->block2);
1370 free(bmap->ineq);
1371 isl_blk_free(bmap->ctx, bmap->block);
1372 isl_vec_free(bmap->sample);
1373 isl_space_free(bmap->dim);
1374 free(bmap);
1376 return NULL;
1379 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1381 return isl_basic_map_free(bset_to_bmap(bset));
1384 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1386 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1389 /* Check that "map" has only named parameters, reporting an error
1390 * if it does not.
1392 isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1394 return isl_space_check_named_params(isl_map_peek_space(map));
1397 /* Check that "bmap" has only named parameters, reporting an error
1398 * if it does not.
1400 static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
1402 return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
1405 /* Check that "bmap1" and "bmap2" have the same parameters,
1406 * reporting an error if they do not.
1408 static isl_stat isl_basic_map_check_equal_params(
1409 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1411 isl_bool match;
1413 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1414 if (match < 0)
1415 return isl_stat_error;
1416 if (!match)
1417 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1418 "parameters don't match", return isl_stat_error);
1419 return isl_stat_ok;
1422 __isl_give isl_map *isl_map_align_params_map_map_and(
1423 __isl_take isl_map *map1, __isl_take isl_map *map2,
1424 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1425 __isl_take isl_map *map2))
1427 if (!map1 || !map2)
1428 goto error;
1429 if (isl_map_has_equal_params(map1, map2))
1430 return fn(map1, map2);
1431 if (isl_map_check_named_params(map1) < 0)
1432 goto error;
1433 if (isl_map_check_named_params(map2) < 0)
1434 goto error;
1435 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1436 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1437 return fn(map1, map2);
1438 error:
1439 isl_map_free(map1);
1440 isl_map_free(map2);
1441 return NULL;
1444 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1445 __isl_keep isl_map *map2,
1446 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1448 isl_bool r;
1450 if (!map1 || !map2)
1451 return isl_bool_error;
1452 if (isl_map_has_equal_params(map1, map2))
1453 return fn(map1, map2);
1454 if (isl_map_check_named_params(map1) < 0)
1455 return isl_bool_error;
1456 if (isl_map_check_named_params(map2) < 0)
1457 return isl_bool_error;
1458 map1 = isl_map_copy(map1);
1459 map2 = isl_map_copy(map2);
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 r = fn(map1, map2);
1463 isl_map_free(map1);
1464 isl_map_free(map2);
1465 return r;
1468 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1470 struct isl_ctx *ctx;
1471 if (!bmap)
1472 return -1;
1473 ctx = bmap->ctx;
1474 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1475 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1476 return -1);
1477 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1478 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1479 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1480 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1481 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1482 isl_int *t;
1483 int j = isl_basic_map_alloc_inequality(bmap);
1484 if (j < 0)
1485 return -1;
1486 t = bmap->ineq[j];
1487 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1488 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1489 bmap->eq[-1] = t;
1490 bmap->n_eq++;
1491 bmap->n_ineq--;
1492 bmap->eq--;
1493 return 0;
1495 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1496 bmap->extra - bmap->n_div);
1497 return bmap->n_eq++;
1500 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1502 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1505 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1507 if (!bmap)
1508 return -1;
1509 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1510 bmap->n_eq -= n;
1511 return 0;
1514 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1516 return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1519 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1521 isl_int *t;
1522 if (!bmap)
1523 return -1;
1524 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1526 if (pos != bmap->n_eq - 1) {
1527 t = bmap->eq[pos];
1528 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1529 bmap->eq[bmap->n_eq - 1] = t;
1531 bmap->n_eq--;
1532 return 0;
1535 /* Turn inequality "pos" of "bmap" into an equality.
1537 * In particular, we move the inequality in front of the equalities
1538 * and move the last inequality in the position of the moved inequality.
1539 * Note that isl_tab_make_equalities_explicit depends on this particular
1540 * change in the ordering of the constraints.
1542 void isl_basic_map_inequality_to_equality(
1543 struct isl_basic_map *bmap, unsigned pos)
1545 isl_int *t;
1547 t = bmap->ineq[pos];
1548 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1549 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1550 bmap->eq[-1] = t;
1551 bmap->n_eq++;
1552 bmap->n_ineq--;
1553 bmap->eq--;
1554 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1555 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1556 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1557 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1560 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1562 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1565 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1567 struct isl_ctx *ctx;
1568 if (!bmap)
1569 return -1;
1570 ctx = bmap->ctx;
1571 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1572 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1573 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1574 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1575 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1576 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1577 1 + isl_basic_map_total_dim(bmap),
1578 bmap->extra - bmap->n_div);
1579 return bmap->n_ineq++;
1582 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1584 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1587 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1589 if (!bmap)
1590 return -1;
1591 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1592 bmap->n_ineq -= n;
1593 return 0;
1596 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1598 return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1601 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1603 isl_int *t;
1604 if (!bmap)
1605 return -1;
1606 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1608 if (pos != bmap->n_ineq - 1) {
1609 t = bmap->ineq[pos];
1610 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1611 bmap->ineq[bmap->n_ineq - 1] = t;
1612 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1614 bmap->n_ineq--;
1615 return 0;
1618 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1620 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1623 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1624 isl_int *eq)
1626 isl_bool empty;
1627 int k;
1629 empty = isl_basic_map_plain_is_empty(bmap);
1630 if (empty < 0)
1631 return isl_basic_map_free(bmap);
1632 if (empty)
1633 return bmap;
1635 bmap = isl_basic_map_cow(bmap);
1636 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1637 if (!bmap)
1638 return NULL;
1639 k = isl_basic_map_alloc_equality(bmap);
1640 if (k < 0)
1641 goto error;
1642 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1643 return bmap;
1644 error:
1645 isl_basic_map_free(bmap);
1646 return NULL;
1649 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1650 isl_int *eq)
1652 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1655 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1656 isl_int *ineq)
1658 int k;
1660 bmap = isl_basic_map_cow(bmap);
1661 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1662 if (!bmap)
1663 return NULL;
1664 k = isl_basic_map_alloc_inequality(bmap);
1665 if (k < 0)
1666 goto error;
1667 isl_seq_cpy(bmap->ineq[k], ineq, 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_ineq(__isl_take isl_basic_set *bset,
1675 isl_int *ineq)
1677 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1680 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1682 if (!bmap)
1683 return -1;
1684 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1685 isl_seq_clr(bmap->div[bmap->n_div] +
1686 1 + 1 + isl_basic_map_total_dim(bmap),
1687 bmap->extra - bmap->n_div);
1688 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1689 return bmap->n_div++;
1692 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1694 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1697 #undef TYPE
1698 #define TYPE isl_basic_map
1699 #include "check_type_range_templ.c"
1701 /* Insert an extra integer division, prescribed by "div", to "bmap"
1702 * at (integer division) position "pos".
1704 * The integer division is first added at the end and then moved
1705 * into the right position.
1707 __isl_give isl_basic_map *isl_basic_map_insert_div(
1708 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1710 int i, k;
1712 bmap = isl_basic_map_cow(bmap);
1713 if (!bmap || !div)
1714 return isl_basic_map_free(bmap);
1716 if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1717 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1718 "unexpected size", return isl_basic_map_free(bmap));
1719 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1720 return isl_basic_map_free(bmap);
1722 bmap = isl_basic_map_extend_space(bmap,
1723 isl_basic_map_get_space(bmap), 1, 0, 2);
1724 k = isl_basic_map_alloc_div(bmap);
1725 if (k < 0)
1726 return isl_basic_map_free(bmap);
1727 isl_seq_cpy(bmap->div[k], div->el, div->size);
1728 isl_int_set_si(bmap->div[k][div->size], 0);
1730 for (i = k; i > pos; --i)
1731 isl_basic_map_swap_div(bmap, i, i - 1);
1733 return bmap;
1736 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1738 if (!bmap)
1739 return isl_stat_error;
1740 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1741 bmap->n_div -= n;
1742 return isl_stat_ok;
1745 static __isl_give isl_basic_map *add_constraints(
1746 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1747 unsigned i_pos, unsigned o_pos)
1749 unsigned total, n_param, n_in, o_in, n_out, o_out, n_div;
1750 isl_ctx *ctx;
1751 isl_space *space;
1752 struct isl_dim_map *dim_map;
1754 space = isl_basic_map_peek_space(bmap2);
1755 if (!bmap1 || !space)
1756 goto error;
1758 total = isl_basic_map_dim(bmap1, isl_dim_all);
1759 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1760 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1761 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1762 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1763 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1764 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1765 ctx = isl_basic_map_get_ctx(bmap1);
1766 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1767 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1768 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1769 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1770 isl_dim_map_div(dim_map, bmap2, total);
1772 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1773 error:
1774 isl_basic_map_free(bmap1);
1775 isl_basic_map_free(bmap2);
1776 return NULL;
1779 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1780 struct isl_basic_set *bset2, unsigned pos)
1782 return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1783 bset_to_bmap(bset2), 0, pos));
1786 __isl_give isl_basic_map *isl_basic_map_extend_space(
1787 __isl_take isl_basic_map *base, __isl_take isl_space *space,
1788 unsigned extra, unsigned n_eq, unsigned n_ineq)
1790 struct isl_basic_map *ext;
1791 unsigned flags;
1792 int dims_ok;
1794 if (!space)
1795 goto error;
1797 if (!base)
1798 goto error;
1800 dims_ok = isl_space_is_equal(base->dim, space) &&
1801 base->extra >= base->n_div + extra;
1803 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1804 room_for_ineq(base, n_ineq)) {
1805 isl_space_free(space);
1806 return base;
1809 isl_assert(base->ctx, base->dim->nparam <= space->nparam, goto error);
1810 isl_assert(base->ctx, base->dim->n_in <= space->n_in, goto error);
1811 isl_assert(base->ctx, base->dim->n_out <= space->n_out, goto error);
1812 extra += base->extra;
1813 n_eq += base->n_eq;
1814 n_ineq += base->n_ineq;
1816 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1817 space = NULL;
1818 if (!ext)
1819 goto error;
1821 if (dims_ok)
1822 ext->sample = isl_vec_copy(base->sample);
1823 flags = base->flags;
1824 ext = add_constraints(ext, base, 0, 0);
1825 if (ext) {
1826 ext->flags = flags;
1827 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1830 return ext;
1832 error:
1833 isl_space_free(space);
1834 isl_basic_map_free(base);
1835 return NULL;
1838 __isl_give isl_basic_set *isl_basic_set_extend_space(
1839 __isl_take isl_basic_set *base,
1840 __isl_take isl_space *dim, unsigned extra,
1841 unsigned n_eq, unsigned n_ineq)
1843 return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1844 dim, extra, n_eq, n_ineq));
1847 struct isl_basic_map *isl_basic_map_extend_constraints(
1848 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1850 if (!base)
1851 return NULL;
1852 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1853 0, n_eq, n_ineq);
1856 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1857 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1858 unsigned n_eq, unsigned n_ineq)
1860 struct isl_basic_map *bmap;
1861 isl_space *dim;
1863 if (!base)
1864 return NULL;
1865 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1866 if (!dim)
1867 goto error;
1869 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1870 return bmap;
1871 error:
1872 isl_basic_map_free(base);
1873 return NULL;
1876 struct isl_basic_set *isl_basic_set_extend_constraints(
1877 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1879 isl_basic_map *bmap = bset_to_bmap(base);
1880 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1881 return bset_from_bmap(bmap);
1884 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1886 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1889 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1891 if (!bmap)
1892 return NULL;
1894 if (bmap->ref > 1) {
1895 bmap->ref--;
1896 bmap = isl_basic_map_dup(bmap);
1898 if (bmap) {
1899 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1900 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1902 return bmap;
1905 /* Clear all cached information in "map", either because it is about
1906 * to be modified or because it is being freed.
1907 * Always return the same pointer that is passed in.
1908 * This is needed for the use in isl_map_free.
1910 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1912 isl_basic_map_free(map->cached_simple_hull[0]);
1913 isl_basic_map_free(map->cached_simple_hull[1]);
1914 map->cached_simple_hull[0] = NULL;
1915 map->cached_simple_hull[1] = NULL;
1916 return map;
1919 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
1921 return isl_map_cow(set);
1924 /* Return an isl_map that is equal to "map" and that has only
1925 * a single reference.
1927 * If the original input already has only one reference, then
1928 * simply return it, but clear all cached information, since
1929 * it may be rendered invalid by the operations that will be
1930 * performed on the result.
1932 * Otherwise, create a duplicate (without any cached information).
1934 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
1936 if (!map)
1937 return NULL;
1939 if (map->ref == 1)
1940 return clear_caches(map);
1941 map->ref--;
1942 return isl_map_dup(map);
1945 static void swap_vars(struct isl_blk blk, isl_int *a,
1946 unsigned a_len, unsigned b_len)
1948 isl_seq_cpy(blk.data, a+a_len, b_len);
1949 isl_seq_cpy(blk.data+b_len, a, a_len);
1950 isl_seq_cpy(a, blk.data, b_len+a_len);
1953 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1954 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1956 int i;
1957 struct isl_blk blk;
1959 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
1960 goto error;
1962 if (n1 == 0 || n2 == 0)
1963 return bmap;
1965 bmap = isl_basic_map_cow(bmap);
1966 if (!bmap)
1967 return NULL;
1969 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
1970 if (isl_blk_is_error(blk))
1971 goto error;
1973 for (i = 0; i < bmap->n_eq; ++i)
1974 swap_vars(blk,
1975 bmap->eq[i] + pos, n1, n2);
1977 for (i = 0; i < bmap->n_ineq; ++i)
1978 swap_vars(blk,
1979 bmap->ineq[i] + pos, n1, n2);
1981 for (i = 0; i < bmap->n_div; ++i)
1982 swap_vars(blk,
1983 bmap->div[i]+1 + pos, n1, n2);
1985 isl_blk_free(bmap->ctx, blk);
1987 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
1988 bmap = isl_basic_map_gauss(bmap, NULL);
1989 return isl_basic_map_finalize(bmap);
1990 error:
1991 isl_basic_map_free(bmap);
1992 return NULL;
1995 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
1996 __isl_take isl_basic_map *bmap)
1998 int i = 0;
1999 unsigned total;
2000 if (!bmap)
2001 goto error;
2002 total = isl_basic_map_total_dim(bmap);
2003 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2004 return isl_basic_map_free(bmap);
2005 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2006 if (bmap->n_eq > 0)
2007 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
2008 else {
2009 i = isl_basic_map_alloc_equality(bmap);
2010 if (i < 0)
2011 goto error;
2013 isl_int_set_si(bmap->eq[i][0], 1);
2014 isl_seq_clr(bmap->eq[i]+1, total);
2015 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2016 isl_vec_free(bmap->sample);
2017 bmap->sample = NULL;
2018 return isl_basic_map_finalize(bmap);
2019 error:
2020 isl_basic_map_free(bmap);
2021 return NULL;
2024 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2025 __isl_take isl_basic_set *bset)
2027 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2030 __isl_give isl_basic_map *isl_basic_map_set_rational(
2031 __isl_take isl_basic_map *bmap)
2033 if (!bmap)
2034 return NULL;
2036 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2037 return bmap;
2039 bmap = isl_basic_map_cow(bmap);
2040 if (!bmap)
2041 return NULL;
2043 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2045 return isl_basic_map_finalize(bmap);
2048 __isl_give isl_basic_set *isl_basic_set_set_rational(
2049 __isl_take isl_basic_set *bset)
2051 return isl_basic_map_set_rational(bset);
2054 __isl_give isl_basic_set *isl_basic_set_set_integral(
2055 __isl_take isl_basic_set *bset)
2057 if (!bset)
2058 return NULL;
2060 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2061 return bset;
2063 bset = isl_basic_set_cow(bset);
2064 if (!bset)
2065 return NULL;
2067 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2069 return isl_basic_set_finalize(bset);
2072 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2074 int i;
2076 map = isl_map_cow(map);
2077 if (!map)
2078 return NULL;
2079 for (i = 0; i < map->n; ++i) {
2080 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2081 if (!map->p[i])
2082 goto error;
2084 return map;
2085 error:
2086 isl_map_free(map);
2087 return NULL;
2090 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2092 return isl_map_set_rational(set);
2095 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2096 * of "bmap").
2098 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2100 isl_int *t = bmap->div[a];
2101 bmap->div[a] = bmap->div[b];
2102 bmap->div[b] = t;
2105 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2106 * div definitions accordingly.
2108 void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
2110 int i;
2111 unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
2113 swap_div(bmap, a, b);
2115 for (i = 0; i < bmap->n_eq; ++i)
2116 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2118 for (i = 0; i < bmap->n_ineq; ++i)
2119 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2121 for (i = 0; i < bmap->n_div; ++i)
2122 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2123 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2126 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2128 isl_seq_cpy(c, c + n, rem);
2129 isl_seq_clr(c + rem, n);
2132 /* Drop n dimensions starting at first.
2134 * In principle, this frees up some extra variables as the number
2135 * of columns remains constant, but we would have to extend
2136 * the div array too as the number of rows in this array is assumed
2137 * to be equal to extra.
2139 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2140 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2142 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2145 /* Move "n" divs starting at "first" to the end of the list of divs.
2147 static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
2148 unsigned first, unsigned n)
2150 isl_int **div;
2151 int i;
2153 if (first + n == bmap->n_div)
2154 return bmap;
2156 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2157 if (!div)
2158 goto error;
2159 for (i = 0; i < n; ++i)
2160 div[i] = bmap->div[first + i];
2161 for (i = 0; i < bmap->n_div - first - n; ++i)
2162 bmap->div[first + i] = bmap->div[first + n + i];
2163 for (i = 0; i < n; ++i)
2164 bmap->div[bmap->n_div - n + i] = div[i];
2165 free(div);
2166 return bmap;
2167 error:
2168 isl_basic_map_free(bmap);
2169 return NULL;
2172 #undef TYPE
2173 #define TYPE isl_map
2174 static
2175 #include "check_type_range_templ.c"
2177 /* Drop "n" dimensions of type "type" starting at "first".
2178 * Perform the core computation, without cowing or
2179 * simplifying and finalizing the result.
2181 * In principle, this frees up some extra variables as the number
2182 * of columns remains constant, but we would have to extend
2183 * the div array too as the number of rows in this array is assumed
2184 * to be equal to extra.
2186 __isl_give isl_basic_map *isl_basic_map_drop_core(
2187 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2188 unsigned first, unsigned n)
2190 int i;
2191 unsigned offset;
2192 unsigned left;
2194 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2195 return isl_basic_map_free(bmap);
2197 offset = isl_basic_map_offset(bmap, type) + first;
2198 left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
2199 for (i = 0; i < bmap->n_eq; ++i)
2200 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2202 for (i = 0; i < bmap->n_ineq; ++i)
2203 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2205 for (i = 0; i < bmap->n_div; ++i)
2206 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2208 if (type == isl_dim_div) {
2209 bmap = move_divs_last(bmap, first, n);
2210 if (!bmap)
2211 return NULL;
2212 if (isl_basic_map_free_div(bmap, n) < 0)
2213 return isl_basic_map_free(bmap);
2214 } else
2215 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2216 if (!bmap->dim)
2217 return isl_basic_map_free(bmap);
2219 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2220 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2221 return bmap;
2224 /* Drop "n" dimensions of type "type" starting at "first".
2226 * In principle, this frees up some extra variables as the number
2227 * of columns remains constant, but we would have to extend
2228 * the div array too as the number of rows in this array is assumed
2229 * to be equal to extra.
2231 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2232 enum isl_dim_type type, unsigned first, unsigned n)
2234 if (!bmap)
2235 return NULL;
2236 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2237 return bmap;
2239 bmap = isl_basic_map_cow(bmap);
2240 if (!bmap)
2241 return NULL;
2243 bmap = isl_basic_map_drop_core(bmap, type, first, n);
2245 bmap = isl_basic_map_simplify(bmap);
2246 return isl_basic_map_finalize(bmap);
2249 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2250 enum isl_dim_type type, unsigned first, unsigned n)
2252 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2253 type, first, n));
2256 /* No longer consider "map" to be normalized.
2258 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2260 if (!map)
2261 return NULL;
2262 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2263 return map;
2266 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2267 enum isl_dim_type type, unsigned first, unsigned n)
2269 int i;
2271 if (isl_map_check_range(map, type, first, n) < 0)
2272 return isl_map_free(map);
2274 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2275 return map;
2276 map = isl_map_cow(map);
2277 if (!map)
2278 goto error;
2279 map->dim = isl_space_drop_dims(map->dim, type, first, n);
2280 if (!map->dim)
2281 goto error;
2283 for (i = 0; i < map->n; ++i) {
2284 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2285 if (!map->p[i])
2286 goto error;
2288 map = isl_map_unmark_normalized(map);
2290 return map;
2291 error:
2292 isl_map_free(map);
2293 return NULL;
2296 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2297 enum isl_dim_type type, unsigned first, unsigned n)
2299 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2302 /* Drop the integer division at position "div", which is assumed
2303 * not to appear in any of the constraints or
2304 * in any of the other integer divisions.
2306 * Since the integer division is redundant, there is no need to cow.
2308 __isl_give isl_basic_map *isl_basic_map_drop_div(
2309 __isl_take isl_basic_map *bmap, unsigned div)
2311 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2314 /* Eliminate the specified n dimensions starting at first from the
2315 * constraints, without removing the dimensions from the space.
2316 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2318 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2319 enum isl_dim_type type, unsigned first, unsigned n)
2321 int i;
2323 if (n == 0)
2324 return map;
2326 if (isl_map_check_range(map, type, first, n) < 0)
2327 return isl_map_free(map);
2329 map = isl_map_cow(map);
2330 if (!map)
2331 return NULL;
2333 for (i = 0; i < map->n; ++i) {
2334 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2335 if (!map->p[i])
2336 goto error;
2338 return map;
2339 error:
2340 isl_map_free(map);
2341 return NULL;
2344 /* Eliminate the specified n dimensions starting at first from the
2345 * constraints, without removing the dimensions from the space.
2346 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2348 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2349 enum isl_dim_type type, unsigned first, unsigned n)
2351 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2354 /* Eliminate the specified n dimensions starting at first from the
2355 * constraints, without removing the dimensions from the space.
2356 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2358 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2359 unsigned first, unsigned n)
2361 return isl_set_eliminate(set, isl_dim_set, first, n);
2364 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2365 __isl_take isl_basic_map *bmap)
2367 if (!bmap)
2368 return NULL;
2369 bmap = isl_basic_map_eliminate_vars(bmap,
2370 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
2371 if (!bmap)
2372 return NULL;
2373 bmap->n_div = 0;
2374 return isl_basic_map_finalize(bmap);
2377 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2378 __isl_take isl_basic_set *bset)
2380 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2383 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2385 int i;
2387 if (!map)
2388 return NULL;
2389 if (map->n == 0)
2390 return map;
2392 map = isl_map_cow(map);
2393 if (!map)
2394 return NULL;
2396 for (i = 0; i < map->n; ++i) {
2397 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2398 if (!map->p[i])
2399 goto error;
2401 return map;
2402 error:
2403 isl_map_free(map);
2404 return NULL;
2407 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2409 return isl_map_remove_divs(set);
2412 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2413 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2414 unsigned first, unsigned n)
2416 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2417 return isl_basic_map_free(bmap);
2418 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2419 return bmap;
2420 bmap = isl_basic_map_eliminate_vars(bmap,
2421 isl_basic_map_offset(bmap, type) - 1 + first, n);
2422 if (!bmap)
2423 return bmap;
2424 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2425 return bmap;
2426 bmap = isl_basic_map_drop(bmap, type, first, n);
2427 return bmap;
2430 /* Return true if the definition of the given div (recursively) involves
2431 * any of the given variables.
2433 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2434 unsigned first, unsigned n)
2436 int i;
2437 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2439 if (isl_int_is_zero(bmap->div[div][0]))
2440 return isl_bool_false;
2441 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2442 return isl_bool_true;
2444 for (i = bmap->n_div - 1; i >= 0; --i) {
2445 isl_bool involves;
2447 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2448 continue;
2449 involves = div_involves_vars(bmap, i, first, n);
2450 if (involves < 0 || involves)
2451 return involves;
2454 return isl_bool_false;
2457 /* Try and add a lower and/or upper bound on "div" to "bmap"
2458 * based on inequality "i".
2459 * "total" is the total number of variables (excluding the divs).
2460 * "v" is a temporary object that can be used during the calculations.
2461 * If "lb" is set, then a lower bound should be constructed.
2462 * If "ub" is set, then an upper bound should be constructed.
2464 * The calling function has already checked that the inequality does not
2465 * reference "div", but we still need to check that the inequality is
2466 * of the right form. We'll consider the case where we want to construct
2467 * a lower bound. The construction of upper bounds is similar.
2469 * Let "div" be of the form
2471 * q = floor((a + f(x))/d)
2473 * We essentially check if constraint "i" is of the form
2475 * b + f(x) >= 0
2477 * so that we can use it to derive a lower bound on "div".
2478 * However, we allow a slightly more general form
2480 * b + g(x) >= 0
2482 * with the condition that the coefficients of g(x) - f(x) are all
2483 * divisible by d.
2484 * Rewriting this constraint as
2486 * 0 >= -b - g(x)
2488 * adding a + f(x) to both sides and dividing by d, we obtain
2490 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2492 * Taking the floor on both sides, we obtain
2494 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2496 * or
2498 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2500 * In the case of an upper bound, we construct the constraint
2502 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2505 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2506 __isl_take isl_basic_map *bmap, int div, int i,
2507 unsigned total, isl_int v, int lb, int ub)
2509 int j;
2511 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2512 if (lb) {
2513 isl_int_sub(v, bmap->ineq[i][1 + j],
2514 bmap->div[div][1 + 1 + j]);
2515 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2517 if (ub) {
2518 isl_int_add(v, bmap->ineq[i][1 + j],
2519 bmap->div[div][1 + 1 + j]);
2520 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2523 if (!lb && !ub)
2524 return bmap;
2526 bmap = isl_basic_map_cow(bmap);
2527 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2528 if (lb) {
2529 int k = isl_basic_map_alloc_inequality(bmap);
2530 if (k < 0)
2531 goto error;
2532 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2533 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2534 bmap->div[div][1 + j]);
2535 isl_int_cdiv_q(bmap->ineq[k][j],
2536 bmap->ineq[k][j], bmap->div[div][0]);
2538 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2540 if (ub) {
2541 int k = isl_basic_map_alloc_inequality(bmap);
2542 if (k < 0)
2543 goto error;
2544 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2545 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2546 bmap->div[div][1 + j]);
2547 isl_int_fdiv_q(bmap->ineq[k][j],
2548 bmap->ineq[k][j], bmap->div[div][0]);
2550 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2553 return bmap;
2554 error:
2555 isl_basic_map_free(bmap);
2556 return NULL;
2559 /* This function is called right before "div" is eliminated from "bmap"
2560 * using Fourier-Motzkin.
2561 * Look through the constraints of "bmap" for constraints on the argument
2562 * of the integer division and use them to construct constraints on the
2563 * integer division itself. These constraints can then be combined
2564 * during the Fourier-Motzkin elimination.
2565 * Note that it is only useful to introduce lower bounds on "div"
2566 * if "bmap" already contains upper bounds on "div" as the newly
2567 * introduce lower bounds can then be combined with the pre-existing
2568 * upper bounds. Similarly for upper bounds.
2569 * We therefore first check if "bmap" contains any lower and/or upper bounds
2570 * on "div".
2572 * It is interesting to note that the introduction of these constraints
2573 * can indeed lead to more accurate results, even when compared to
2574 * deriving constraints on the argument of "div" from constraints on "div".
2575 * Consider, for example, the set
2577 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2579 * The second constraint can be rewritten as
2581 * 2 * [(-i-2j+3)/4] + k >= 0
2583 * from which we can derive
2585 * -i - 2j + 3 >= -2k
2587 * or
2589 * i + 2j <= 3 + 2k
2591 * Combined with the first constraint, we obtain
2593 * -3 <= 3 + 2k or k >= -3
2595 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2596 * the first constraint, we obtain
2598 * [(i + 2j)/4] >= [-3/4] = -1
2600 * Combining this constraint with the second constraint, we obtain
2602 * k >= -2
2604 static __isl_give isl_basic_map *insert_bounds_on_div(
2605 __isl_take isl_basic_map *bmap, int div)
2607 int i;
2608 int check_lb, check_ub;
2609 isl_int v;
2610 unsigned total;
2612 if (!bmap)
2613 return NULL;
2615 if (isl_int_is_zero(bmap->div[div][0]))
2616 return bmap;
2618 total = isl_space_dim(bmap->dim, isl_dim_all);
2620 check_lb = 0;
2621 check_ub = 0;
2622 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2623 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2624 if (s > 0)
2625 check_ub = 1;
2626 if (s < 0)
2627 check_lb = 1;
2630 if (!check_lb && !check_ub)
2631 return bmap;
2633 isl_int_init(v);
2635 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2636 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2637 continue;
2639 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2640 check_lb, check_ub);
2643 isl_int_clear(v);
2645 return bmap;
2648 /* Remove all divs (recursively) involving any of the given dimensions
2649 * in their definitions.
2651 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2652 __isl_take isl_basic_map *bmap,
2653 enum isl_dim_type type, unsigned first, unsigned n)
2655 int i;
2657 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2658 return isl_basic_map_free(bmap);
2659 first += isl_basic_map_offset(bmap, type);
2661 for (i = bmap->n_div - 1; i >= 0; --i) {
2662 isl_bool involves;
2664 involves = div_involves_vars(bmap, i, first, n);
2665 if (involves < 0)
2666 return isl_basic_map_free(bmap);
2667 if (!involves)
2668 continue;
2669 bmap = insert_bounds_on_div(bmap, i);
2670 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2671 if (!bmap)
2672 return NULL;
2673 i = bmap->n_div;
2676 return bmap;
2679 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2680 __isl_take isl_basic_set *bset,
2681 enum isl_dim_type type, unsigned first, unsigned n)
2683 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2686 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2687 enum isl_dim_type type, unsigned first, unsigned n)
2689 int i;
2691 if (!map)
2692 return NULL;
2693 if (map->n == 0)
2694 return map;
2696 map = isl_map_cow(map);
2697 if (!map)
2698 return NULL;
2700 for (i = 0; i < map->n; ++i) {
2701 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2702 type, first, n);
2703 if (!map->p[i])
2704 goto error;
2706 return map;
2707 error:
2708 isl_map_free(map);
2709 return NULL;
2712 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2713 enum isl_dim_type type, unsigned first, unsigned n)
2715 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2716 type, first, n));
2719 /* Does the description of "bmap" depend on the specified dimensions?
2720 * We also check whether the dimensions appear in any of the div definitions.
2721 * In principle there is no need for this check. If the dimensions appear
2722 * in a div definition, they also appear in the defining constraints of that
2723 * div.
2725 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2726 enum isl_dim_type type, unsigned first, unsigned n)
2728 int i;
2730 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2731 return isl_bool_error;
2733 first += isl_basic_map_offset(bmap, type);
2734 for (i = 0; i < bmap->n_eq; ++i)
2735 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2736 return isl_bool_true;
2737 for (i = 0; i < bmap->n_ineq; ++i)
2738 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2739 return isl_bool_true;
2740 for (i = 0; i < bmap->n_div; ++i) {
2741 if (isl_int_is_zero(bmap->div[i][0]))
2742 continue;
2743 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2744 return isl_bool_true;
2747 return isl_bool_false;
2750 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2751 enum isl_dim_type type, unsigned first, unsigned n)
2753 int i;
2755 if (isl_map_check_range(map, type, first, n) < 0)
2756 return isl_bool_error;
2758 for (i = 0; i < map->n; ++i) {
2759 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2760 type, first, n);
2761 if (involves < 0 || involves)
2762 return involves;
2765 return isl_bool_false;
2768 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2769 enum isl_dim_type type, unsigned first, unsigned n)
2771 return isl_basic_map_involves_dims(bset, type, first, n);
2774 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2775 enum isl_dim_type type, unsigned first, unsigned n)
2777 return isl_map_involves_dims(set, type, first, n);
2780 /* Drop all constraints in bmap that involve any of the dimensions
2781 * first to first+n-1.
2782 * This function only performs the actual removal of constraints.
2784 * This function should not call finalize since it is used by
2785 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
2787 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2788 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2790 int i;
2792 if (n == 0)
2793 return bmap;
2795 bmap = isl_basic_map_cow(bmap);
2797 if (!bmap)
2798 return NULL;
2800 for (i = bmap->n_eq - 1; i >= 0; --i) {
2801 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2802 continue;
2803 isl_basic_map_drop_equality(bmap, i);
2806 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2807 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2808 continue;
2809 isl_basic_map_drop_inequality(bmap, i);
2812 return bmap;
2815 /* Drop all constraints in bset that involve any of the dimensions
2816 * first to first+n-1.
2817 * This function only performs the actual removal of constraints.
2819 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2820 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2822 return isl_basic_map_drop_constraints_involving(bset, first, n);
2825 /* Drop all constraints in bmap that do not involve any of the dimensions
2826 * first to first + n - 1 of the given type.
2828 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2829 __isl_take isl_basic_map *bmap,
2830 enum isl_dim_type type, unsigned first, unsigned n)
2832 int i;
2834 if (n == 0) {
2835 isl_space *space = isl_basic_map_get_space(bmap);
2836 isl_basic_map_free(bmap);
2837 return isl_basic_map_universe(space);
2839 bmap = isl_basic_map_cow(bmap);
2840 if (!bmap)
2841 return NULL;
2843 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2844 return isl_basic_map_free(bmap);
2846 first += isl_basic_map_offset(bmap, type) - 1;
2848 for (i = bmap->n_eq - 1; i >= 0; --i) {
2849 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2850 continue;
2851 isl_basic_map_drop_equality(bmap, i);
2854 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2855 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2856 continue;
2857 isl_basic_map_drop_inequality(bmap, i);
2860 bmap = isl_basic_map_add_known_div_constraints(bmap);
2861 return bmap;
2864 /* Drop all constraints in bset that do not involve any of the dimensions
2865 * first to first + n - 1 of the given type.
2867 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2868 __isl_take isl_basic_set *bset,
2869 enum isl_dim_type type, unsigned first, unsigned n)
2871 return isl_basic_map_drop_constraints_not_involving_dims(bset,
2872 type, first, n);
2875 /* Drop all constraints in bmap that involve any of the dimensions
2876 * first to first + n - 1 of the given type.
2878 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2879 __isl_take isl_basic_map *bmap,
2880 enum isl_dim_type type, unsigned first, unsigned n)
2882 if (!bmap)
2883 return NULL;
2884 if (n == 0)
2885 return bmap;
2887 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2888 return isl_basic_map_free(bmap);
2890 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2891 first += isl_basic_map_offset(bmap, type) - 1;
2892 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
2893 bmap = isl_basic_map_add_known_div_constraints(bmap);
2894 return bmap;
2897 /* Drop all constraints in bset that involve any of the dimensions
2898 * first to first + n - 1 of the given type.
2900 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2901 __isl_take isl_basic_set *bset,
2902 enum isl_dim_type type, unsigned first, unsigned n)
2904 return isl_basic_map_drop_constraints_involving_dims(bset,
2905 type, first, n);
2908 /* Drop constraints from "map" by applying "drop" to each basic map.
2910 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2911 enum isl_dim_type type, unsigned first, unsigned n,
2912 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2913 enum isl_dim_type type, unsigned first, unsigned n))
2915 int i;
2917 if (isl_map_check_range(map, type, first, n) < 0)
2918 return isl_map_free(map);
2920 map = isl_map_cow(map);
2921 if (!map)
2922 return NULL;
2924 for (i = 0; i < map->n; ++i) {
2925 map->p[i] = drop(map->p[i], type, first, n);
2926 if (!map->p[i])
2927 return isl_map_free(map);
2930 if (map->n > 1)
2931 ISL_F_CLR(map, ISL_MAP_DISJOINT);
2933 return map;
2936 /* Drop all constraints in map that involve any of the dimensions
2937 * first to first + n - 1 of the given type.
2939 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
2940 __isl_take isl_map *map,
2941 enum isl_dim_type type, unsigned first, unsigned n)
2943 if (n == 0)
2944 return map;
2945 return drop_constraints(map, type, first, n,
2946 &isl_basic_map_drop_constraints_involving_dims);
2949 /* Drop all constraints in "map" that do not involve any of the dimensions
2950 * first to first + n - 1 of the given type.
2952 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
2953 __isl_take isl_map *map,
2954 enum isl_dim_type type, unsigned first, unsigned n)
2956 if (n == 0) {
2957 isl_space *space = isl_map_get_space(map);
2958 isl_map_free(map);
2959 return isl_map_universe(space);
2961 return drop_constraints(map, type, first, n,
2962 &isl_basic_map_drop_constraints_not_involving_dims);
2965 /* Drop all constraints in set that involve any of the dimensions
2966 * first to first + n - 1 of the given type.
2968 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
2969 __isl_take isl_set *set,
2970 enum isl_dim_type type, unsigned first, unsigned n)
2972 return isl_map_drop_constraints_involving_dims(set, type, first, n);
2975 /* Drop all constraints in "set" that do not involve any of the dimensions
2976 * first to first + n - 1 of the given type.
2978 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
2979 __isl_take isl_set *set,
2980 enum isl_dim_type type, unsigned first, unsigned n)
2982 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
2985 /* Does local variable "div" of "bmap" have a complete explicit representation?
2986 * Having a complete explicit representation requires not only
2987 * an explicit representation, but also that all local variables
2988 * that appear in this explicit representation in turn have
2989 * a complete explicit representation.
2991 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
2993 int i;
2994 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2995 isl_bool marked;
2997 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
2998 if (marked < 0 || marked)
2999 return isl_bool_not(marked);
3001 for (i = bmap->n_div - 1; i >= 0; --i) {
3002 isl_bool known;
3004 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3005 continue;
3006 known = isl_basic_map_div_is_known(bmap, i);
3007 if (known < 0 || !known)
3008 return known;
3011 return isl_bool_true;
3014 /* Remove all divs that are unknown or defined in terms of unknown divs.
3016 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3017 __isl_take isl_basic_map *bmap)
3019 int i;
3021 if (!bmap)
3022 return NULL;
3024 for (i = bmap->n_div - 1; i >= 0; --i) {
3025 if (isl_basic_map_div_is_known(bmap, i))
3026 continue;
3027 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3028 if (!bmap)
3029 return NULL;
3030 i = bmap->n_div;
3033 return bmap;
3036 /* Remove all divs that are unknown or defined in terms of unknown divs.
3038 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3039 __isl_take isl_basic_set *bset)
3041 return isl_basic_map_remove_unknown_divs(bset);
3044 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3046 int i;
3048 if (!map)
3049 return NULL;
3050 if (map->n == 0)
3051 return map;
3053 map = isl_map_cow(map);
3054 if (!map)
3055 return NULL;
3057 for (i = 0; i < map->n; ++i) {
3058 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3059 if (!map->p[i])
3060 goto error;
3062 return map;
3063 error:
3064 isl_map_free(map);
3065 return NULL;
3068 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3070 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3073 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3074 __isl_take isl_basic_set *bset,
3075 enum isl_dim_type type, unsigned first, unsigned n)
3077 isl_basic_map *bmap = bset_to_bmap(bset);
3078 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3079 return bset_from_bmap(bmap);
3082 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3083 enum isl_dim_type type, unsigned first, unsigned n)
3085 int i;
3087 if (n == 0)
3088 return map;
3090 map = isl_map_cow(map);
3091 if (isl_map_check_range(map, type, first, n) < 0)
3092 return isl_map_free(map);
3094 for (i = 0; i < map->n; ++i) {
3095 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3096 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3097 if (!map->p[i])
3098 goto error;
3100 map = isl_map_drop(map, type, first, n);
3101 return map;
3102 error:
3103 isl_map_free(map);
3104 return NULL;
3107 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3108 enum isl_dim_type type, unsigned first, unsigned n)
3110 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3111 type, first, n));
3114 /* Project out n inputs starting at first using Fourier-Motzkin */
3115 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
3116 unsigned first, unsigned n)
3118 return isl_map_remove_dims(map, isl_dim_in, first, n);
3121 static void dump_term(struct isl_basic_map *bmap,
3122 isl_int c, int pos, FILE *out)
3124 const char *name;
3125 unsigned in = isl_basic_map_dim(bmap, isl_dim_in);
3126 unsigned dim = in + isl_basic_map_dim(bmap, isl_dim_out);
3127 unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
3128 if (!pos)
3129 isl_int_print(out, c, 0);
3130 else {
3131 if (!isl_int_is_one(c))
3132 isl_int_print(out, c, 0);
3133 if (pos < 1 + nparam) {
3134 name = isl_space_get_dim_name(bmap->dim,
3135 isl_dim_param, pos - 1);
3136 if (name)
3137 fprintf(out, "%s", name);
3138 else
3139 fprintf(out, "p%d", pos - 1);
3140 } else if (pos < 1 + nparam + in)
3141 fprintf(out, "i%d", pos - 1 - nparam);
3142 else if (pos < 1 + nparam + dim)
3143 fprintf(out, "o%d", pos - 1 - nparam - in);
3144 else
3145 fprintf(out, "e%d", pos - 1 - nparam - dim);
3149 static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
3150 int sign, FILE *out)
3152 int i;
3153 int first;
3154 unsigned len = 1 + isl_basic_map_total_dim(bmap);
3155 isl_int v;
3157 isl_int_init(v);
3158 for (i = 0, first = 1; i < len; ++i) {
3159 if (isl_int_sgn(c[i]) * sign <= 0)
3160 continue;
3161 if (!first)
3162 fprintf(out, " + ");
3163 first = 0;
3164 isl_int_abs(v, c[i]);
3165 dump_term(bmap, v, i, out);
3167 isl_int_clear(v);
3168 if (first)
3169 fprintf(out, "0");
3172 static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
3173 const char *op, FILE *out, int indent)
3175 int i;
3177 fprintf(out, "%*s", indent, "");
3179 dump_constraint_sign(bmap, c, 1, out);
3180 fprintf(out, " %s ", op);
3181 dump_constraint_sign(bmap, c, -1, out);
3183 fprintf(out, "\n");
3185 for (i = bmap->n_div; i < bmap->extra; ++i) {
3186 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
3187 continue;
3188 fprintf(out, "%*s", indent, "");
3189 fprintf(out, "ERROR: unused div coefficient not zero\n");
3190 abort();
3194 static void dump_constraints(struct isl_basic_map *bmap,
3195 isl_int **c, unsigned n,
3196 const char *op, FILE *out, int indent)
3198 int i;
3200 for (i = 0; i < n; ++i)
3201 dump_constraint(bmap, c[i], op, out, indent);
3204 static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
3206 int j;
3207 int first = 1;
3208 unsigned total = isl_basic_map_total_dim(bmap);
3210 for (j = 0; j < 1 + total; ++j) {
3211 if (isl_int_is_zero(exp[j]))
3212 continue;
3213 if (!first && isl_int_is_pos(exp[j]))
3214 fprintf(out, "+");
3215 dump_term(bmap, exp[j], j, out);
3216 first = 0;
3220 static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
3222 int i;
3224 dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
3225 dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
3227 for (i = 0; i < bmap->n_div; ++i) {
3228 fprintf(out, "%*s", indent, "");
3229 fprintf(out, "e%d = [(", i);
3230 dump_affine(bmap, bmap->div[i]+1, out);
3231 fprintf(out, ")/");
3232 isl_int_print(out, bmap->div[i][0], 0);
3233 fprintf(out, "]\n");
3237 void isl_basic_set_print_internal(struct isl_basic_set *bset,
3238 FILE *out, int indent)
3240 if (!bset) {
3241 fprintf(out, "null basic set\n");
3242 return;
3245 fprintf(out, "%*s", indent, "");
3246 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3247 bset->ref, bset->dim->nparam, bset->dim->n_out,
3248 bset->extra, bset->flags);
3249 dump(bset_to_bmap(bset), out, indent);
3252 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
3253 FILE *out, int indent)
3255 if (!bmap) {
3256 fprintf(out, "null basic map\n");
3257 return;
3260 fprintf(out, "%*s", indent, "");
3261 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3262 "flags: %x, n_name: %d\n",
3263 bmap->ref,
3264 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3265 bmap->extra, bmap->flags, bmap->dim->n_id);
3266 dump(bmap, out, indent);
3269 int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
3271 unsigned total;
3272 if (!bmap)
3273 return -1;
3274 total = isl_basic_map_total_dim(bmap);
3275 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
3276 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3277 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3278 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3279 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3280 return 0;
3283 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3284 unsigned flags)
3286 if (isl_space_check_is_set(space) < 0)
3287 goto error;
3288 return isl_map_alloc_space(space, n, flags);
3289 error:
3290 isl_space_free(space);
3291 return NULL;
3294 /* Make sure "map" has room for at least "n" more basic maps.
3296 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3298 int i;
3299 struct isl_map *grown = NULL;
3301 if (!map)
3302 return NULL;
3303 isl_assert(map->ctx, n >= 0, goto error);
3304 if (map->n + n <= map->size)
3305 return map;
3306 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3307 if (!grown)
3308 goto error;
3309 for (i = 0; i < map->n; ++i) {
3310 grown->p[i] = isl_basic_map_copy(map->p[i]);
3311 if (!grown->p[i])
3312 goto error;
3313 grown->n++;
3315 isl_map_free(map);
3316 return grown;
3317 error:
3318 isl_map_free(grown);
3319 isl_map_free(map);
3320 return NULL;
3323 /* Make sure "set" has room for at least "n" more basic sets.
3325 struct isl_set *isl_set_grow(struct isl_set *set, int n)
3327 return set_from_map(isl_map_grow(set_to_map(set), n));
3330 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3332 return isl_map_from_basic_map(bset);
3335 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3337 struct isl_map *map;
3339 if (!bmap)
3340 return NULL;
3342 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3343 return isl_map_add_basic_map(map, bmap);
3346 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3347 __isl_take isl_basic_set *bset)
3349 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3350 bset_to_bmap(bset)));
3353 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3355 return isl_map_free(set);
3358 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3360 int i;
3362 if (!set) {
3363 fprintf(out, "null set\n");
3364 return;
3367 fprintf(out, "%*s", indent, "");
3368 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3369 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3370 set->flags);
3371 for (i = 0; i < set->n; ++i) {
3372 fprintf(out, "%*s", indent, "");
3373 fprintf(out, "basic set %d:\n", i);
3374 isl_basic_set_print_internal(set->p[i], out, indent+4);
3378 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3380 int i;
3382 if (!map) {
3383 fprintf(out, "null map\n");
3384 return;
3387 fprintf(out, "%*s", indent, "");
3388 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3389 "flags: %x, n_name: %d\n",
3390 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3391 map->dim->n_out, map->flags, map->dim->n_id);
3392 for (i = 0; i < map->n; ++i) {
3393 fprintf(out, "%*s", indent, "");
3394 fprintf(out, "basic map %d:\n", i);
3395 isl_basic_map_print_internal(map->p[i], out, indent+4);
3399 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3400 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3402 struct isl_basic_map *bmap_domain;
3404 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3405 goto error;
3407 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
3408 isl_assert(bset->ctx,
3409 isl_basic_map_compatible_domain(bmap, bset), goto error);
3411 bmap = isl_basic_map_cow(bmap);
3412 if (!bmap)
3413 goto error;
3414 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3415 bset->n_div, bset->n_eq, bset->n_ineq);
3416 bmap_domain = isl_basic_map_from_domain(bset);
3417 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3419 bmap = isl_basic_map_simplify(bmap);
3420 return isl_basic_map_finalize(bmap);
3421 error:
3422 isl_basic_map_free(bmap);
3423 isl_basic_set_free(bset);
3424 return NULL;
3427 /* Check that the space of "bset" is the same as that of the range of "bmap".
3429 static isl_stat isl_basic_map_check_compatible_range(
3430 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3432 isl_bool ok;
3434 ok = isl_basic_map_compatible_range(bmap, bset);
3435 if (ok < 0)
3436 return isl_stat_error;
3437 if (!ok)
3438 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3439 "incompatible spaces", return isl_stat_error);
3441 return isl_stat_ok;
3444 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3445 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3447 struct isl_basic_map *bmap_range;
3449 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3450 goto error;
3452 if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
3453 isl_basic_map_check_compatible_range(bmap, bset) < 0)
3454 goto error;
3456 if (isl_basic_set_plain_is_universe(bset)) {
3457 isl_basic_set_free(bset);
3458 return bmap;
3461 bmap = isl_basic_map_cow(bmap);
3462 if (!bmap)
3463 goto error;
3464 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3465 bset->n_div, bset->n_eq, bset->n_ineq);
3466 bmap_range = bset_to_bmap(bset);
3467 bmap = add_constraints(bmap, bmap_range, 0, 0);
3469 bmap = isl_basic_map_simplify(bmap);
3470 return isl_basic_map_finalize(bmap);
3471 error:
3472 isl_basic_map_free(bmap);
3473 isl_basic_set_free(bset);
3474 return NULL;
3477 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3478 __isl_keep isl_vec *vec)
3480 int i;
3481 unsigned total;
3482 isl_int s;
3484 if (!bmap || !vec)
3485 return isl_bool_error;
3487 total = 1 + isl_basic_map_total_dim(bmap);
3488 if (total != vec->size)
3489 return isl_bool_false;
3491 isl_int_init(s);
3493 for (i = 0; i < bmap->n_eq; ++i) {
3494 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3495 if (!isl_int_is_zero(s)) {
3496 isl_int_clear(s);
3497 return isl_bool_false;
3501 for (i = 0; i < bmap->n_ineq; ++i) {
3502 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3503 if (isl_int_is_neg(s)) {
3504 isl_int_clear(s);
3505 return isl_bool_false;
3509 isl_int_clear(s);
3511 return isl_bool_true;
3514 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3515 __isl_keep isl_vec *vec)
3517 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3520 __isl_give isl_basic_map *isl_basic_map_intersect(
3521 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3523 struct isl_vec *sample = NULL;
3525 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3526 goto error;
3527 if (isl_space_dim(bmap1->dim, isl_dim_all) ==
3528 isl_space_dim(bmap1->dim, isl_dim_param) &&
3529 isl_space_dim(bmap2->dim, isl_dim_all) !=
3530 isl_space_dim(bmap2->dim, isl_dim_param))
3531 return isl_basic_map_intersect(bmap2, bmap1);
3533 if (isl_space_dim(bmap2->dim, isl_dim_all) !=
3534 isl_space_dim(bmap2->dim, isl_dim_param))
3535 isl_assert(bmap1->ctx,
3536 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3538 if (isl_basic_map_plain_is_empty(bmap1)) {
3539 isl_basic_map_free(bmap2);
3540 return bmap1;
3542 if (isl_basic_map_plain_is_empty(bmap2)) {
3543 isl_basic_map_free(bmap1);
3544 return bmap2;
3547 if (bmap1->sample &&
3548 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3549 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3550 sample = isl_vec_copy(bmap1->sample);
3551 else if (bmap2->sample &&
3552 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3553 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3554 sample = isl_vec_copy(bmap2->sample);
3556 bmap1 = isl_basic_map_cow(bmap1);
3557 if (!bmap1)
3558 goto error;
3559 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3560 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3561 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3563 if (!bmap1)
3564 isl_vec_free(sample);
3565 else if (sample) {
3566 isl_vec_free(bmap1->sample);
3567 bmap1->sample = sample;
3570 bmap1 = isl_basic_map_simplify(bmap1);
3571 return isl_basic_map_finalize(bmap1);
3572 error:
3573 if (sample)
3574 isl_vec_free(sample);
3575 isl_basic_map_free(bmap1);
3576 isl_basic_map_free(bmap2);
3577 return NULL;
3580 struct isl_basic_set *isl_basic_set_intersect(
3581 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3583 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3584 bset_to_bmap(bset2)));
3587 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3588 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3590 return isl_basic_set_intersect(bset1, bset2);
3593 /* Special case of isl_map_intersect, where both map1 and map2
3594 * are convex, without any divs and such that either map1 or map2
3595 * contains a single constraint. This constraint is then simply
3596 * added to the other map.
3598 static __isl_give isl_map *map_intersect_add_constraint(
3599 __isl_take isl_map *map1, __isl_take isl_map *map2)
3601 isl_assert(map1->ctx, map1->n == 1, goto error);
3602 isl_assert(map2->ctx, map1->n == 1, goto error);
3603 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3604 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3606 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3607 return isl_map_intersect(map2, map1);
3609 map1 = isl_map_cow(map1);
3610 if (!map1)
3611 goto error;
3612 if (isl_map_plain_is_empty(map1)) {
3613 isl_map_free(map2);
3614 return map1;
3616 if (map2->p[0]->n_eq == 1)
3617 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3618 else
3619 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3620 map2->p[0]->ineq[0]);
3622 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3623 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3624 if (!map1->p[0])
3625 goto error;
3627 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3628 isl_basic_map_free(map1->p[0]);
3629 map1->n = 0;
3632 isl_map_free(map2);
3634 map1 = isl_map_unmark_normalized(map1);
3635 return map1;
3636 error:
3637 isl_map_free(map1);
3638 isl_map_free(map2);
3639 return NULL;
3642 /* map2 may be either a parameter domain or a map living in the same
3643 * space as map1.
3645 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3646 __isl_take isl_map *map2)
3648 unsigned flags = 0;
3649 isl_bool equal;
3650 isl_map *result;
3651 int i, j;
3653 if (!map1 || !map2)
3654 goto error;
3656 if ((isl_map_plain_is_empty(map1) ||
3657 isl_map_plain_is_universe(map2)) &&
3658 isl_space_is_equal(map1->dim, map2->dim)) {
3659 isl_map_free(map2);
3660 return map1;
3662 if ((isl_map_plain_is_empty(map2) ||
3663 isl_map_plain_is_universe(map1)) &&
3664 isl_space_is_equal(map1->dim, map2->dim)) {
3665 isl_map_free(map1);
3666 return map2;
3669 if (map1->n == 1 && map2->n == 1 &&
3670 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3671 isl_space_is_equal(map1->dim, map2->dim) &&
3672 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3673 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3674 return map_intersect_add_constraint(map1, map2);
3676 equal = isl_map_plain_is_equal(map1, map2);
3677 if (equal < 0)
3678 goto error;
3679 if (equal) {
3680 isl_map_free(map2);
3681 return map1;
3684 if (isl_space_dim(map2->dim, isl_dim_all) !=
3685 isl_space_dim(map2->dim, isl_dim_param))
3686 isl_assert(map1->ctx,
3687 isl_space_is_equal(map1->dim, map2->dim), goto error);
3689 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3690 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3691 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3693 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3694 map1->n * map2->n, flags);
3695 if (!result)
3696 goto error;
3697 for (i = 0; i < map1->n; ++i)
3698 for (j = 0; j < map2->n; ++j) {
3699 struct isl_basic_map *part;
3700 part = isl_basic_map_intersect(
3701 isl_basic_map_copy(map1->p[i]),
3702 isl_basic_map_copy(map2->p[j]));
3703 if (isl_basic_map_is_empty(part) < 0)
3704 part = isl_basic_map_free(part);
3705 result = isl_map_add_basic_map(result, part);
3706 if (!result)
3707 goto error;
3709 isl_map_free(map1);
3710 isl_map_free(map2);
3711 return result;
3712 error:
3713 isl_map_free(map1);
3714 isl_map_free(map2);
3715 return NULL;
3718 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3719 __isl_take isl_map *map2)
3721 if (!map1 || !map2)
3722 goto error;
3723 if (!isl_space_is_equal(map1->dim, map2->dim))
3724 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3725 "spaces don't match", goto error);
3726 return map_intersect_internal(map1, map2);
3727 error:
3728 isl_map_free(map1);
3729 isl_map_free(map2);
3730 return NULL;
3733 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3734 __isl_take isl_map *map2)
3736 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3739 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3741 return set_from_map(isl_map_intersect(set_to_map(set1),
3742 set_to_map(set2)));
3745 /* map_intersect_internal accepts intersections
3746 * with parameter domains, so we can just call that function.
3748 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3749 __isl_take isl_set *params)
3751 return map_intersect_internal(map, params);
3754 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3755 __isl_take isl_map *map2)
3757 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3760 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3761 __isl_take isl_set *params)
3763 return isl_map_intersect_params(set, params);
3766 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3768 isl_space *space;
3769 unsigned pos, n1, n2;
3771 if (!bmap)
3772 return NULL;
3773 bmap = isl_basic_map_cow(bmap);
3774 if (!bmap)
3775 return NULL;
3776 space = isl_space_reverse(isl_space_copy(bmap->dim));
3777 pos = isl_basic_map_offset(bmap, isl_dim_in);
3778 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3779 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3780 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3781 return isl_basic_map_reset_space(bmap, space);
3784 static __isl_give isl_basic_map *basic_map_space_reset(
3785 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3787 isl_space *space;
3789 if (!bmap)
3790 return NULL;
3791 if (!isl_space_is_named_or_nested(bmap->dim, type))
3792 return bmap;
3794 space = isl_basic_map_get_space(bmap);
3795 space = isl_space_reset(space, type);
3796 bmap = isl_basic_map_reset_space(bmap, space);
3797 return bmap;
3800 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3801 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3802 unsigned pos, unsigned n)
3804 isl_bool rational;
3805 isl_space *res_space;
3806 struct isl_basic_map *res;
3807 struct isl_dim_map *dim_map;
3808 unsigned total, off;
3809 enum isl_dim_type t;
3811 if (n == 0)
3812 return basic_map_space_reset(bmap, type);
3814 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3815 type, pos, n);
3816 if (!res_space)
3817 return isl_basic_map_free(bmap);
3819 total = isl_basic_map_total_dim(bmap) + n;
3820 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3821 off = 0;
3822 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3823 if (t != type) {
3824 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3825 } else {
3826 unsigned size = isl_basic_map_dim(bmap, t);
3827 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3828 0, pos, off);
3829 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3830 pos, size - pos, off + pos + n);
3832 off += isl_space_dim(res_space, t);
3834 isl_dim_map_div(dim_map, bmap, off);
3836 res = isl_basic_map_alloc_space(res_space,
3837 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3838 rational = isl_basic_map_is_rational(bmap);
3839 if (rational < 0)
3840 res = isl_basic_map_free(res);
3841 if (rational)
3842 res = isl_basic_map_set_rational(res);
3843 if (isl_basic_map_plain_is_empty(bmap)) {
3844 isl_basic_map_free(bmap);
3845 free(dim_map);
3846 return isl_basic_map_set_to_empty(res);
3848 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3849 return isl_basic_map_finalize(res);
3852 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3853 __isl_take isl_basic_set *bset,
3854 enum isl_dim_type type, unsigned pos, unsigned n)
3856 return isl_basic_map_insert_dims(bset, type, pos, n);
3859 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3860 enum isl_dim_type type, unsigned n)
3862 if (!bmap)
3863 return NULL;
3864 return isl_basic_map_insert_dims(bmap, type,
3865 isl_basic_map_dim(bmap, type), n);
3868 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3869 enum isl_dim_type type, unsigned n)
3871 if (!bset)
3872 return NULL;
3873 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3874 return isl_basic_map_add_dims(bset, type, n);
3875 error:
3876 isl_basic_set_free(bset);
3877 return NULL;
3880 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3881 enum isl_dim_type type)
3883 isl_space *space;
3885 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3886 return map;
3888 space = isl_map_get_space(map);
3889 space = isl_space_reset(space, type);
3890 map = isl_map_reset_space(map, space);
3891 return map;
3894 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3895 enum isl_dim_type type, unsigned pos, unsigned n)
3897 int i;
3899 if (n == 0)
3900 return map_space_reset(map, type);
3902 map = isl_map_cow(map);
3903 if (!map)
3904 return NULL;
3906 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3907 if (!map->dim)
3908 goto error;
3910 for (i = 0; i < map->n; ++i) {
3911 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3912 if (!map->p[i])
3913 goto error;
3916 return map;
3917 error:
3918 isl_map_free(map);
3919 return NULL;
3922 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3923 enum isl_dim_type type, unsigned pos, unsigned n)
3925 return isl_map_insert_dims(set, type, pos, n);
3928 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3929 enum isl_dim_type type, unsigned n)
3931 if (!map)
3932 return NULL;
3933 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3936 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3937 enum isl_dim_type type, unsigned n)
3939 if (!set)
3940 return NULL;
3941 isl_assert(set->ctx, type != isl_dim_in, goto error);
3942 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
3943 error:
3944 isl_set_free(set);
3945 return NULL;
3948 __isl_give isl_basic_map *isl_basic_map_move_dims(
3949 __isl_take isl_basic_map *bmap,
3950 enum isl_dim_type dst_type, unsigned dst_pos,
3951 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3953 struct isl_dim_map *dim_map;
3954 struct isl_basic_map *res;
3955 enum isl_dim_type t;
3956 unsigned total, off;
3958 if (!bmap)
3959 return NULL;
3960 if (n == 0) {
3961 bmap = isl_basic_map_reset(bmap, src_type);
3962 bmap = isl_basic_map_reset(bmap, dst_type);
3963 return bmap;
3966 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
3967 return isl_basic_map_free(bmap);
3969 if (dst_type == src_type && dst_pos == src_pos)
3970 return bmap;
3972 isl_assert(bmap->ctx, dst_type != src_type, goto error);
3974 if (pos(bmap->dim, dst_type) + dst_pos ==
3975 pos(bmap->dim, src_type) + src_pos +
3976 ((src_type < dst_type) ? n : 0)) {
3977 bmap = isl_basic_map_cow(bmap);
3978 if (!bmap)
3979 return NULL;
3981 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3982 src_type, src_pos, n);
3983 if (!bmap->dim)
3984 goto error;
3986 bmap = isl_basic_map_finalize(bmap);
3988 return bmap;
3991 total = isl_basic_map_total_dim(bmap);
3992 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3994 off = 0;
3995 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3996 unsigned size = isl_space_dim(bmap->dim, t);
3997 if (t == dst_type) {
3998 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3999 0, dst_pos, off);
4000 off += dst_pos;
4001 isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
4002 src_pos, n, off);
4003 off += n;
4004 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4005 dst_pos, size - dst_pos, off);
4006 off += size - dst_pos;
4007 } else if (t == src_type) {
4008 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4009 0, src_pos, off);
4010 off += src_pos;
4011 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4012 src_pos + n, size - src_pos - n, off);
4013 off += size - src_pos - n;
4014 } else {
4015 isl_dim_map_dim(dim_map, bmap->dim, t, off);
4016 off += size;
4019 isl_dim_map_div(dim_map, bmap, off);
4021 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4022 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4023 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4024 if (!bmap)
4025 goto error;
4027 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4028 src_type, src_pos, n);
4029 if (!bmap->dim)
4030 goto error;
4032 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4033 bmap = isl_basic_map_gauss(bmap, NULL);
4034 bmap = isl_basic_map_finalize(bmap);
4036 return bmap;
4037 error:
4038 isl_basic_map_free(bmap);
4039 return NULL;
4042 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4043 enum isl_dim_type dst_type, unsigned dst_pos,
4044 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4046 isl_basic_map *bmap = bset_to_bmap(bset);
4047 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4048 src_type, src_pos, n);
4049 return bset_from_bmap(bmap);
4052 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4053 enum isl_dim_type dst_type, unsigned dst_pos,
4054 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4056 if (!set)
4057 return NULL;
4058 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4059 return set_from_map(isl_map_move_dims(set_to_map(set),
4060 dst_type, dst_pos, src_type, src_pos, n));
4061 error:
4062 isl_set_free(set);
4063 return NULL;
4066 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4067 enum isl_dim_type dst_type, unsigned dst_pos,
4068 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4070 int i;
4072 if (n == 0) {
4073 map = isl_map_reset(map, src_type);
4074 map = isl_map_reset(map, dst_type);
4075 return map;
4078 if (isl_map_check_range(map, src_type, src_pos, n))
4079 return isl_map_free(map);
4081 if (dst_type == src_type && dst_pos == src_pos)
4082 return map;
4084 isl_assert(map->ctx, dst_type != src_type, goto error);
4086 map = isl_map_cow(map);
4087 if (!map)
4088 return NULL;
4090 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
4091 if (!map->dim)
4092 goto error;
4094 for (i = 0; i < map->n; ++i) {
4095 map->p[i] = isl_basic_map_move_dims(map->p[i],
4096 dst_type, dst_pos,
4097 src_type, src_pos, n);
4098 if (!map->p[i])
4099 goto error;
4102 return map;
4103 error:
4104 isl_map_free(map);
4105 return NULL;
4108 /* Move the specified dimensions to the last columns right before
4109 * the divs. Don't change the dimension specification of bmap.
4110 * That's the responsibility of the caller.
4112 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4113 enum isl_dim_type type, unsigned first, unsigned n)
4115 struct isl_dim_map *dim_map;
4116 struct isl_basic_map *res;
4117 enum isl_dim_type t;
4118 unsigned total, off;
4120 if (!bmap)
4121 return NULL;
4122 if (pos(bmap->dim, type) + first + n ==
4123 1 + isl_space_dim(bmap->dim, isl_dim_all))
4124 return bmap;
4126 total = isl_basic_map_total_dim(bmap);
4127 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4129 off = 0;
4130 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4131 unsigned size = isl_space_dim(bmap->dim, t);
4132 if (t == type) {
4133 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4134 0, first, off);
4135 off += first;
4136 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4137 first, n, total - bmap->n_div - n);
4138 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4139 first + n, size - (first + n), off);
4140 off += size - (first + n);
4141 } else {
4142 isl_dim_map_dim(dim_map, bmap->dim, t, off);
4143 off += size;
4146 isl_dim_map_div(dim_map, bmap, off + n);
4148 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4149 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4150 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4151 return res;
4154 /* Insert "n" rows in the divs of "bmap".
4156 * The number of columns is not changed, which means that the last
4157 * dimensions of "bmap" are being reintepreted as the new divs.
4158 * The space of "bmap" is not adjusted, however, which means
4159 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4160 * from the space of "bmap" is the responsibility of the caller.
4162 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4163 int n)
4165 int i;
4166 size_t row_size;
4167 isl_int **new_div;
4168 isl_int *old;
4170 bmap = isl_basic_map_cow(bmap);
4171 if (!bmap)
4172 return NULL;
4174 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
4175 old = bmap->block2.data;
4176 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4177 (bmap->extra + n) * (1 + row_size));
4178 if (!bmap->block2.data)
4179 return isl_basic_map_free(bmap);
4180 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4181 if (!new_div)
4182 return isl_basic_map_free(bmap);
4183 for (i = 0; i < n; ++i) {
4184 new_div[i] = bmap->block2.data +
4185 (bmap->extra + i) * (1 + row_size);
4186 isl_seq_clr(new_div[i], 1 + row_size);
4188 for (i = 0; i < bmap->extra; ++i)
4189 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4190 free(bmap->div);
4191 bmap->div = new_div;
4192 bmap->n_div += n;
4193 bmap->extra += n;
4195 return bmap;
4198 /* Drop constraints from "bmap" that only involve the variables
4199 * of "type" in the range [first, first + n] that are not related
4200 * to any of the variables outside that interval.
4201 * These constraints cannot influence the values for the variables
4202 * outside the interval, except in case they cause "bmap" to be empty.
4203 * Only drop the constraints if "bmap" is known to be non-empty.
4205 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4206 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4207 unsigned first, unsigned n)
4209 int i;
4210 int *groups;
4211 unsigned dim, n_div;
4212 isl_bool non_empty;
4214 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4215 if (non_empty < 0)
4216 return isl_basic_map_free(bmap);
4217 if (!non_empty)
4218 return bmap;
4220 dim = isl_basic_map_dim(bmap, isl_dim_all);
4221 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4222 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4223 if (!groups)
4224 return isl_basic_map_free(bmap);
4225 first += isl_basic_map_offset(bmap, type) - 1;
4226 for (i = 0; i < first; ++i)
4227 groups[i] = -1;
4228 for (i = first + n; i < dim - n_div; ++i)
4229 groups[i] = -1;
4231 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4233 return bmap;
4236 /* Turn the n dimensions of type type, starting at first
4237 * into existentially quantified variables.
4239 * If a subset of the projected out variables are unrelated
4240 * to any of the variables that remain, then the constraints
4241 * involving this subset are simply dropped first.
4243 __isl_give isl_basic_map *isl_basic_map_project_out(
4244 __isl_take isl_basic_map *bmap,
4245 enum isl_dim_type type, unsigned first, unsigned n)
4247 isl_bool empty;
4249 if (n == 0)
4250 return basic_map_space_reset(bmap, type);
4251 if (type == isl_dim_div)
4252 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4253 "cannot project out existentially quantified variables",
4254 return isl_basic_map_free(bmap));
4256 empty = isl_basic_map_plain_is_empty(bmap);
4257 if (empty < 0)
4258 return isl_basic_map_free(bmap);
4259 if (empty)
4260 bmap = isl_basic_map_set_to_empty(bmap);
4262 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4263 if (!bmap)
4264 return NULL;
4266 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4267 return isl_basic_map_remove_dims(bmap, type, first, n);
4269 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4270 return isl_basic_map_free(bmap);
4272 bmap = move_last(bmap, type, first, n);
4273 bmap = isl_basic_map_cow(bmap);
4274 bmap = insert_div_rows(bmap, n);
4275 if (!bmap)
4276 return NULL;
4278 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
4279 if (!bmap->dim)
4280 goto error;
4281 bmap = isl_basic_map_simplify(bmap);
4282 bmap = isl_basic_map_drop_redundant_divs(bmap);
4283 return isl_basic_map_finalize(bmap);
4284 error:
4285 isl_basic_map_free(bmap);
4286 return NULL;
4289 /* Turn the n dimensions of type type, starting at first
4290 * into existentially quantified variables.
4292 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
4293 enum isl_dim_type type, unsigned first, unsigned n)
4295 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4296 type, first, n));
4299 /* Turn the n dimensions of type type, starting at first
4300 * into existentially quantified variables.
4302 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4303 enum isl_dim_type type, unsigned first, unsigned n)
4305 int i;
4307 if (n == 0)
4308 return map_space_reset(map, type);
4310 if (isl_map_check_range(map, type, first, n) < 0)
4311 return isl_map_free(map);
4313 map = isl_map_cow(map);
4314 if (!map)
4315 return NULL;
4317 map->dim = isl_space_drop_dims(map->dim, type, first, n);
4318 if (!map->dim)
4319 goto error;
4321 for (i = 0; i < map->n; ++i) {
4322 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4323 if (!map->p[i])
4324 goto error;
4327 return map;
4328 error:
4329 isl_map_free(map);
4330 return NULL;
4333 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4334 * into existentially quantified variables.
4336 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4337 enum isl_dim_type type, unsigned first, unsigned n)
4339 unsigned dim;
4341 if (isl_map_check_range(map, type, first, n) < 0)
4342 return isl_map_free(map);
4343 dim = isl_map_dim(map, type);
4344 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4345 map = isl_map_project_out(map, type, 0, first);
4346 return map;
4349 /* Turn the n dimensions of type type, starting at first
4350 * into existentially quantified variables.
4352 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4353 enum isl_dim_type type, unsigned first, unsigned n)
4355 return set_from_map(isl_map_project_out(set_to_map(set),
4356 type, first, n));
4359 /* Return a map that projects the elements in "set" onto their
4360 * "n" set dimensions starting at "first".
4361 * "type" should be equal to isl_dim_set.
4363 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4364 enum isl_dim_type type, unsigned first, unsigned n)
4366 int i;
4367 int dim;
4368 isl_map *map;
4370 if (!set)
4371 return NULL;
4372 if (type != isl_dim_set)
4373 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4374 "only set dimensions can be projected out", goto error);
4375 dim = isl_set_dim(set, isl_dim_set);
4376 if (first + n > dim || first + n < first)
4377 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4378 "index out of bounds", goto error);
4380 map = isl_map_from_domain(set);
4381 map = isl_map_add_dims(map, isl_dim_out, n);
4382 for (i = 0; i < n; ++i)
4383 map = isl_map_equate(map, isl_dim_in, first + i,
4384 isl_dim_out, i);
4385 return map;
4386 error:
4387 isl_set_free(set);
4388 return NULL;
4391 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4392 unsigned n)
4394 int i, j;
4396 for (i = 0; i < n; ++i) {
4397 j = isl_basic_map_alloc_div(bmap);
4398 if (j < 0)
4399 goto error;
4400 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4402 return bmap;
4403 error:
4404 isl_basic_map_free(bmap);
4405 return NULL;
4408 struct isl_basic_map *isl_basic_map_apply_range(
4409 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4411 isl_space *space_result = NULL;
4412 struct isl_basic_map *bmap;
4413 unsigned n_in, n_out, n, nparam, total, pos;
4414 struct isl_dim_map *dim_map1, *dim_map2;
4416 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4417 goto error;
4418 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4419 bmap2->dim, isl_dim_in))
4420 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4421 "spaces don't match", goto error);
4423 space_result = isl_space_join(isl_space_copy(bmap1->dim),
4424 isl_space_copy(bmap2->dim));
4426 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4427 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4428 n = isl_basic_map_dim(bmap1, isl_dim_out);
4429 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4431 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4432 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4433 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4434 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4435 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4436 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4437 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4438 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4439 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4440 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4441 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4443 bmap = isl_basic_map_alloc_space(space_result,
4444 bmap1->n_div + bmap2->n_div + n,
4445 bmap1->n_eq + bmap2->n_eq,
4446 bmap1->n_ineq + bmap2->n_ineq);
4447 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4448 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4449 bmap = add_divs(bmap, n);
4450 bmap = isl_basic_map_simplify(bmap);
4451 bmap = isl_basic_map_drop_redundant_divs(bmap);
4452 return isl_basic_map_finalize(bmap);
4453 error:
4454 isl_basic_map_free(bmap1);
4455 isl_basic_map_free(bmap2);
4456 return NULL;
4459 struct isl_basic_set *isl_basic_set_apply(
4460 struct isl_basic_set *bset, struct isl_basic_map *bmap)
4462 if (!bset || !bmap)
4463 goto error;
4465 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4466 goto error);
4468 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4469 bmap));
4470 error:
4471 isl_basic_set_free(bset);
4472 isl_basic_map_free(bmap);
4473 return NULL;
4476 struct isl_basic_map *isl_basic_map_apply_domain(
4477 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4479 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4480 goto error;
4481 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4482 bmap2->dim, isl_dim_in))
4483 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4484 "spaces don't match", goto error);
4486 bmap1 = isl_basic_map_reverse(bmap1);
4487 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4488 return isl_basic_map_reverse(bmap1);
4489 error:
4490 isl_basic_map_free(bmap1);
4491 isl_basic_map_free(bmap2);
4492 return NULL;
4495 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4496 * A \cap B -> f(A) + f(B)
4498 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4499 __isl_take isl_basic_map *bmap2)
4501 unsigned n_in, n_out, nparam, total, pos;
4502 struct isl_basic_map *bmap = NULL;
4503 struct isl_dim_map *dim_map1, *dim_map2;
4504 int i;
4506 if (!bmap1 || !bmap2)
4507 goto error;
4509 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4510 goto error);
4512 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4513 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4514 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4516 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4517 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4518 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4519 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4520 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4521 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4522 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4523 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4524 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4525 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4526 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4528 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4529 bmap1->n_div + bmap2->n_div + 2 * n_out,
4530 bmap1->n_eq + bmap2->n_eq + n_out,
4531 bmap1->n_ineq + bmap2->n_ineq);
4532 for (i = 0; i < n_out; ++i) {
4533 int j = isl_basic_map_alloc_equality(bmap);
4534 if (j < 0)
4535 goto error;
4536 isl_seq_clr(bmap->eq[j], 1+total);
4537 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4538 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4539 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4541 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4542 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4543 bmap = add_divs(bmap, 2 * n_out);
4545 bmap = isl_basic_map_simplify(bmap);
4546 return isl_basic_map_finalize(bmap);
4547 error:
4548 isl_basic_map_free(bmap);
4549 isl_basic_map_free(bmap1);
4550 isl_basic_map_free(bmap2);
4551 return NULL;
4554 /* Given two maps A -> f(A) and B -> g(B), construct a map
4555 * A \cap B -> f(A) + f(B)
4557 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4558 __isl_take isl_map *map2)
4560 struct isl_map *result;
4561 int i, j;
4563 if (!map1 || !map2)
4564 goto error;
4566 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4568 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4569 map1->n * map2->n, 0);
4570 if (!result)
4571 goto error;
4572 for (i = 0; i < map1->n; ++i)
4573 for (j = 0; j < map2->n; ++j) {
4574 struct isl_basic_map *part;
4575 part = isl_basic_map_sum(
4576 isl_basic_map_copy(map1->p[i]),
4577 isl_basic_map_copy(map2->p[j]));
4578 if (isl_basic_map_is_empty(part))
4579 isl_basic_map_free(part);
4580 else
4581 result = isl_map_add_basic_map(result, part);
4582 if (!result)
4583 goto error;
4585 isl_map_free(map1);
4586 isl_map_free(map2);
4587 return result;
4588 error:
4589 isl_map_free(map1);
4590 isl_map_free(map2);
4591 return NULL;
4594 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4595 __isl_take isl_set *set2)
4597 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4600 /* Given a basic map A -> f(A), construct A -> -f(A).
4602 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4604 int i, j;
4605 unsigned off, n;
4607 bmap = isl_basic_map_cow(bmap);
4608 if (!bmap)
4609 return NULL;
4611 n = isl_basic_map_dim(bmap, isl_dim_out);
4612 off = isl_basic_map_offset(bmap, isl_dim_out);
4613 for (i = 0; i < bmap->n_eq; ++i)
4614 for (j = 0; j < n; ++j)
4615 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4616 for (i = 0; i < bmap->n_ineq; ++i)
4617 for (j = 0; j < n; ++j)
4618 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4619 for (i = 0; i < bmap->n_div; ++i)
4620 for (j = 0; j < n; ++j)
4621 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4622 bmap = isl_basic_map_gauss(bmap, NULL);
4623 return isl_basic_map_finalize(bmap);
4626 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4628 return isl_basic_map_neg(bset);
4631 /* Given a map A -> f(A), construct A -> -f(A).
4633 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4635 int i;
4637 map = isl_map_cow(map);
4638 if (!map)
4639 return NULL;
4641 for (i = 0; i < map->n; ++i) {
4642 map->p[i] = isl_basic_map_neg(map->p[i]);
4643 if (!map->p[i])
4644 goto error;
4647 return map;
4648 error:
4649 isl_map_free(map);
4650 return NULL;
4653 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4655 return set_from_map(isl_map_neg(set_to_map(set)));
4658 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4659 * A -> floor(f(A)/d).
4661 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4662 isl_int d)
4664 unsigned n_in, n_out, nparam, total, pos;
4665 struct isl_basic_map *result = NULL;
4666 struct isl_dim_map *dim_map;
4667 int i;
4669 if (!bmap)
4670 return NULL;
4672 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4673 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4674 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4676 total = nparam + n_in + n_out + bmap->n_div + n_out;
4677 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4678 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4679 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4680 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4681 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4683 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4684 bmap->n_div + n_out,
4685 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4686 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4687 result = add_divs(result, n_out);
4688 for (i = 0; i < n_out; ++i) {
4689 int j;
4690 j = isl_basic_map_alloc_inequality(result);
4691 if (j < 0)
4692 goto error;
4693 isl_seq_clr(result->ineq[j], 1+total);
4694 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4695 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4696 j = isl_basic_map_alloc_inequality(result);
4697 if (j < 0)
4698 goto error;
4699 isl_seq_clr(result->ineq[j], 1+total);
4700 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4701 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4702 isl_int_sub_ui(result->ineq[j][0], d, 1);
4705 result = isl_basic_map_simplify(result);
4706 return isl_basic_map_finalize(result);
4707 error:
4708 isl_basic_map_free(result);
4709 return NULL;
4712 /* Given a map A -> f(A) and an integer d, construct a map
4713 * A -> floor(f(A)/d).
4715 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4717 int i;
4719 map = isl_map_cow(map);
4720 if (!map)
4721 return NULL;
4723 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4724 for (i = 0; i < map->n; ++i) {
4725 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4726 if (!map->p[i])
4727 goto error;
4729 map = isl_map_unmark_normalized(map);
4731 return map;
4732 error:
4733 isl_map_free(map);
4734 return NULL;
4737 /* Given a map A -> f(A) and an integer d, construct a map
4738 * A -> floor(f(A)/d).
4740 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4741 __isl_take isl_val *d)
4743 if (!map || !d)
4744 goto error;
4745 if (!isl_val_is_int(d))
4746 isl_die(isl_val_get_ctx(d), isl_error_invalid,
4747 "expecting integer denominator", goto error);
4748 map = isl_map_floordiv(map, d->n);
4749 isl_val_free(d);
4750 return map;
4751 error:
4752 isl_map_free(map);
4753 isl_val_free(d);
4754 return NULL;
4757 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
4758 unsigned pos)
4760 int i;
4761 unsigned nparam;
4762 unsigned n_in;
4764 i = isl_basic_map_alloc_equality(bmap);
4765 if (i < 0)
4766 goto error;
4767 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4768 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4769 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4770 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4771 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4772 return isl_basic_map_finalize(bmap);
4773 error:
4774 isl_basic_map_free(bmap);
4775 return NULL;
4778 /* Add a constraint to "bmap" expressing i_pos < o_pos
4780 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
4781 unsigned pos)
4783 int i;
4784 unsigned nparam;
4785 unsigned n_in;
4787 i = isl_basic_map_alloc_inequality(bmap);
4788 if (i < 0)
4789 goto error;
4790 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4791 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4792 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4793 isl_int_set_si(bmap->ineq[i][0], -1);
4794 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4795 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4796 return isl_basic_map_finalize(bmap);
4797 error:
4798 isl_basic_map_free(bmap);
4799 return NULL;
4802 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4804 static __isl_give isl_basic_map *var_less_or_equal(
4805 __isl_take isl_basic_map *bmap, unsigned pos)
4807 int i;
4808 unsigned nparam;
4809 unsigned n_in;
4811 i = isl_basic_map_alloc_inequality(bmap);
4812 if (i < 0)
4813 goto error;
4814 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4815 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4816 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4817 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4818 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4819 return isl_basic_map_finalize(bmap);
4820 error:
4821 isl_basic_map_free(bmap);
4822 return NULL;
4825 /* Add a constraint to "bmap" expressing i_pos > o_pos
4827 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
4828 unsigned pos)
4830 int i;
4831 unsigned nparam;
4832 unsigned n_in;
4834 i = isl_basic_map_alloc_inequality(bmap);
4835 if (i < 0)
4836 goto error;
4837 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4838 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4839 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4840 isl_int_set_si(bmap->ineq[i][0], -1);
4841 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4842 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4843 return isl_basic_map_finalize(bmap);
4844 error:
4845 isl_basic_map_free(bmap);
4846 return NULL;
4849 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4851 static __isl_give isl_basic_map *var_more_or_equal(
4852 __isl_take isl_basic_map *bmap, unsigned pos)
4854 int i;
4855 unsigned nparam;
4856 unsigned n_in;
4858 i = isl_basic_map_alloc_inequality(bmap);
4859 if (i < 0)
4860 goto error;
4861 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4862 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4863 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4864 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4865 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4866 return isl_basic_map_finalize(bmap);
4867 error:
4868 isl_basic_map_free(bmap);
4869 return NULL;
4872 __isl_give isl_basic_map *isl_basic_map_equal(
4873 __isl_take isl_space *space, unsigned n_equal)
4875 int i;
4876 struct isl_basic_map *bmap;
4877 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
4878 if (!bmap)
4879 return NULL;
4880 for (i = 0; i < n_equal && bmap; ++i)
4881 bmap = var_equal(bmap, i);
4882 return isl_basic_map_finalize(bmap);
4885 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
4887 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
4888 unsigned pos)
4890 int i;
4891 struct isl_basic_map *bmap;
4892 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4893 if (!bmap)
4894 return NULL;
4895 for (i = 0; i < pos && bmap; ++i)
4896 bmap = var_equal(bmap, i);
4897 if (bmap)
4898 bmap = var_less(bmap, pos);
4899 return isl_basic_map_finalize(bmap);
4902 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
4904 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4905 __isl_take isl_space *space, unsigned pos)
4907 int i;
4908 isl_basic_map *bmap;
4910 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4911 for (i = 0; i < pos; ++i)
4912 bmap = var_equal(bmap, i);
4913 bmap = var_less_or_equal(bmap, pos);
4914 return isl_basic_map_finalize(bmap);
4917 /* Return a relation on "space" expressing i_pos > o_pos
4919 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
4920 unsigned pos)
4922 int i;
4923 struct isl_basic_map *bmap;
4924 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4925 if (!bmap)
4926 return NULL;
4927 for (i = 0; i < pos && bmap; ++i)
4928 bmap = var_equal(bmap, i);
4929 if (bmap)
4930 bmap = var_more(bmap, pos);
4931 return isl_basic_map_finalize(bmap);
4934 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
4936 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4937 __isl_take isl_space *space, unsigned pos)
4939 int i;
4940 isl_basic_map *bmap;
4942 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4943 for (i = 0; i < pos; ++i)
4944 bmap = var_equal(bmap, i);
4945 bmap = var_more_or_equal(bmap, pos);
4946 return isl_basic_map_finalize(bmap);
4949 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
4950 unsigned n, int equal)
4952 struct isl_map *map;
4953 int i;
4955 if (n == 0 && equal)
4956 return isl_map_universe(space);
4958 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
4960 for (i = 0; i + 1 < n; ++i)
4961 map = isl_map_add_basic_map(map,
4962 isl_basic_map_less_at(isl_space_copy(space), i));
4963 if (n > 0) {
4964 if (equal)
4965 map = isl_map_add_basic_map(map,
4966 isl_basic_map_less_or_equal_at(space, n - 1));
4967 else
4968 map = isl_map_add_basic_map(map,
4969 isl_basic_map_less_at(space, n - 1));
4970 } else
4971 isl_space_free(space);
4973 return map;
4976 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
4978 if (!space)
4979 return NULL;
4980 return map_lex_lte_first(space, space->n_out, equal);
4983 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
4985 return map_lex_lte_first(dim, n, 0);
4988 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
4990 return map_lex_lte_first(dim, n, 1);
4993 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
4995 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
4998 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
5000 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
5003 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5004 unsigned n, int equal)
5006 struct isl_map *map;
5007 int i;
5009 if (n == 0 && equal)
5010 return isl_map_universe(space);
5012 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5014 for (i = 0; i + 1 < n; ++i)
5015 map = isl_map_add_basic_map(map,
5016 isl_basic_map_more_at(isl_space_copy(space), i));
5017 if (n > 0) {
5018 if (equal)
5019 map = isl_map_add_basic_map(map,
5020 isl_basic_map_more_or_equal_at(space, n - 1));
5021 else
5022 map = isl_map_add_basic_map(map,
5023 isl_basic_map_more_at(space, n - 1));
5024 } else
5025 isl_space_free(space);
5027 return map;
5030 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5032 if (!space)
5033 return NULL;
5034 return map_lex_gte_first(space, space->n_out, equal);
5037 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
5039 return map_lex_gte_first(dim, n, 0);
5042 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
5044 return map_lex_gte_first(dim, n, 1);
5047 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
5049 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
5052 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
5054 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
5057 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5058 __isl_take isl_set *set2)
5060 isl_map *map;
5061 map = isl_map_lex_le(isl_set_get_space(set1));
5062 map = isl_map_intersect_domain(map, set1);
5063 map = isl_map_intersect_range(map, set2);
5064 return map;
5067 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5068 __isl_take isl_set *set2)
5070 isl_map *map;
5071 map = isl_map_lex_lt(isl_set_get_space(set1));
5072 map = isl_map_intersect_domain(map, set1);
5073 map = isl_map_intersect_range(map, set2);
5074 return map;
5077 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5078 __isl_take isl_set *set2)
5080 isl_map *map;
5081 map = isl_map_lex_ge(isl_set_get_space(set1));
5082 map = isl_map_intersect_domain(map, set1);
5083 map = isl_map_intersect_range(map, set2);
5084 return map;
5087 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5088 __isl_take isl_set *set2)
5090 isl_map *map;
5091 map = isl_map_lex_gt(isl_set_get_space(set1));
5092 map = isl_map_intersect_domain(map, set1);
5093 map = isl_map_intersect_range(map, set2);
5094 return map;
5097 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5098 __isl_take isl_map *map2)
5100 isl_map *map;
5101 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5102 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5103 map = isl_map_apply_range(map, isl_map_reverse(map2));
5104 return map;
5107 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5108 __isl_take isl_map *map2)
5110 isl_map *map;
5111 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5112 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5113 map = isl_map_apply_range(map, isl_map_reverse(map2));
5114 return map;
5117 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5118 __isl_take isl_map *map2)
5120 isl_map *map;
5121 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5122 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5123 map = isl_map_apply_range(map, isl_map_reverse(map2));
5124 return map;
5127 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5128 __isl_take isl_map *map2)
5130 isl_map *map;
5131 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5132 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5133 map = isl_map_apply_range(map, isl_map_reverse(map2));
5134 return map;
5137 /* For a div d = floor(f/m), add the constraint
5139 * f - m d >= 0
5141 static isl_stat add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
5142 unsigned pos, isl_int *div)
5144 int i;
5145 unsigned total = isl_basic_map_total_dim(bmap);
5147 i = isl_basic_map_alloc_inequality(bmap);
5148 if (i < 0)
5149 return isl_stat_error;
5150 isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
5151 isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
5153 return isl_stat_ok;
5156 /* For a div d = floor(f/m), add the constraint
5158 * -(f-(m-1)) + m d >= 0
5160 static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
5161 unsigned pos, isl_int *div)
5163 int i;
5164 unsigned total = isl_basic_map_total_dim(bmap);
5166 i = isl_basic_map_alloc_inequality(bmap);
5167 if (i < 0)
5168 return isl_stat_error;
5169 isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
5170 isl_int_set(bmap->ineq[i][1 + pos], div[0]);
5171 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5172 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5174 return isl_stat_ok;
5177 /* For a div d = floor(f/m), add the constraints
5179 * f - m d >= 0
5180 * -(f-(m-1)) + m d >= 0
5182 * Note that the second constraint is the negation of
5184 * f - m d >= m
5186 int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
5187 unsigned pos, isl_int *div)
5189 if (add_upper_div_constraint(bmap, pos, div) < 0)
5190 return -1;
5191 if (add_lower_div_constraint(bmap, pos, div) < 0)
5192 return -1;
5193 return 0;
5196 int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
5197 unsigned pos, isl_int *div)
5199 return isl_basic_map_add_div_constraints_var(bset_to_bmap(bset),
5200 pos, div);
5203 int isl_basic_map_add_div_constraints(__isl_keep isl_basic_map *bmap,
5204 unsigned div)
5206 unsigned total = isl_basic_map_total_dim(bmap);
5207 unsigned div_pos = total - bmap->n_div + div;
5209 return isl_basic_map_add_div_constraints_var(bmap, div_pos,
5210 bmap->div[div]);
5213 /* For each known div d = floor(f/m), add the constraints
5215 * f - m d >= 0
5216 * -(f-(m-1)) + m d >= 0
5218 * Remove duplicate constraints in case of some these div constraints
5219 * already appear in "bmap".
5221 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5222 __isl_take isl_basic_map *bmap)
5224 unsigned n_div;
5226 if (!bmap)
5227 return NULL;
5228 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5229 if (n_div == 0)
5230 return bmap;
5232 bmap = add_known_div_constraints(bmap);
5233 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5234 bmap = isl_basic_map_finalize(bmap);
5235 return bmap;
5238 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5240 * In particular, if this div is of the form d = floor(f/m),
5241 * then add the constraint
5243 * f - m d >= 0
5245 * if sign < 0 or the constraint
5247 * -(f-(m-1)) + m d >= 0
5249 * if sign > 0.
5251 int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
5252 unsigned div, int sign)
5254 unsigned total;
5255 unsigned div_pos;
5257 if (!bmap)
5258 return -1;
5260 total = isl_basic_map_total_dim(bmap);
5261 div_pos = total - bmap->n_div + div;
5263 if (sign < 0)
5264 return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
5265 else
5266 return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
5269 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5270 __isl_take isl_basic_map *bmap)
5272 if (!bmap)
5273 goto error;
5274 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5275 bmap->n_div == 0 &&
5276 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5277 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5278 return bset_from_bmap(bmap);
5279 bmap = isl_basic_map_cow(bmap);
5280 if (!bmap)
5281 goto error;
5282 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
5283 if (!bmap->dim)
5284 goto error;
5285 bmap->extra -= bmap->n_div;
5286 bmap->n_div = 0;
5287 bmap = isl_basic_map_finalize(bmap);
5288 return bset_from_bmap(bmap);
5289 error:
5290 isl_basic_map_free(bmap);
5291 return NULL;
5294 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5295 __isl_take isl_basic_set *bset)
5297 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5300 /* Replace each element in "list" by the result of applying
5301 * isl_basic_map_underlying_set to the element.
5303 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5304 __isl_take isl_basic_map_list *list)
5306 int i, n;
5308 if (!list)
5309 return NULL;
5311 n = isl_basic_map_list_n_basic_map(list);
5312 for (i = 0; i < n; ++i) {
5313 isl_basic_map *bmap;
5314 isl_basic_set *bset;
5316 bmap = isl_basic_map_list_get_basic_map(list, i);
5317 bset = isl_basic_set_underlying_set(bmap);
5318 list = isl_basic_set_list_set_basic_set(list, i, bset);
5321 return list;
5324 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5325 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5327 struct isl_basic_map *bmap;
5328 struct isl_ctx *ctx;
5329 unsigned total;
5330 int i;
5332 if (!bset || !like)
5333 goto error;
5334 ctx = bset->ctx;
5335 isl_assert(ctx, bset->n_div == 0, goto error);
5336 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
5337 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
5338 goto error);
5339 if (like->n_div == 0) {
5340 isl_space *space = isl_basic_map_get_space(like);
5341 isl_basic_map_free(like);
5342 return isl_basic_map_reset_space(bset, space);
5344 bset = isl_basic_set_cow(bset);
5345 if (!bset)
5346 goto error;
5347 total = bset->dim->n_out + bset->extra;
5348 bmap = bset_to_bmap(bset);
5349 isl_space_free(bmap->dim);
5350 bmap->dim = isl_space_copy(like->dim);
5351 if (!bmap->dim)
5352 goto error;
5353 bmap->n_div = like->n_div;
5354 bmap->extra += like->n_div;
5355 if (bmap->extra) {
5356 unsigned ltotal;
5357 isl_int **div;
5358 ltotal = total - bmap->extra + like->extra;
5359 if (ltotal > total)
5360 ltotal = total;
5361 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5362 bmap->extra * (1 + 1 + total));
5363 if (isl_blk_is_error(bmap->block2))
5364 goto error;
5365 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5366 if (!div)
5367 goto error;
5368 bmap->div = div;
5369 for (i = 0; i < bmap->extra; ++i)
5370 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5371 for (i = 0; i < like->n_div; ++i) {
5372 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5373 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5375 bmap = isl_basic_map_add_known_div_constraints(bmap);
5377 isl_basic_map_free(like);
5378 bmap = isl_basic_map_simplify(bmap);
5379 bmap = isl_basic_map_finalize(bmap);
5380 return bmap;
5381 error:
5382 isl_basic_map_free(like);
5383 isl_basic_set_free(bset);
5384 return NULL;
5387 struct isl_basic_set *isl_basic_set_from_underlying_set(
5388 struct isl_basic_set *bset, struct isl_basic_set *like)
5390 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5391 bset_to_bmap(like)));
5394 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5396 int i;
5398 map = isl_map_cow(map);
5399 if (!map)
5400 return NULL;
5401 map->dim = isl_space_cow(map->dim);
5402 if (!map->dim)
5403 goto error;
5405 for (i = 1; i < map->n; ++i)
5406 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5407 goto error);
5408 for (i = 0; i < map->n; ++i) {
5409 map->p[i] = bset_to_bmap(
5410 isl_basic_map_underlying_set(map->p[i]));
5411 if (!map->p[i])
5412 goto error;
5414 if (map->n == 0)
5415 map->dim = isl_space_underlying(map->dim, 0);
5416 else {
5417 isl_space_free(map->dim);
5418 map->dim = isl_space_copy(map->p[0]->dim);
5420 if (!map->dim)
5421 goto error;
5422 return set_from_map(map);
5423 error:
5424 isl_map_free(map);
5425 return NULL;
5428 /* Replace the space of "bmap" by "space".
5430 * If the space of "bmap" is identical to "space" (including the identifiers
5431 * of the input and output dimensions), then simply return the original input.
5433 __isl_give isl_basic_map *isl_basic_map_reset_space(
5434 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5436 isl_bool equal;
5437 isl_space *bmap_space;
5439 bmap_space = isl_basic_map_peek_space(bmap);
5440 equal = isl_space_is_equal(bmap_space, space);
5441 if (equal >= 0 && equal)
5442 equal = isl_space_has_equal_ids(bmap_space, space);
5443 if (equal < 0)
5444 goto error;
5445 if (equal) {
5446 isl_space_free(space);
5447 return bmap;
5449 bmap = isl_basic_map_cow(bmap);
5450 if (!bmap || !space)
5451 goto error;
5453 isl_space_free(bmap->dim);
5454 bmap->dim = space;
5456 bmap = isl_basic_map_finalize(bmap);
5458 return bmap;
5459 error:
5460 isl_basic_map_free(bmap);
5461 isl_space_free(space);
5462 return NULL;
5465 __isl_give isl_basic_set *isl_basic_set_reset_space(
5466 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5468 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5469 dim));
5472 /* Check that the total dimensions of "map" and "space" are the same.
5474 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5475 __isl_keep isl_space *space)
5477 unsigned dim1, dim2;
5479 if (!map || !space)
5480 return isl_stat_error;
5481 dim1 = isl_map_dim(map, isl_dim_all);
5482 dim2 = isl_space_dim(space, isl_dim_all);
5483 if (dim1 == dim2)
5484 return isl_stat_ok;
5485 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5486 "total dimensions do not match", return isl_stat_error);
5489 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5490 __isl_take isl_space *space)
5492 int i;
5494 map = isl_map_cow(map);
5495 if (!map || !space)
5496 goto error;
5498 for (i = 0; i < map->n; ++i) {
5499 map->p[i] = isl_basic_map_reset_space(map->p[i],
5500 isl_space_copy(space));
5501 if (!map->p[i])
5502 goto error;
5504 isl_space_free(map->dim);
5505 map->dim = space;
5507 return map;
5508 error:
5509 isl_map_free(map);
5510 isl_space_free(space);
5511 return NULL;
5514 /* Replace the space of "map" by "space", without modifying
5515 * the dimension of "map".
5517 * If the space of "map" is identical to "space" (including the identifiers
5518 * of the input and output dimensions), then simply return the original input.
5520 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5521 __isl_take isl_space *space)
5523 isl_bool equal;
5524 isl_space *map_space;
5526 map_space = isl_map_peek_space(map);
5527 equal = isl_space_is_equal(map_space, space);
5528 if (equal >= 0 && equal)
5529 equal = isl_space_has_equal_ids(map_space, space);
5530 if (equal < 0)
5531 goto error;
5532 if (equal) {
5533 isl_space_free(space);
5534 return map;
5536 if (check_map_space_equal_total_dim(map, space) < 0)
5537 goto error;
5538 return isl_map_reset_space(map, space);
5539 error:
5540 isl_map_free(map);
5541 isl_space_free(space);
5542 return NULL;
5545 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5546 __isl_take isl_space *dim)
5548 return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5551 /* Compute the parameter domain of the given basic set.
5553 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5555 isl_bool is_params;
5556 isl_space *space;
5557 unsigned n;
5559 is_params = isl_basic_set_is_params(bset);
5560 if (is_params < 0)
5561 return isl_basic_set_free(bset);
5562 if (is_params)
5563 return bset;
5565 n = isl_basic_set_dim(bset, isl_dim_set);
5566 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5567 space = isl_basic_set_get_space(bset);
5568 space = isl_space_params(space);
5569 bset = isl_basic_set_reset_space(bset, space);
5570 return bset;
5573 /* Construct a zero-dimensional basic set with the given parameter domain.
5575 __isl_give isl_basic_set *isl_basic_set_from_params(
5576 __isl_take isl_basic_set *bset)
5578 isl_space *space;
5579 space = isl_basic_set_get_space(bset);
5580 space = isl_space_set_from_params(space);
5581 bset = isl_basic_set_reset_space(bset, space);
5582 return bset;
5585 /* Compute the parameter domain of the given set.
5587 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5589 isl_space *space;
5590 unsigned n;
5592 if (isl_set_is_params(set))
5593 return set;
5595 n = isl_set_dim(set, isl_dim_set);
5596 set = isl_set_project_out(set, isl_dim_set, 0, n);
5597 space = isl_set_get_space(set);
5598 space = isl_space_params(space);
5599 set = isl_set_reset_space(set, space);
5600 return set;
5603 /* Construct a zero-dimensional set with the given parameter domain.
5605 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5607 isl_space *space;
5608 space = isl_set_get_space(set);
5609 space = isl_space_set_from_params(space);
5610 set = isl_set_reset_space(set, space);
5611 return set;
5614 /* Compute the parameter domain of the given map.
5616 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5618 isl_space *space;
5619 unsigned n;
5621 n = isl_map_dim(map, isl_dim_in);
5622 map = isl_map_project_out(map, isl_dim_in, 0, n);
5623 n = isl_map_dim(map, isl_dim_out);
5624 map = isl_map_project_out(map, isl_dim_out, 0, n);
5625 space = isl_map_get_space(map);
5626 space = isl_space_params(space);
5627 map = isl_map_reset_space(map, space);
5628 return map;
5631 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5633 isl_space *space;
5634 unsigned n_out;
5636 if (!bmap)
5637 return NULL;
5638 space = isl_space_domain(isl_basic_map_get_space(bmap));
5640 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5641 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5643 return isl_basic_map_reset_space(bmap, space);
5646 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5648 if (!bmap)
5649 return isl_bool_error;
5650 return isl_space_may_be_set(bmap->dim);
5653 /* Is this basic map actually a set?
5654 * Users should never call this function. Outside of isl,
5655 * the type should indicate whether something is a set or a map.
5657 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5659 if (!bmap)
5660 return isl_bool_error;
5661 return isl_space_is_set(bmap->dim);
5664 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5666 isl_bool is_set;
5668 is_set = isl_basic_map_is_set(bmap);
5669 if (is_set < 0)
5670 goto error;
5671 if (is_set)
5672 return bmap;
5673 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5674 error:
5675 isl_basic_map_free(bmap);
5676 return NULL;
5679 __isl_give isl_basic_map *isl_basic_map_domain_map(
5680 __isl_take isl_basic_map *bmap)
5682 int i;
5683 isl_space *space;
5684 isl_basic_map *domain;
5685 int nparam, n_in, n_out;
5687 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5688 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5689 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5691 space = isl_basic_map_get_space(bmap);
5692 space = isl_space_from_range(isl_space_domain(space));
5693 domain = isl_basic_map_universe(space);
5695 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5696 bmap = isl_basic_map_apply_range(bmap, domain);
5697 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5699 for (i = 0; i < n_in; ++i)
5700 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5701 isl_dim_out, i);
5703 bmap = isl_basic_map_gauss(bmap, NULL);
5704 return isl_basic_map_finalize(bmap);
5707 __isl_give isl_basic_map *isl_basic_map_range_map(
5708 __isl_take isl_basic_map *bmap)
5710 int i;
5711 isl_space *space;
5712 isl_basic_map *range;
5713 int nparam, n_in, n_out;
5715 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5716 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5717 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5719 space = isl_basic_map_get_space(bmap);
5720 space = isl_space_from_range(isl_space_range(space));
5721 range = isl_basic_map_universe(space);
5723 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5724 bmap = isl_basic_map_apply_range(bmap, range);
5725 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5727 for (i = 0; i < n_out; ++i)
5728 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5729 isl_dim_out, i);
5731 bmap = isl_basic_map_gauss(bmap, NULL);
5732 return isl_basic_map_finalize(bmap);
5735 int isl_map_may_be_set(__isl_keep isl_map *map)
5737 if (!map)
5738 return -1;
5739 return isl_space_may_be_set(map->dim);
5742 /* Is this map actually a set?
5743 * Users should never call this function. Outside of isl,
5744 * the type should indicate whether something is a set or a map.
5746 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5748 if (!map)
5749 return isl_bool_error;
5750 return isl_space_is_set(map->dim);
5753 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
5755 int i;
5756 isl_bool is_set;
5757 struct isl_set *set;
5759 is_set = isl_map_is_set(map);
5760 if (is_set < 0)
5761 goto error;
5762 if (is_set)
5763 return set_from_map(map);
5765 map = isl_map_cow(map);
5766 if (!map)
5767 goto error;
5769 set = set_from_map(map);
5770 set->dim = isl_space_range(set->dim);
5771 if (!set->dim)
5772 goto error;
5773 for (i = 0; i < map->n; ++i) {
5774 set->p[i] = isl_basic_map_range(map->p[i]);
5775 if (!set->p[i])
5776 goto error;
5778 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5779 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5780 return set;
5781 error:
5782 isl_map_free(map);
5783 return NULL;
5786 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5788 int i;
5790 map = isl_map_cow(map);
5791 if (!map)
5792 return NULL;
5794 map->dim = isl_space_domain_map(map->dim);
5795 if (!map->dim)
5796 goto error;
5797 for (i = 0; i < map->n; ++i) {
5798 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5799 if (!map->p[i])
5800 goto error;
5802 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5803 map = isl_map_unmark_normalized(map);
5804 return map;
5805 error:
5806 isl_map_free(map);
5807 return NULL;
5810 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5812 int i;
5813 isl_space *range_dim;
5815 map = isl_map_cow(map);
5816 if (!map)
5817 return NULL;
5819 range_dim = isl_space_range(isl_map_get_space(map));
5820 range_dim = isl_space_from_range(range_dim);
5821 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5822 map->dim = isl_space_join(map->dim, range_dim);
5823 if (!map->dim)
5824 goto error;
5825 for (i = 0; i < map->n; ++i) {
5826 map->p[i] = isl_basic_map_range_map(map->p[i]);
5827 if (!map->p[i])
5828 goto error;
5830 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5831 map = isl_map_unmark_normalized(map);
5832 return map;
5833 error:
5834 isl_map_free(map);
5835 return NULL;
5838 /* Given a wrapped map of the form A[B -> C],
5839 * return the map A[B -> C] -> B.
5841 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5843 isl_id *id;
5844 isl_map *map;
5846 if (!set)
5847 return NULL;
5848 if (!isl_set_has_tuple_id(set))
5849 return isl_map_domain_map(isl_set_unwrap(set));
5851 id = isl_set_get_tuple_id(set);
5852 map = isl_map_domain_map(isl_set_unwrap(set));
5853 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5855 return map;
5858 __isl_give isl_basic_map *isl_basic_map_from_domain(
5859 __isl_take isl_basic_set *bset)
5861 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5864 __isl_give isl_basic_map *isl_basic_map_from_range(
5865 __isl_take isl_basic_set *bset)
5867 isl_space *space;
5868 space = isl_basic_set_get_space(bset);
5869 space = isl_space_from_range(space);
5870 bset = isl_basic_set_reset_space(bset, space);
5871 return bset_to_bmap(bset);
5874 /* Create a relation with the given set as range.
5875 * The domain of the created relation is a zero-dimensional
5876 * flat anonymous space.
5878 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5880 isl_space *space;
5881 space = isl_set_get_space(set);
5882 space = isl_space_from_range(space);
5883 set = isl_set_reset_space(set, space);
5884 return set_to_map(set);
5887 /* Create a relation with the given set as domain.
5888 * The range of the created relation is a zero-dimensional
5889 * flat anonymous space.
5891 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5893 return isl_map_reverse(isl_map_from_range(set));
5896 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5897 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5899 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5902 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5903 __isl_take isl_set *range)
5905 return isl_map_apply_range(isl_map_reverse(domain), range);
5908 /* Return a newly allocated isl_map with given space and flags and
5909 * room for "n" basic maps.
5910 * Make sure that all cached information is cleared.
5912 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5913 unsigned flags)
5915 struct isl_map *map;
5917 if (!space)
5918 return NULL;
5919 if (n < 0)
5920 isl_die(space->ctx, isl_error_internal,
5921 "negative number of basic maps", goto error);
5922 map = isl_calloc(space->ctx, struct isl_map,
5923 sizeof(struct isl_map) +
5924 (n - 1) * sizeof(struct isl_basic_map *));
5925 if (!map)
5926 goto error;
5928 map->ctx = space->ctx;
5929 isl_ctx_ref(map->ctx);
5930 map->ref = 1;
5931 map->size = n;
5932 map->n = 0;
5933 map->dim = space;
5934 map->flags = flags;
5935 return map;
5936 error:
5937 isl_space_free(space);
5938 return NULL;
5941 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
5943 struct isl_basic_map *bmap;
5944 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
5945 bmap = isl_basic_map_set_to_empty(bmap);
5946 return bmap;
5949 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
5951 struct isl_basic_set *bset;
5952 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
5953 bset = isl_basic_set_set_to_empty(bset);
5954 return bset;
5957 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
5959 struct isl_basic_map *bmap;
5960 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
5961 bmap = isl_basic_map_finalize(bmap);
5962 return bmap;
5965 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
5967 struct isl_basic_set *bset;
5968 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
5969 bset = isl_basic_set_finalize(bset);
5970 return bset;
5973 __isl_give isl_basic_map *isl_basic_map_nat_universe(
5974 __isl_take isl_space *space)
5976 int i;
5977 unsigned total = isl_space_dim(space, isl_dim_all);
5978 isl_basic_map *bmap;
5980 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
5981 for (i = 0; i < total; ++i) {
5982 int k = isl_basic_map_alloc_inequality(bmap);
5983 if (k < 0)
5984 goto error;
5985 isl_seq_clr(bmap->ineq[k], 1 + total);
5986 isl_int_set_si(bmap->ineq[k][1 + i], 1);
5988 return bmap;
5989 error:
5990 isl_basic_map_free(bmap);
5991 return NULL;
5994 __isl_give isl_basic_set *isl_basic_set_nat_universe(
5995 __isl_take isl_space *space)
5997 return isl_basic_map_nat_universe(space);
6000 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
6002 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
6005 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
6007 return isl_map_nat_universe(dim);
6010 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6012 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6015 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6017 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6020 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6022 struct isl_map *map;
6023 if (!space)
6024 return NULL;
6025 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6026 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6027 return map;
6030 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6032 struct isl_set *set;
6033 if (!space)
6034 return NULL;
6035 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6036 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6037 return set;
6040 struct isl_map *isl_map_dup(struct isl_map *map)
6042 int i;
6043 struct isl_map *dup;
6045 if (!map)
6046 return NULL;
6047 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6048 for (i = 0; i < map->n; ++i)
6049 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6050 return dup;
6053 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6054 __isl_take isl_basic_map *bmap)
6056 if (!bmap || !map)
6057 goto error;
6058 if (isl_basic_map_plain_is_empty(bmap)) {
6059 isl_basic_map_free(bmap);
6060 return map;
6062 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
6063 isl_assert(map->ctx, map->n < map->size, goto error);
6064 map->p[map->n] = bmap;
6065 map->n++;
6066 map = isl_map_unmark_normalized(map);
6067 return map;
6068 error:
6069 if (map)
6070 isl_map_free(map);
6071 if (bmap)
6072 isl_basic_map_free(bmap);
6073 return NULL;
6076 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6078 int i;
6080 if (!map)
6081 return NULL;
6083 if (--map->ref > 0)
6084 return NULL;
6086 clear_caches(map);
6087 isl_ctx_deref(map->ctx);
6088 for (i = 0; i < map->n; ++i)
6089 isl_basic_map_free(map->p[i]);
6090 isl_space_free(map->dim);
6091 free(map);
6093 return NULL;
6096 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6097 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6099 int j;
6101 bmap = isl_basic_map_cow(bmap);
6102 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6103 j = isl_basic_map_alloc_equality(bmap);
6104 if (j < 0)
6105 goto error;
6106 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6107 isl_int_set_si(bmap->eq[j][pos], -1);
6108 isl_int_set_si(bmap->eq[j][0], value);
6109 bmap = isl_basic_map_simplify(bmap);
6110 return isl_basic_map_finalize(bmap);
6111 error:
6112 isl_basic_map_free(bmap);
6113 return NULL;
6116 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6117 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6119 int j;
6121 bmap = isl_basic_map_cow(bmap);
6122 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6123 j = isl_basic_map_alloc_equality(bmap);
6124 if (j < 0)
6125 goto error;
6126 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6127 isl_int_set_si(bmap->eq[j][pos], -1);
6128 isl_int_set(bmap->eq[j][0], value);
6129 bmap = isl_basic_map_simplify(bmap);
6130 return isl_basic_map_finalize(bmap);
6131 error:
6132 isl_basic_map_free(bmap);
6133 return NULL;
6136 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6137 enum isl_dim_type type, unsigned pos, int value)
6139 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6140 return isl_basic_map_free(bmap);
6141 return isl_basic_map_fix_pos_si(bmap,
6142 isl_basic_map_offset(bmap, type) + pos, value);
6145 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6146 enum isl_dim_type type, unsigned pos, isl_int value)
6148 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6149 return isl_basic_map_free(bmap);
6150 return isl_basic_map_fix_pos(bmap,
6151 isl_basic_map_offset(bmap, type) + pos, value);
6154 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6155 * to be equal to "v".
6157 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6158 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6160 if (!bmap || !v)
6161 goto error;
6162 if (!isl_val_is_int(v))
6163 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6164 "expecting integer value", goto error);
6165 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6166 goto error;
6167 pos += isl_basic_map_offset(bmap, type);
6168 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6169 isl_val_free(v);
6170 return bmap;
6171 error:
6172 isl_basic_map_free(bmap);
6173 isl_val_free(v);
6174 return NULL;
6177 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6178 * to be equal to "v".
6180 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6181 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6183 return isl_basic_map_fix_val(bset, type, pos, v);
6186 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
6187 enum isl_dim_type type, unsigned pos, int value)
6189 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6190 type, pos, value));
6193 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6194 enum isl_dim_type type, unsigned pos, isl_int value)
6196 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6197 type, pos, value));
6200 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
6201 unsigned input, int value)
6203 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
6206 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
6207 unsigned dim, int value)
6209 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6210 isl_dim_set, dim, value));
6213 /* Remove the basic map at position "i" from "map" if this basic map
6214 * is (obviously) empty.
6216 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6218 isl_bool empty;
6220 if (!map)
6221 return NULL;
6223 empty = isl_basic_map_plain_is_empty(map->p[i]);
6224 if (empty < 0)
6225 return isl_map_free(map);
6226 if (!empty)
6227 return map;
6229 isl_basic_map_free(map->p[i]);
6230 map->n--;
6231 if (i != map->n) {
6232 map->p[i] = map->p[map->n];
6233 map = isl_map_unmark_normalized(map);
6237 return map;
6240 /* Perform "fn" on each basic map of "map", where we may not be holding
6241 * the only reference to "map".
6242 * In particular, "fn" should be a semantics preserving operation
6243 * that we want to apply to all copies of "map". We therefore need
6244 * to be careful not to modify "map" in a way that breaks "map"
6245 * in case anything goes wrong.
6247 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6248 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6250 struct isl_basic_map *bmap;
6251 int i;
6253 if (!map)
6254 return NULL;
6256 for (i = map->n - 1; i >= 0; --i) {
6257 bmap = isl_basic_map_copy(map->p[i]);
6258 bmap = fn(bmap);
6259 if (!bmap)
6260 goto error;
6261 isl_basic_map_free(map->p[i]);
6262 map->p[i] = bmap;
6263 map = remove_if_empty(map, i);
6264 if (!map)
6265 return NULL;
6268 return map;
6269 error:
6270 isl_map_free(map);
6271 return NULL;
6274 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6275 enum isl_dim_type type, unsigned pos, int value)
6277 int i;
6279 map = isl_map_cow(map);
6280 if (isl_map_check_range(map, type, pos, 1) < 0)
6281 return isl_map_free(map);
6282 for (i = map->n - 1; i >= 0; --i) {
6283 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6284 map = remove_if_empty(map, i);
6285 if (!map)
6286 return NULL;
6288 map = isl_map_unmark_normalized(map);
6289 return map;
6292 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6293 enum isl_dim_type type, unsigned pos, int value)
6295 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6298 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6299 enum isl_dim_type type, unsigned pos, isl_int value)
6301 int i;
6303 map = isl_map_cow(map);
6304 if (isl_map_check_range(map, type, pos, 1) < 0)
6305 return isl_map_free(map);
6306 for (i = 0; i < map->n; ++i) {
6307 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6308 if (!map->p[i])
6309 goto error;
6311 map = isl_map_unmark_normalized(map);
6312 return map;
6313 error:
6314 isl_map_free(map);
6315 return NULL;
6318 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6319 enum isl_dim_type type, unsigned pos, isl_int value)
6321 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6324 /* Fix the value of the variable at position "pos" of type "type" of "map"
6325 * to be equal to "v".
6327 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6328 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6330 int i;
6332 map = isl_map_cow(map);
6333 if (!map || !v)
6334 goto error;
6336 if (!isl_val_is_int(v))
6337 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6338 "expecting integer value", goto error);
6339 if (isl_map_check_range(map, type, pos, 1) < 0)
6340 goto error;
6341 for (i = map->n - 1; i >= 0; --i) {
6342 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6343 isl_val_copy(v));
6344 map = remove_if_empty(map, i);
6345 if (!map)
6346 goto error;
6348 map = isl_map_unmark_normalized(map);
6349 isl_val_free(v);
6350 return map;
6351 error:
6352 isl_map_free(map);
6353 isl_val_free(v);
6354 return NULL;
6357 /* Fix the value of the variable at position "pos" of type "type" of "set"
6358 * to be equal to "v".
6360 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6361 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6363 return isl_map_fix_val(set, type, pos, v);
6366 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
6367 unsigned input, int value)
6369 return isl_map_fix_si(map, isl_dim_in, input, value);
6372 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
6374 return set_from_map(isl_map_fix_si(set_to_map(set),
6375 isl_dim_set, dim, value));
6378 static __isl_give isl_basic_map *basic_map_bound_si(
6379 __isl_take isl_basic_map *bmap,
6380 enum isl_dim_type type, unsigned pos, int value, int upper)
6382 int j;
6384 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6385 return isl_basic_map_free(bmap);
6386 pos += isl_basic_map_offset(bmap, type);
6387 bmap = isl_basic_map_cow(bmap);
6388 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6389 j = isl_basic_map_alloc_inequality(bmap);
6390 if (j < 0)
6391 goto error;
6392 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6393 if (upper) {
6394 isl_int_set_si(bmap->ineq[j][pos], -1);
6395 isl_int_set_si(bmap->ineq[j][0], value);
6396 } else {
6397 isl_int_set_si(bmap->ineq[j][pos], 1);
6398 isl_int_set_si(bmap->ineq[j][0], -value);
6400 bmap = isl_basic_map_simplify(bmap);
6401 return isl_basic_map_finalize(bmap);
6402 error:
6403 isl_basic_map_free(bmap);
6404 return NULL;
6407 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6408 __isl_take isl_basic_map *bmap,
6409 enum isl_dim_type type, unsigned pos, int value)
6411 return basic_map_bound_si(bmap, type, pos, value, 0);
6414 /* Constrain the values of the given dimension to be no greater than "value".
6416 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6417 __isl_take isl_basic_map *bmap,
6418 enum isl_dim_type type, unsigned pos, int value)
6420 return basic_map_bound_si(bmap, type, pos, value, 1);
6423 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6424 enum isl_dim_type type, unsigned pos, int value, int upper)
6426 int i;
6428 map = isl_map_cow(map);
6429 if (isl_map_check_range(map, type, pos, 1) < 0)
6430 return isl_map_free(map);
6431 for (i = 0; i < map->n; ++i) {
6432 map->p[i] = basic_map_bound_si(map->p[i],
6433 type, pos, value, upper);
6434 if (!map->p[i])
6435 goto error;
6437 map = isl_map_unmark_normalized(map);
6438 return map;
6439 error:
6440 isl_map_free(map);
6441 return NULL;
6444 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6445 enum isl_dim_type type, unsigned pos, int value)
6447 return map_bound_si(map, type, pos, value, 0);
6450 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6451 enum isl_dim_type type, unsigned pos, int value)
6453 return map_bound_si(map, type, pos, value, 1);
6456 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6457 enum isl_dim_type type, unsigned pos, int value)
6459 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6460 type, pos, value));
6463 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6464 enum isl_dim_type type, unsigned pos, int value)
6466 return isl_map_upper_bound_si(set, type, pos, value);
6469 /* Bound the given variable of "bmap" from below (or above is "upper"
6470 * is set) to "value".
6472 static __isl_give isl_basic_map *basic_map_bound(
6473 __isl_take isl_basic_map *bmap,
6474 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6476 int j;
6478 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6479 return isl_basic_map_free(bmap);
6480 pos += isl_basic_map_offset(bmap, type);
6481 bmap = isl_basic_map_cow(bmap);
6482 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6483 j = isl_basic_map_alloc_inequality(bmap);
6484 if (j < 0)
6485 goto error;
6486 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6487 if (upper) {
6488 isl_int_set_si(bmap->ineq[j][pos], -1);
6489 isl_int_set(bmap->ineq[j][0], value);
6490 } else {
6491 isl_int_set_si(bmap->ineq[j][pos], 1);
6492 isl_int_neg(bmap->ineq[j][0], value);
6494 bmap = isl_basic_map_simplify(bmap);
6495 return isl_basic_map_finalize(bmap);
6496 error:
6497 isl_basic_map_free(bmap);
6498 return NULL;
6501 /* Bound the given variable of "map" from below (or above is "upper"
6502 * is set) to "value".
6504 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6505 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6507 int i;
6509 map = isl_map_cow(map);
6510 if (isl_map_check_range(map, type, pos, 1) < 0)
6511 return isl_map_free(map);
6512 for (i = map->n - 1; i >= 0; --i) {
6513 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6514 map = remove_if_empty(map, i);
6515 if (!map)
6516 return NULL;
6518 map = isl_map_unmark_normalized(map);
6519 return map;
6522 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6523 enum isl_dim_type type, unsigned pos, isl_int value)
6525 return map_bound(map, type, pos, value, 0);
6528 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6529 enum isl_dim_type type, unsigned pos, isl_int value)
6531 return map_bound(map, type, pos, value, 1);
6534 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6535 enum isl_dim_type type, unsigned pos, isl_int value)
6537 return isl_map_lower_bound(set, type, pos, value);
6540 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6541 enum isl_dim_type type, unsigned pos, isl_int value)
6543 return isl_map_upper_bound(set, type, pos, value);
6546 /* Force the values of the variable at position "pos" of type "type" of "set"
6547 * to be no smaller than "value".
6549 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6550 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6552 if (!value)
6553 goto error;
6554 if (!isl_val_is_int(value))
6555 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6556 "expecting integer value", goto error);
6557 set = isl_set_lower_bound(set, type, pos, value->n);
6558 isl_val_free(value);
6559 return set;
6560 error:
6561 isl_val_free(value);
6562 isl_set_free(set);
6563 return NULL;
6566 /* Force the values of the variable at position "pos" of type "type" of "set"
6567 * to be no greater than "value".
6569 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6570 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6572 if (!value)
6573 goto error;
6574 if (!isl_val_is_int(value))
6575 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6576 "expecting integer value", goto error);
6577 set = isl_set_upper_bound(set, type, pos, value->n);
6578 isl_val_free(value);
6579 return set;
6580 error:
6581 isl_val_free(value);
6582 isl_set_free(set);
6583 return NULL;
6586 /* Bound the given variable of "bset" from below (or above is "upper"
6587 * is set) to "value".
6589 static __isl_give isl_basic_set *isl_basic_set_bound(
6590 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6591 isl_int value, int upper)
6593 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
6594 type, pos, value, upper));
6597 /* Bound the given variable of "bset" from below (or above is "upper"
6598 * is set) to "value".
6600 static __isl_give isl_basic_set *isl_basic_set_bound_val(
6601 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6602 __isl_take isl_val *value, int upper)
6604 if (!value)
6605 goto error;
6606 if (!isl_val_is_int(value))
6607 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
6608 "expecting integer value", goto error);
6609 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
6610 isl_val_free(value);
6611 return bset;
6612 error:
6613 isl_val_free(value);
6614 isl_basic_set_free(bset);
6615 return NULL;
6618 /* Bound the given variable of "bset" from below to "value".
6620 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
6621 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6622 __isl_take isl_val *value)
6624 return isl_basic_set_bound_val(bset, type, pos, value, 0);
6627 /* Bound the given variable of "bset" from above to "value".
6629 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
6630 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6631 __isl_take isl_val *value)
6633 return isl_basic_set_bound_val(bset, type, pos, value, 1);
6636 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
6638 int i;
6640 map = isl_map_cow(map);
6641 if (!map)
6642 return NULL;
6644 map->dim = isl_space_reverse(map->dim);
6645 if (!map->dim)
6646 goto error;
6647 for (i = 0; i < map->n; ++i) {
6648 map->p[i] = isl_basic_map_reverse(map->p[i]);
6649 if (!map->p[i])
6650 goto error;
6652 map = isl_map_unmark_normalized(map);
6653 return map;
6654 error:
6655 isl_map_free(map);
6656 return NULL;
6659 #undef TYPE
6660 #define TYPE isl_pw_multi_aff
6661 #undef SUFFIX
6662 #define SUFFIX _pw_multi_aff
6663 #undef EMPTY
6664 #define EMPTY isl_pw_multi_aff_empty
6665 #undef ADD
6666 #define ADD isl_pw_multi_aff_union_add
6667 #include "isl_map_lexopt_templ.c"
6669 /* Given a map "map", compute the lexicographically minimal
6670 * (or maximal) image element for each domain element in dom,
6671 * in the form of an isl_pw_multi_aff.
6672 * If "empty" is not NULL, then set *empty to those elements in dom that
6673 * do not have an image element.
6674 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6675 * should be computed over the domain of "map". "empty" is also NULL
6676 * in this case.
6678 * We first compute the lexicographically minimal or maximal element
6679 * in the first basic map. This results in a partial solution "res"
6680 * and a subset "todo" of dom that still need to be handled.
6681 * We then consider each of the remaining maps in "map" and successively
6682 * update both "res" and "todo".
6683 * If "empty" is NULL, then the todo sets are not needed and therefore
6684 * also not computed.
6686 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6687 __isl_take isl_map *map, __isl_take isl_set *dom,
6688 __isl_give isl_set **empty, unsigned flags)
6690 int i;
6691 int full;
6692 isl_pw_multi_aff *res;
6693 isl_set *todo;
6695 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6696 if (!map || (!full && !dom))
6697 goto error;
6699 if (isl_map_plain_is_empty(map)) {
6700 if (empty)
6701 *empty = dom;
6702 else
6703 isl_set_free(dom);
6704 return isl_pw_multi_aff_from_map(map);
6707 res = basic_map_partial_lexopt_pw_multi_aff(
6708 isl_basic_map_copy(map->p[0]),
6709 isl_set_copy(dom), empty, flags);
6711 if (empty)
6712 todo = *empty;
6713 for (i = 1; i < map->n; ++i) {
6714 isl_pw_multi_aff *res_i;
6716 res_i = basic_map_partial_lexopt_pw_multi_aff(
6717 isl_basic_map_copy(map->p[i]),
6718 isl_set_copy(dom), empty, flags);
6720 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6721 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6722 else
6723 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6725 if (empty)
6726 todo = isl_set_intersect(todo, *empty);
6729 isl_set_free(dom);
6730 isl_map_free(map);
6732 if (empty)
6733 *empty = todo;
6735 return res;
6736 error:
6737 if (empty)
6738 *empty = NULL;
6739 isl_set_free(dom);
6740 isl_map_free(map);
6741 return NULL;
6744 #undef TYPE
6745 #define TYPE isl_map
6746 #undef SUFFIX
6747 #define SUFFIX
6748 #undef EMPTY
6749 #define EMPTY isl_map_empty
6750 #undef ADD
6751 #define ADD isl_map_union_disjoint
6752 #include "isl_map_lexopt_templ.c"
6754 /* Given a map "map", compute the lexicographically minimal
6755 * (or maximal) image element for each domain element in "dom",
6756 * in the form of an isl_map.
6757 * If "empty" is not NULL, then set *empty to those elements in "dom" that
6758 * do not have an image element.
6759 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6760 * should be computed over the domain of "map". "empty" is also NULL
6761 * in this case.
6763 * If the input consists of more than one disjunct, then first
6764 * compute the desired result in the form of an isl_pw_multi_aff and
6765 * then convert that into an isl_map.
6767 * This function used to have an explicit implementation in terms
6768 * of isl_maps, but it would continually intersect the domains of
6769 * partial results with the complement of the domain of the next
6770 * partial solution, potentially leading to an explosion in the number
6771 * of disjuncts if there are several disjuncts in the input.
6772 * An even earlier implementation of this function would look for
6773 * better results in the domain of the partial result and for extra
6774 * results in the complement of this domain, which would lead to
6775 * even more splintering.
6777 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6778 __isl_take isl_map *map, __isl_take isl_set *dom,
6779 __isl_give isl_set **empty, unsigned flags)
6781 int full;
6782 struct isl_map *res;
6783 isl_pw_multi_aff *pma;
6785 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6786 if (!map || (!full && !dom))
6787 goto error;
6789 if (isl_map_plain_is_empty(map)) {
6790 if (empty)
6791 *empty = dom;
6792 else
6793 isl_set_free(dom);
6794 return map;
6797 if (map->n == 1) {
6798 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6799 dom, empty, flags);
6800 isl_map_free(map);
6801 return res;
6804 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6805 flags);
6806 return isl_map_from_pw_multi_aff(pma);
6807 error:
6808 if (empty)
6809 *empty = NULL;
6810 isl_set_free(dom);
6811 isl_map_free(map);
6812 return NULL;
6815 __isl_give isl_map *isl_map_partial_lexmax(
6816 __isl_take isl_map *map, __isl_take isl_set *dom,
6817 __isl_give isl_set **empty)
6819 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6822 __isl_give isl_map *isl_map_partial_lexmin(
6823 __isl_take isl_map *map, __isl_take isl_set *dom,
6824 __isl_give isl_set **empty)
6826 return isl_map_partial_lexopt(map, dom, empty, 0);
6829 __isl_give isl_set *isl_set_partial_lexmin(
6830 __isl_take isl_set *set, __isl_take isl_set *dom,
6831 __isl_give isl_set **empty)
6833 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6834 dom, empty));
6837 __isl_give isl_set *isl_set_partial_lexmax(
6838 __isl_take isl_set *set, __isl_take isl_set *dom,
6839 __isl_give isl_set **empty)
6841 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6842 dom, empty));
6845 /* Compute the lexicographic minimum (or maximum if "flags" includes
6846 * ISL_OPT_MAX) of "bset" over its parametric domain.
6848 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6849 unsigned flags)
6851 return isl_basic_map_lexopt(bset, flags);
6854 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6856 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6859 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6861 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6864 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6866 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6869 /* Compute the lexicographic minimum of "bset" over its parametric domain
6870 * for the purpose of quantifier elimination.
6871 * That is, find an explicit representation for all the existentially
6872 * quantified variables in "bset" by computing their lexicographic
6873 * minimum.
6875 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6876 __isl_take isl_basic_set *bset)
6878 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6881 /* Given a basic map with one output dimension, compute the minimum or
6882 * maximum of that dimension as an isl_pw_aff.
6884 * Compute the optimum as a lexicographic optimum over the single
6885 * output dimension and extract the single isl_pw_aff from the result.
6887 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6888 int max)
6890 isl_pw_multi_aff *pma;
6891 isl_pw_aff *pwaff;
6893 bmap = isl_basic_map_copy(bmap);
6894 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
6895 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
6896 isl_pw_multi_aff_free(pma);
6898 return pwaff;
6901 /* Compute the minimum or maximum of the given output dimension
6902 * as a function of the parameters and the input dimensions,
6903 * but independently of the other output dimensions.
6905 * We first project out the other output dimension and then compute
6906 * the "lexicographic" maximum in each basic map, combining the results
6907 * using isl_pw_aff_union_max.
6909 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6910 int max)
6912 int i;
6913 isl_pw_aff *pwaff;
6914 unsigned n_out;
6916 n_out = isl_map_dim(map, isl_dim_out);
6917 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6918 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6919 if (!map)
6920 return NULL;
6922 if (map->n == 0) {
6923 isl_space *space = isl_map_get_space(map);
6924 isl_map_free(map);
6925 return isl_pw_aff_empty(space);
6928 pwaff = basic_map_dim_opt(map->p[0], max);
6929 for (i = 1; i < map->n; ++i) {
6930 isl_pw_aff *pwaff_i;
6932 pwaff_i = basic_map_dim_opt(map->p[i], max);
6933 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6936 isl_map_free(map);
6938 return pwaff;
6941 /* Compute the minimum of the given output dimension as a function of the
6942 * parameters and input dimensions, but independently of
6943 * the other output dimensions.
6945 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
6947 return map_dim_opt(map, pos, 0);
6950 /* Compute the maximum of the given output dimension as a function of the
6951 * parameters and input dimensions, but independently of
6952 * the other output dimensions.
6954 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6956 return map_dim_opt(map, pos, 1);
6959 /* Compute the minimum or maximum of the given set dimension
6960 * as a function of the parameters,
6961 * but independently of the other set dimensions.
6963 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
6964 int max)
6966 return map_dim_opt(set, pos, max);
6969 /* Compute the maximum of the given set dimension as a function of the
6970 * parameters, but independently of the other set dimensions.
6972 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
6974 return set_dim_opt(set, pos, 1);
6977 /* Compute the minimum of the given set dimension as a function of the
6978 * parameters, but independently of the other set dimensions.
6980 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
6982 return set_dim_opt(set, pos, 0);
6985 /* Apply a preimage specified by "mat" on the parameters of "bset".
6986 * bset is assumed to have only parameters and divs.
6988 static __isl_give isl_basic_set *basic_set_parameter_preimage(
6989 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
6991 unsigned nparam;
6993 if (!bset || !mat)
6994 goto error;
6996 bset->dim = isl_space_cow(bset->dim);
6997 if (!bset->dim)
6998 goto error;
7000 nparam = isl_basic_set_dim(bset, isl_dim_param);
7002 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7004 bset->dim->nparam = 0;
7005 bset->dim->n_out = nparam;
7006 bset = isl_basic_set_preimage(bset, mat);
7007 if (bset) {
7008 bset->dim->nparam = bset->dim->n_out;
7009 bset->dim->n_out = 0;
7011 return bset;
7012 error:
7013 isl_mat_free(mat);
7014 isl_basic_set_free(bset);
7015 return NULL;
7018 /* Apply a preimage specified by "mat" on the parameters of "set".
7019 * set is assumed to have only parameters and divs.
7021 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7022 __isl_take isl_mat *mat)
7024 isl_space *space;
7025 unsigned nparam;
7027 if (!set || !mat)
7028 goto error;
7030 nparam = isl_set_dim(set, isl_dim_param);
7032 if (mat->n_row != 1 + nparam)
7033 isl_die(isl_set_get_ctx(set), isl_error_internal,
7034 "unexpected number of rows", goto error);
7036 space = isl_set_get_space(set);
7037 space = isl_space_move_dims(space, isl_dim_set, 0,
7038 isl_dim_param, 0, nparam);
7039 set = isl_set_reset_space(set, space);
7040 set = isl_set_preimage(set, mat);
7041 nparam = isl_set_dim(set, isl_dim_out);
7042 space = isl_set_get_space(set);
7043 space = isl_space_move_dims(space, isl_dim_param, 0,
7044 isl_dim_out, 0, nparam);
7045 set = isl_set_reset_space(set, space);
7046 return set;
7047 error:
7048 isl_mat_free(mat);
7049 isl_set_free(set);
7050 return NULL;
7053 /* Intersect the basic set "bset" with the affine space specified by the
7054 * equalities in "eq".
7056 static __isl_give isl_basic_set *basic_set_append_equalities(
7057 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7059 int i, k;
7060 unsigned len;
7062 if (!bset || !eq)
7063 goto error;
7065 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
7066 eq->n_row, 0);
7067 if (!bset)
7068 goto error;
7070 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
7071 for (i = 0; i < eq->n_row; ++i) {
7072 k = isl_basic_set_alloc_equality(bset);
7073 if (k < 0)
7074 goto error;
7075 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7076 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7078 isl_mat_free(eq);
7080 bset = isl_basic_set_gauss(bset, NULL);
7081 bset = isl_basic_set_finalize(bset);
7083 return bset;
7084 error:
7085 isl_mat_free(eq);
7086 isl_basic_set_free(bset);
7087 return NULL;
7090 /* Intersect the set "set" with the affine space specified by the
7091 * equalities in "eq".
7093 static struct isl_set *set_append_equalities(struct isl_set *set,
7094 struct isl_mat *eq)
7096 int i;
7098 if (!set || !eq)
7099 goto error;
7101 for (i = 0; i < set->n; ++i) {
7102 set->p[i] = basic_set_append_equalities(set->p[i],
7103 isl_mat_copy(eq));
7104 if (!set->p[i])
7105 goto error;
7107 isl_mat_free(eq);
7108 return set;
7109 error:
7110 isl_mat_free(eq);
7111 isl_set_free(set);
7112 return NULL;
7115 /* Given a basic set "bset" that only involves parameters and existentially
7116 * quantified variables, return the index of the first equality
7117 * that only involves parameters. If there is no such equality then
7118 * return bset->n_eq.
7120 * This function assumes that isl_basic_set_gauss has been called on "bset".
7122 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7124 int i, j;
7125 unsigned nparam, n_div;
7127 if (!bset)
7128 return -1;
7130 nparam = isl_basic_set_dim(bset, isl_dim_param);
7131 n_div = isl_basic_set_dim(bset, isl_dim_div);
7133 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7134 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7135 ++i;
7138 return i;
7141 /* Compute an explicit representation for the existentially quantified
7142 * variables in "bset" by computing the "minimal value" of the set
7143 * variables. Since there are no set variables, the computation of
7144 * the minimal value essentially computes an explicit representation
7145 * of the non-empty part(s) of "bset".
7147 * The input only involves parameters and existentially quantified variables.
7148 * All equalities among parameters have been removed.
7150 * Since the existentially quantified variables in the result are in general
7151 * going to be different from those in the input, we first replace
7152 * them by the minimal number of variables based on their equalities.
7153 * This should simplify the parametric integer programming.
7155 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7157 isl_morph *morph1, *morph2;
7158 isl_set *set;
7159 unsigned n;
7161 if (!bset)
7162 return NULL;
7163 if (bset->n_eq == 0)
7164 return isl_basic_set_lexmin_compute_divs(bset);
7166 morph1 = isl_basic_set_parameter_compression(bset);
7167 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7168 bset = isl_basic_set_lift(bset);
7169 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7170 bset = isl_morph_basic_set(morph2, bset);
7171 n = isl_basic_set_dim(bset, isl_dim_set);
7172 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7174 set = isl_basic_set_lexmin_compute_divs(bset);
7176 set = isl_morph_set(isl_morph_inverse(morph1), set);
7178 return set;
7181 /* Project the given basic set onto its parameter domain, possibly introducing
7182 * new, explicit, existential variables in the constraints.
7183 * The input has parameters and (possibly implicit) existential variables.
7184 * The output has the same parameters, but only
7185 * explicit existentially quantified variables.
7187 * The actual projection is performed by pip, but pip doesn't seem
7188 * to like equalities very much, so we first remove the equalities
7189 * among the parameters by performing a variable compression on
7190 * the parameters. Afterward, an inverse transformation is performed
7191 * and the equalities among the parameters are inserted back in.
7193 * The variable compression on the parameters may uncover additional
7194 * equalities that were only implicit before. We therefore check
7195 * if there are any new parameter equalities in the result and
7196 * if so recurse. The removal of parameter equalities is required
7197 * for the parameter compression performed by base_compute_divs.
7199 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
7201 int i;
7202 struct isl_mat *eq;
7203 struct isl_mat *T, *T2;
7204 struct isl_set *set;
7205 unsigned nparam;
7207 bset = isl_basic_set_cow(bset);
7208 if (!bset)
7209 return NULL;
7211 if (bset->n_eq == 0)
7212 return base_compute_divs(bset);
7214 bset = isl_basic_set_gauss(bset, NULL);
7215 if (!bset)
7216 return NULL;
7217 if (isl_basic_set_plain_is_empty(bset))
7218 return isl_set_from_basic_set(bset);
7220 i = first_parameter_equality(bset);
7221 if (i == bset->n_eq)
7222 return base_compute_divs(bset);
7224 nparam = isl_basic_set_dim(bset, isl_dim_param);
7225 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7226 0, 1 + nparam);
7227 eq = isl_mat_cow(eq);
7228 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7229 if (T && T->n_col == 0) {
7230 isl_mat_free(T);
7231 isl_mat_free(T2);
7232 isl_mat_free(eq);
7233 bset = isl_basic_set_set_to_empty(bset);
7234 return isl_set_from_basic_set(bset);
7236 bset = basic_set_parameter_preimage(bset, T);
7238 i = first_parameter_equality(bset);
7239 if (!bset)
7240 set = NULL;
7241 else if (i == bset->n_eq)
7242 set = base_compute_divs(bset);
7243 else
7244 set = parameter_compute_divs(bset);
7245 set = set_parameter_preimage(set, T2);
7246 set = set_append_equalities(set, eq);
7247 return set;
7250 /* Insert the divs from "ls" before those of "bmap".
7252 * The number of columns is not changed, which means that the last
7253 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7254 * The caller is responsible for removing the same number of dimensions
7255 * from the space of "bmap".
7257 static __isl_give isl_basic_map *insert_divs_from_local_space(
7258 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7260 int i;
7261 int n_div;
7262 int old_n_div;
7264 n_div = isl_local_space_dim(ls, isl_dim_div);
7265 if (n_div == 0)
7266 return bmap;
7268 old_n_div = bmap->n_div;
7269 bmap = insert_div_rows(bmap, n_div);
7270 if (!bmap)
7271 return NULL;
7273 for (i = 0; i < n_div; ++i) {
7274 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7275 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7278 return bmap;
7281 /* Replace the space of "bmap" by the space and divs of "ls".
7283 * If "ls" has any divs, then we simplify the result since we may
7284 * have discovered some additional equalities that could simplify
7285 * the div expressions.
7287 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7288 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7290 int n_div;
7292 bmap = isl_basic_map_cow(bmap);
7293 if (!bmap || !ls)
7294 goto error;
7296 n_div = isl_local_space_dim(ls, isl_dim_div);
7297 bmap = insert_divs_from_local_space(bmap, ls);
7298 if (!bmap)
7299 goto error;
7301 isl_space_free(bmap->dim);
7302 bmap->dim = isl_local_space_get_space(ls);
7303 if (!bmap->dim)
7304 goto error;
7306 isl_local_space_free(ls);
7307 if (n_div > 0)
7308 bmap = isl_basic_map_simplify(bmap);
7309 bmap = isl_basic_map_finalize(bmap);
7310 return bmap;
7311 error:
7312 isl_basic_map_free(bmap);
7313 isl_local_space_free(ls);
7314 return NULL;
7317 /* Replace the space of "map" by the space and divs of "ls".
7319 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7320 __isl_take isl_local_space *ls)
7322 int i;
7324 map = isl_map_cow(map);
7325 if (!map || !ls)
7326 goto error;
7328 for (i = 0; i < map->n; ++i) {
7329 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7330 isl_local_space_copy(ls));
7331 if (!map->p[i])
7332 goto error;
7334 isl_space_free(map->dim);
7335 map->dim = isl_local_space_get_space(ls);
7336 if (!map->dim)
7337 goto error;
7339 isl_local_space_free(ls);
7340 return map;
7341 error:
7342 isl_local_space_free(ls);
7343 isl_map_free(map);
7344 return NULL;
7347 /* Compute an explicit representation for the existentially
7348 * quantified variables for which do not know any explicit representation yet.
7350 * We first sort the existentially quantified variables so that the
7351 * existentially quantified variables for which we already have an explicit
7352 * representation are placed before those for which we do not.
7353 * The input dimensions, the output dimensions and the existentially
7354 * quantified variables for which we already have an explicit
7355 * representation are then turned into parameters.
7356 * compute_divs returns a map with the same parameters and
7357 * no input or output dimensions and the dimension specification
7358 * is reset to that of the input, including the existentially quantified
7359 * variables for which we already had an explicit representation.
7361 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7363 struct isl_basic_set *bset;
7364 struct isl_set *set;
7365 struct isl_map *map;
7366 isl_space *space;
7367 isl_local_space *ls;
7368 unsigned nparam;
7369 unsigned n_in;
7370 unsigned n_out;
7371 int n_known;
7372 int i;
7374 bmap = isl_basic_map_sort_divs(bmap);
7375 bmap = isl_basic_map_cow(bmap);
7376 if (!bmap)
7377 return NULL;
7379 n_known = isl_basic_map_first_unknown_div(bmap);
7380 if (n_known < 0)
7381 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7383 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7384 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7385 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7386 space = isl_space_set_alloc(bmap->ctx,
7387 nparam + n_in + n_out + n_known, 0);
7388 if (!space)
7389 goto error;
7391 ls = isl_basic_map_get_local_space(bmap);
7392 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7393 n_known, bmap->n_div - n_known);
7394 if (n_known > 0) {
7395 for (i = n_known; i < bmap->n_div; ++i)
7396 swap_div(bmap, i - n_known, i);
7397 bmap->n_div -= n_known;
7398 bmap->extra -= n_known;
7400 bmap = isl_basic_map_reset_space(bmap, space);
7401 bset = bset_from_bmap(bmap);
7403 set = parameter_compute_divs(bset);
7404 map = set_to_map(set);
7405 map = replace_space_by_local_space(map, ls);
7407 return map;
7408 error:
7409 isl_basic_map_free(bmap);
7410 return NULL;
7413 /* Remove the explicit representation of local variable "div",
7414 * if there is any.
7416 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7417 __isl_take isl_basic_map *bmap, int div)
7419 isl_bool unknown;
7421 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7422 if (unknown < 0)
7423 return isl_basic_map_free(bmap);
7424 if (unknown)
7425 return bmap;
7427 bmap = isl_basic_map_cow(bmap);
7428 if (!bmap)
7429 return NULL;
7430 isl_int_set_si(bmap->div[div][0], 0);
7431 return bmap;
7434 /* Is local variable "div" of "bmap" marked as not having an explicit
7435 * representation?
7436 * Note that even if "div" is not marked in this way and therefore
7437 * has an explicit representation, this representation may still
7438 * depend (indirectly) on other local variables that do not
7439 * have an explicit representation.
7441 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7442 int div)
7444 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7445 return isl_bool_error;
7446 return isl_int_is_zero(bmap->div[div][0]);
7449 /* Return the position of the first local variable that does not
7450 * have an explicit representation.
7451 * Return the total number of local variables if they all have
7452 * an explicit representation.
7453 * Return -1 on error.
7455 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7457 int i;
7459 if (!bmap)
7460 return -1;
7462 for (i = 0; i < bmap->n_div; ++i) {
7463 if (!isl_basic_map_div_is_known(bmap, i))
7464 return i;
7466 return bmap->n_div;
7469 /* Return the position of the first local variable that does not
7470 * have an explicit representation.
7471 * Return the total number of local variables if they all have
7472 * an explicit representation.
7473 * Return -1 on error.
7475 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7477 return isl_basic_map_first_unknown_div(bset);
7480 /* Does "bmap" have an explicit representation for all local variables?
7482 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7484 int first, n;
7486 n = isl_basic_map_dim(bmap, isl_dim_div);
7487 first = isl_basic_map_first_unknown_div(bmap);
7488 if (first < 0)
7489 return isl_bool_error;
7490 return first == n;
7493 /* Do all basic maps in "map" have an explicit representation
7494 * for all local variables?
7496 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7498 int i;
7500 if (!map)
7501 return isl_bool_error;
7503 for (i = 0; i < map->n; ++i) {
7504 int known = isl_basic_map_divs_known(map->p[i]);
7505 if (known <= 0)
7506 return known;
7509 return isl_bool_true;
7512 /* If bmap contains any unknown divs, then compute explicit
7513 * expressions for them. However, this computation may be
7514 * quite expensive, so first try to remove divs that aren't
7515 * strictly needed.
7517 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7519 int known;
7520 struct isl_map *map;
7522 known = isl_basic_map_divs_known(bmap);
7523 if (known < 0)
7524 goto error;
7525 if (known)
7526 return isl_map_from_basic_map(bmap);
7528 bmap = isl_basic_map_drop_redundant_divs(bmap);
7530 known = isl_basic_map_divs_known(bmap);
7531 if (known < 0)
7532 goto error;
7533 if (known)
7534 return isl_map_from_basic_map(bmap);
7536 map = compute_divs(bmap);
7537 return map;
7538 error:
7539 isl_basic_map_free(bmap);
7540 return NULL;
7543 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7545 int i;
7546 int known;
7547 struct isl_map *res;
7549 if (!map)
7550 return NULL;
7551 if (map->n == 0)
7552 return map;
7554 known = isl_map_divs_known(map);
7555 if (known < 0) {
7556 isl_map_free(map);
7557 return NULL;
7559 if (known)
7560 return map;
7562 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7563 for (i = 1 ; i < map->n; ++i) {
7564 struct isl_map *r2;
7565 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7566 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7567 res = isl_map_union_disjoint(res, r2);
7568 else
7569 res = isl_map_union(res, r2);
7571 isl_map_free(map);
7573 return res;
7576 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
7578 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7581 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7583 return set_from_map(isl_map_compute_divs(set_to_map(set)));
7586 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
7588 int i;
7589 struct isl_set *set;
7591 if (!map)
7592 goto error;
7594 map = isl_map_cow(map);
7595 if (!map)
7596 return NULL;
7598 set = set_from_map(map);
7599 set->dim = isl_space_domain(set->dim);
7600 if (!set->dim)
7601 goto error;
7602 for (i = 0; i < map->n; ++i) {
7603 set->p[i] = isl_basic_map_domain(map->p[i]);
7604 if (!set->p[i])
7605 goto error;
7607 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7608 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7609 return set;
7610 error:
7611 isl_map_free(map);
7612 return NULL;
7615 /* Return the union of "map1" and "map2", where we assume for now that
7616 * "map1" and "map2" are disjoint. Note that the basic maps inside
7617 * "map1" or "map2" may not be disjoint from each other.
7618 * Also note that this function is also called from isl_map_union,
7619 * which takes care of handling the situation where "map1" and "map2"
7620 * may not be disjoint.
7622 * If one of the inputs is empty, we can simply return the other input.
7623 * Similarly, if one of the inputs is universal, then it is equal to the union.
7625 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7626 __isl_take isl_map *map2)
7628 int i;
7629 unsigned flags = 0;
7630 struct isl_map *map = NULL;
7631 int is_universe;
7633 if (!map1 || !map2)
7634 goto error;
7636 if (!isl_space_is_equal(map1->dim, map2->dim))
7637 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7638 "spaces don't match", goto error);
7640 if (map1->n == 0) {
7641 isl_map_free(map1);
7642 return map2;
7644 if (map2->n == 0) {
7645 isl_map_free(map2);
7646 return map1;
7649 is_universe = isl_map_plain_is_universe(map1);
7650 if (is_universe < 0)
7651 goto error;
7652 if (is_universe) {
7653 isl_map_free(map2);
7654 return map1;
7657 is_universe = isl_map_plain_is_universe(map2);
7658 if (is_universe < 0)
7659 goto error;
7660 if (is_universe) {
7661 isl_map_free(map1);
7662 return map2;
7665 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7666 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7667 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7669 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7670 map1->n + map2->n, flags);
7671 if (!map)
7672 goto error;
7673 for (i = 0; i < map1->n; ++i) {
7674 map = isl_map_add_basic_map(map,
7675 isl_basic_map_copy(map1->p[i]));
7676 if (!map)
7677 goto error;
7679 for (i = 0; i < map2->n; ++i) {
7680 map = isl_map_add_basic_map(map,
7681 isl_basic_map_copy(map2->p[i]));
7682 if (!map)
7683 goto error;
7685 isl_map_free(map1);
7686 isl_map_free(map2);
7687 return map;
7688 error:
7689 isl_map_free(map);
7690 isl_map_free(map1);
7691 isl_map_free(map2);
7692 return NULL;
7695 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7696 * guaranteed to be disjoint by the caller.
7698 * Note that this functions is called from within isl_map_make_disjoint,
7699 * so we have to be careful not to touch the constraints of the inputs
7700 * in any way.
7702 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7703 __isl_take isl_map *map2)
7705 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7708 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7709 * not be disjoint. The parameters are assumed to have been aligned.
7711 * We currently simply call map_union_disjoint, the internal operation
7712 * of which does not really depend on the inputs being disjoint.
7713 * If the result contains more than one basic map, then we clear
7714 * the disjoint flag since the result may contain basic maps from
7715 * both inputs and these are not guaranteed to be disjoint.
7717 * As a special case, if "map1" and "map2" are obviously equal,
7718 * then we simply return "map1".
7720 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7721 __isl_take isl_map *map2)
7723 int equal;
7725 if (!map1 || !map2)
7726 goto error;
7728 equal = isl_map_plain_is_equal(map1, map2);
7729 if (equal < 0)
7730 goto error;
7731 if (equal) {
7732 isl_map_free(map2);
7733 return map1;
7736 map1 = map_union_disjoint(map1, map2);
7737 if (!map1)
7738 return NULL;
7739 if (map1->n > 1)
7740 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7741 return map1;
7742 error:
7743 isl_map_free(map1);
7744 isl_map_free(map2);
7745 return NULL;
7748 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7749 * not be disjoint.
7751 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7752 __isl_take isl_map *map2)
7754 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7757 __isl_give isl_set *isl_set_union_disjoint(
7758 __isl_take isl_set *set1, __isl_take isl_set *set2)
7760 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7761 set_to_map(set2)));
7764 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7766 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7769 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7770 * the results.
7772 * "map" and "set" are assumed to be compatible and non-NULL.
7774 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7775 __isl_take isl_set *set,
7776 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7777 __isl_take isl_basic_set *bset))
7779 unsigned flags = 0;
7780 struct isl_map *result;
7781 int i, j;
7783 if (isl_set_plain_is_universe(set)) {
7784 isl_set_free(set);
7785 return map;
7788 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7789 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7790 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7792 result = isl_map_alloc_space(isl_space_copy(map->dim),
7793 map->n * set->n, flags);
7794 for (i = 0; result && i < map->n; ++i)
7795 for (j = 0; j < set->n; ++j) {
7796 result = isl_map_add_basic_map(result,
7797 fn(isl_basic_map_copy(map->p[i]),
7798 isl_basic_set_copy(set->p[j])));
7799 if (!result)
7800 break;
7803 isl_map_free(map);
7804 isl_set_free(set);
7805 return result;
7808 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7809 __isl_take isl_set *set)
7811 isl_bool ok;
7813 ok = isl_map_compatible_range(map, set);
7814 if (ok < 0)
7815 goto error;
7816 if (!ok)
7817 isl_die(set->ctx, isl_error_invalid,
7818 "incompatible spaces", goto error);
7820 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7821 error:
7822 isl_map_free(map);
7823 isl_set_free(set);
7824 return NULL;
7827 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7828 __isl_take isl_set *set)
7830 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7833 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7834 __isl_take isl_set *set)
7836 isl_bool ok;
7838 ok = isl_map_compatible_domain(map, set);
7839 if (ok < 0)
7840 goto error;
7841 if (!ok)
7842 isl_die(set->ctx, isl_error_invalid,
7843 "incompatible spaces", goto error);
7845 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7846 error:
7847 isl_map_free(map);
7848 isl_set_free(set);
7849 return NULL;
7852 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7853 __isl_take isl_set *set)
7855 return isl_map_align_params_map_map_and(map, set,
7856 &map_intersect_domain);
7859 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7860 * in the space B -> C, return the intersection.
7861 * The parameters are assumed to have been aligned.
7863 * The map "factor" is first extended to a map living in the space
7864 * [A -> B] -> C and then a regular intersection is computed.
7866 static __isl_give isl_map *map_intersect_domain_factor_range(
7867 __isl_take isl_map *map, __isl_take isl_map *factor)
7869 isl_space *space;
7870 isl_map *ext_factor;
7872 space = isl_space_domain_factor_domain(isl_map_get_space(map));
7873 ext_factor = isl_map_universe(space);
7874 ext_factor = isl_map_domain_product(ext_factor, factor);
7875 return map_intersect(map, ext_factor);
7878 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7879 * in the space B -> C, return the intersection.
7881 __isl_give isl_map *isl_map_intersect_domain_factor_range(
7882 __isl_take isl_map *map, __isl_take isl_map *factor)
7884 return isl_map_align_params_map_map_and(map, factor,
7885 &map_intersect_domain_factor_range);
7888 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7889 * in the space A -> C, return the intersection.
7891 * The map "factor" is first extended to a map living in the space
7892 * A -> [B -> C] and then a regular intersection is computed.
7894 static __isl_give isl_map *map_intersect_range_factor_range(
7895 __isl_take isl_map *map, __isl_take isl_map *factor)
7897 isl_space *space;
7898 isl_map *ext_factor;
7900 space = isl_space_range_factor_domain(isl_map_get_space(map));
7901 ext_factor = isl_map_universe(space);
7902 ext_factor = isl_map_range_product(ext_factor, factor);
7903 return isl_map_intersect(map, ext_factor);
7906 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7907 * in the space A -> C, return the intersection.
7909 __isl_give isl_map *isl_map_intersect_range_factor_range(
7910 __isl_take isl_map *map, __isl_take isl_map *factor)
7912 return isl_map_align_params_map_map_and(map, factor,
7913 &map_intersect_range_factor_range);
7916 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7917 __isl_take isl_map *map2)
7919 if (!map1 || !map2)
7920 goto error;
7921 map1 = isl_map_reverse(map1);
7922 map1 = isl_map_apply_range(map1, map2);
7923 return isl_map_reverse(map1);
7924 error:
7925 isl_map_free(map1);
7926 isl_map_free(map2);
7927 return NULL;
7930 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7931 __isl_take isl_map *map2)
7933 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7936 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7937 __isl_take isl_map *map2)
7939 isl_space *space;
7940 struct isl_map *result;
7941 int i, j;
7943 if (!map1 || !map2)
7944 goto error;
7946 space = isl_space_join(isl_space_copy(map1->dim),
7947 isl_space_copy(map2->dim));
7949 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
7950 if (!result)
7951 goto error;
7952 for (i = 0; i < map1->n; ++i)
7953 for (j = 0; j < map2->n; ++j) {
7954 result = isl_map_add_basic_map(result,
7955 isl_basic_map_apply_range(
7956 isl_basic_map_copy(map1->p[i]),
7957 isl_basic_map_copy(map2->p[j])));
7958 if (!result)
7959 goto error;
7961 isl_map_free(map1);
7962 isl_map_free(map2);
7963 if (result && result->n <= 1)
7964 ISL_F_SET(result, ISL_MAP_DISJOINT);
7965 return result;
7966 error:
7967 isl_map_free(map1);
7968 isl_map_free(map2);
7969 return NULL;
7972 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
7973 __isl_take isl_map *map2)
7975 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
7979 * returns range - domain
7981 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
7983 isl_space *target_space;
7984 struct isl_basic_set *bset;
7985 unsigned dim;
7986 unsigned nparam;
7987 int i;
7989 if (!bmap)
7990 goto error;
7991 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7992 bmap->dim, isl_dim_out),
7993 goto error);
7994 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
7995 dim = isl_basic_map_dim(bmap, isl_dim_in);
7996 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7997 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
7998 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
7999 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8000 for (i = 0; i < dim; ++i) {
8001 int j = isl_basic_map_alloc_equality(bmap);
8002 if (j < 0) {
8003 bmap = isl_basic_map_free(bmap);
8004 break;
8006 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
8007 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8008 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8009 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8011 bset = isl_basic_map_domain(bmap);
8012 bset = isl_basic_set_reset_space(bset, target_space);
8013 return bset;
8014 error:
8015 isl_basic_map_free(bmap);
8016 return NULL;
8020 * returns range - domain
8022 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8024 int i;
8025 isl_space *dim;
8026 struct isl_set *result;
8028 if (!map)
8029 return NULL;
8031 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
8032 map->dim, isl_dim_out),
8033 goto error);
8034 dim = isl_map_get_space(map);
8035 dim = isl_space_domain(dim);
8036 result = isl_set_alloc_space(dim, map->n, 0);
8037 if (!result)
8038 goto error;
8039 for (i = 0; i < map->n; ++i)
8040 result = isl_set_add_basic_set(result,
8041 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8042 isl_map_free(map);
8043 return result;
8044 error:
8045 isl_map_free(map);
8046 return NULL;
8050 * returns [domain -> range] -> range - domain
8052 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8053 __isl_take isl_basic_map *bmap)
8055 int i, k;
8056 isl_space *space;
8057 isl_basic_map *domain;
8058 int nparam, n;
8059 unsigned total;
8061 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8062 bmap->dim, isl_dim_out))
8063 isl_die(bmap->ctx, isl_error_invalid,
8064 "domain and range don't match", goto error);
8066 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8067 n = isl_basic_map_dim(bmap, isl_dim_in);
8069 space = isl_basic_map_get_space(bmap);
8070 space = isl_space_from_range(isl_space_domain(space));
8071 domain = isl_basic_map_universe(space);
8073 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8074 bmap = isl_basic_map_apply_range(bmap, domain);
8075 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8077 total = isl_basic_map_total_dim(bmap);
8079 for (i = 0; i < n; ++i) {
8080 k = isl_basic_map_alloc_equality(bmap);
8081 if (k < 0)
8082 goto error;
8083 isl_seq_clr(bmap->eq[k], 1 + total);
8084 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8085 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8086 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8089 bmap = isl_basic_map_gauss(bmap, NULL);
8090 return isl_basic_map_finalize(bmap);
8091 error:
8092 isl_basic_map_free(bmap);
8093 return NULL;
8097 * returns [domain -> range] -> range - domain
8099 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8101 int i;
8102 isl_space *domain_space;
8104 if (!map)
8105 return NULL;
8107 if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
8108 map->dim, isl_dim_out))
8109 isl_die(map->ctx, isl_error_invalid,
8110 "domain and range don't match", goto error);
8112 map = isl_map_cow(map);
8113 if (!map)
8114 return NULL;
8116 domain_space = isl_space_domain(isl_map_get_space(map));
8117 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
8118 map->dim = isl_space_join(map->dim, isl_space_from_range(domain_space));
8119 if (!map->dim)
8120 goto error;
8121 for (i = 0; i < map->n; ++i) {
8122 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
8123 if (!map->p[i])
8124 goto error;
8126 map = isl_map_unmark_normalized(map);
8127 return map;
8128 error:
8129 isl_map_free(map);
8130 return NULL;
8133 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8135 unsigned n_in, n_out;
8137 if (!space)
8138 return NULL;
8139 n_in = isl_space_dim(space, isl_dim_in);
8140 n_out = isl_space_dim(space, isl_dim_out);
8141 if (n_in != n_out)
8142 isl_die(space->ctx, isl_error_invalid,
8143 "number of input and output dimensions needs to be "
8144 "the same", goto error);
8145 return isl_basic_map_equal(space, n_in);
8146 error:
8147 isl_space_free(space);
8148 return NULL;
8151 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
8153 return isl_map_from_basic_map(isl_basic_map_identity(dim));
8156 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8158 isl_space *dim = isl_set_get_space(set);
8159 isl_map *id;
8160 id = isl_map_identity(isl_space_map_from_set(dim));
8161 return isl_map_intersect_range(id, set);
8164 /* Construct a basic set with all set dimensions having only non-negative
8165 * values.
8167 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8168 __isl_take isl_space *space)
8170 int i;
8171 unsigned nparam;
8172 unsigned dim;
8173 struct isl_basic_set *bset;
8175 if (!space)
8176 return NULL;
8177 nparam = space->nparam;
8178 dim = space->n_out;
8179 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8180 if (!bset)
8181 return NULL;
8182 for (i = 0; i < dim; ++i) {
8183 int k = isl_basic_set_alloc_inequality(bset);
8184 if (k < 0)
8185 goto error;
8186 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
8187 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8189 return bset;
8190 error:
8191 isl_basic_set_free(bset);
8192 return NULL;
8195 /* Construct the half-space x_pos >= 0.
8197 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8198 int pos)
8200 int k;
8201 isl_basic_set *nonneg;
8203 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8204 k = isl_basic_set_alloc_inequality(nonneg);
8205 if (k < 0)
8206 goto error;
8207 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
8208 isl_int_set_si(nonneg->ineq[k][pos], 1);
8210 return isl_basic_set_finalize(nonneg);
8211 error:
8212 isl_basic_set_free(nonneg);
8213 return NULL;
8216 /* Construct the half-space x_pos <= -1.
8218 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8219 int pos)
8221 int k;
8222 isl_basic_set *neg;
8224 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8225 k = isl_basic_set_alloc_inequality(neg);
8226 if (k < 0)
8227 goto error;
8228 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
8229 isl_int_set_si(neg->ineq[k][0], -1);
8230 isl_int_set_si(neg->ineq[k][pos], -1);
8232 return isl_basic_set_finalize(neg);
8233 error:
8234 isl_basic_set_free(neg);
8235 return NULL;
8238 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8239 enum isl_dim_type type, unsigned first, unsigned n)
8241 int i;
8242 unsigned offset;
8243 isl_basic_set *nonneg;
8244 isl_basic_set *neg;
8246 if (!set)
8247 return NULL;
8248 if (n == 0)
8249 return set;
8251 isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
8253 offset = pos(set->dim, type);
8254 for (i = 0; i < n; ++i) {
8255 nonneg = nonneg_halfspace(isl_set_get_space(set),
8256 offset + first + i);
8257 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8259 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8262 return set;
8263 error:
8264 isl_set_free(set);
8265 return NULL;
8268 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8269 int len,
8270 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8271 void *user)
8273 isl_set *half;
8275 if (!set)
8276 return isl_stat_error;
8277 if (isl_set_plain_is_empty(set)) {
8278 isl_set_free(set);
8279 return isl_stat_ok;
8281 if (first == len)
8282 return fn(set, signs, user);
8284 signs[first] = 1;
8285 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8286 1 + first));
8287 half = isl_set_intersect(half, isl_set_copy(set));
8288 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8289 goto error;
8291 signs[first] = -1;
8292 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8293 1 + first));
8294 half = isl_set_intersect(half, set);
8295 return foreach_orthant(half, signs, first + 1, len, fn, user);
8296 error:
8297 isl_set_free(set);
8298 return isl_stat_error;
8301 /* Call "fn" on the intersections of "set" with each of the orthants
8302 * (except for obviously empty intersections). The orthant is identified
8303 * by the signs array, with each entry having value 1 or -1 according
8304 * to the sign of the corresponding variable.
8306 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8307 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8308 void *user)
8310 unsigned nparam;
8311 unsigned nvar;
8312 int *signs;
8313 isl_stat r;
8315 if (!set)
8316 return isl_stat_error;
8317 if (isl_set_plain_is_empty(set))
8318 return isl_stat_ok;
8320 nparam = isl_set_dim(set, isl_dim_param);
8321 nvar = isl_set_dim(set, isl_dim_set);
8323 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8325 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8326 fn, user);
8328 free(signs);
8330 return r;
8333 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8335 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8338 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8339 __isl_keep isl_basic_map *bmap2)
8341 isl_bool is_subset;
8342 struct isl_map *map1;
8343 struct isl_map *map2;
8345 if (!bmap1 || !bmap2)
8346 return isl_bool_error;
8348 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8349 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8351 is_subset = isl_map_is_subset(map1, map2);
8353 isl_map_free(map1);
8354 isl_map_free(map2);
8356 return is_subset;
8359 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8360 __isl_keep isl_basic_set *bset2)
8362 return isl_basic_map_is_subset(bset1, bset2);
8365 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8366 __isl_keep isl_basic_map *bmap2)
8368 isl_bool is_subset;
8370 if (!bmap1 || !bmap2)
8371 return isl_bool_error;
8372 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8373 if (is_subset != isl_bool_true)
8374 return is_subset;
8375 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8376 return is_subset;
8379 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8380 __isl_keep isl_basic_set *bset2)
8382 return isl_basic_map_is_equal(
8383 bset_to_bmap(bset1), bset_to_bmap(bset2));
8386 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8388 int i;
8389 int is_empty;
8391 if (!map)
8392 return isl_bool_error;
8393 for (i = 0; i < map->n; ++i) {
8394 is_empty = isl_basic_map_is_empty(map->p[i]);
8395 if (is_empty < 0)
8396 return isl_bool_error;
8397 if (!is_empty)
8398 return isl_bool_false;
8400 return isl_bool_true;
8403 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8405 return map ? map->n == 0 : isl_bool_error;
8408 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8410 return set ? set->n == 0 : isl_bool_error;
8413 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8415 return isl_map_is_empty(set_to_map(set));
8418 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
8419 __isl_keep isl_map *map2)
8421 if (!map1 || !map2)
8422 return isl_bool_error;
8424 return isl_space_is_equal(map1->dim, map2->dim);
8427 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
8428 __isl_keep isl_set *set2)
8430 if (!set1 || !set2)
8431 return isl_bool_error;
8433 return isl_space_is_equal(set1->dim, set2->dim);
8436 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8438 isl_bool is_subset;
8440 if (!map1 || !map2)
8441 return isl_bool_error;
8442 is_subset = isl_map_is_subset(map1, map2);
8443 if (is_subset != isl_bool_true)
8444 return is_subset;
8445 is_subset = isl_map_is_subset(map2, map1);
8446 return is_subset;
8449 /* Is "map1" equal to "map2"?
8451 * First check if they are obviously equal.
8452 * If not, then perform a more detailed analysis.
8454 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8456 isl_bool equal;
8458 equal = isl_map_plain_is_equal(map1, map2);
8459 if (equal < 0 || equal)
8460 return equal;
8461 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8464 isl_bool isl_basic_map_is_strict_subset(
8465 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8467 isl_bool is_subset;
8469 if (!bmap1 || !bmap2)
8470 return isl_bool_error;
8471 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8472 if (is_subset != isl_bool_true)
8473 return is_subset;
8474 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8475 return isl_bool_not(is_subset);
8478 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8479 __isl_keep isl_map *map2)
8481 isl_bool is_subset;
8483 if (!map1 || !map2)
8484 return isl_bool_error;
8485 is_subset = isl_map_is_subset(map1, map2);
8486 if (is_subset != isl_bool_true)
8487 return is_subset;
8488 is_subset = isl_map_is_subset(map2, map1);
8489 return isl_bool_not(is_subset);
8492 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8493 __isl_keep isl_set *set2)
8495 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8498 /* Is "bmap" obviously equal to the universe with the same space?
8500 * That is, does it not have any constraints?
8502 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8504 if (!bmap)
8505 return isl_bool_error;
8506 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8509 /* Is "bset" obviously equal to the universe with the same space?
8511 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8513 return isl_basic_map_plain_is_universe(bset);
8516 /* If "c" does not involve any existentially quantified variables,
8517 * then set *univ to false and abort
8519 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8521 isl_bool *univ = user;
8522 unsigned n;
8524 n = isl_constraint_dim(c, isl_dim_div);
8525 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8526 isl_constraint_free(c);
8527 if (*univ < 0 || !*univ)
8528 return isl_stat_error;
8529 return isl_stat_ok;
8532 /* Is "bmap" equal to the universe with the same space?
8534 * First check if it is obviously equal to the universe.
8535 * If not and if there are any constraints not involving
8536 * existentially quantified variables, then it is certainly
8537 * not equal to the universe.
8538 * Otherwise, check if the universe is a subset of "bmap".
8540 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8542 isl_bool univ;
8543 isl_basic_map *test;
8545 univ = isl_basic_map_plain_is_universe(bmap);
8546 if (univ < 0 || univ)
8547 return univ;
8548 if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8549 return isl_bool_false;
8550 univ = isl_bool_true;
8551 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8552 univ)
8553 return isl_bool_error;
8554 if (univ < 0 || !univ)
8555 return univ;
8556 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8557 univ = isl_basic_map_is_subset(test, bmap);
8558 isl_basic_map_free(test);
8559 return univ;
8562 /* Is "bset" equal to the universe with the same space?
8564 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8566 return isl_basic_map_is_universe(bset);
8569 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8571 int i;
8573 if (!map)
8574 return isl_bool_error;
8576 for (i = 0; i < map->n; ++i) {
8577 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8578 if (r < 0 || r)
8579 return r;
8582 return isl_bool_false;
8585 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8587 return isl_map_plain_is_universe(set_to_map(set));
8590 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8592 struct isl_basic_set *bset = NULL;
8593 struct isl_vec *sample = NULL;
8594 isl_bool empty, non_empty;
8596 if (!bmap)
8597 return isl_bool_error;
8599 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8600 return isl_bool_true;
8602 if (isl_basic_map_plain_is_universe(bmap))
8603 return isl_bool_false;
8605 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8606 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8607 copy = isl_basic_map_remove_redundancies(copy);
8608 empty = isl_basic_map_plain_is_empty(copy);
8609 isl_basic_map_free(copy);
8610 return empty;
8613 non_empty = isl_basic_map_plain_is_non_empty(bmap);
8614 if (non_empty < 0)
8615 return isl_bool_error;
8616 if (non_empty)
8617 return isl_bool_false;
8618 isl_vec_free(bmap->sample);
8619 bmap->sample = NULL;
8620 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8621 if (!bset)
8622 return isl_bool_error;
8623 sample = isl_basic_set_sample_vec(bset);
8624 if (!sample)
8625 return isl_bool_error;
8626 empty = sample->size == 0;
8627 isl_vec_free(bmap->sample);
8628 bmap->sample = sample;
8629 if (empty)
8630 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8632 return empty;
8635 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8637 if (!bmap)
8638 return isl_bool_error;
8639 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8642 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8644 if (!bset)
8645 return isl_bool_error;
8646 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8649 /* Is "bmap" known to be non-empty?
8651 * That is, is the cached sample still valid?
8653 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8655 unsigned total;
8657 if (!bmap)
8658 return isl_bool_error;
8659 if (!bmap->sample)
8660 return isl_bool_false;
8661 total = 1 + isl_basic_map_total_dim(bmap);
8662 if (bmap->sample->size != total)
8663 return isl_bool_false;
8664 return isl_basic_map_contains(bmap, bmap->sample);
8667 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8669 return isl_basic_map_is_empty(bset_to_bmap(bset));
8672 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
8673 __isl_take isl_basic_map *bmap2)
8675 struct isl_map *map;
8676 if (!bmap1 || !bmap2)
8677 goto error;
8679 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8681 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8682 if (!map)
8683 goto error;
8684 map = isl_map_add_basic_map(map, bmap1);
8685 map = isl_map_add_basic_map(map, bmap2);
8686 return map;
8687 error:
8688 isl_basic_map_free(bmap1);
8689 isl_basic_map_free(bmap2);
8690 return NULL;
8693 struct isl_set *isl_basic_set_union(
8694 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8696 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8697 bset_to_bmap(bset2)));
8700 /* Order divs such that any div only depends on previous divs */
8701 __isl_give isl_basic_map *isl_basic_map_order_divs(
8702 __isl_take isl_basic_map *bmap)
8704 int i;
8705 unsigned off;
8707 if (!bmap)
8708 return NULL;
8710 off = isl_space_dim(bmap->dim, isl_dim_all);
8712 for (i = 0; i < bmap->n_div; ++i) {
8713 int pos;
8714 if (isl_int_is_zero(bmap->div[i][0]))
8715 continue;
8716 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8717 bmap->n_div-i);
8718 if (pos == -1)
8719 continue;
8720 if (pos == 0)
8721 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8722 "integer division depends on itself",
8723 return isl_basic_map_free(bmap));
8724 isl_basic_map_swap_div(bmap, i, i + pos);
8725 --i;
8727 return bmap;
8730 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8732 return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8735 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8737 int i;
8739 if (!map)
8740 return 0;
8742 for (i = 0; i < map->n; ++i) {
8743 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8744 if (!map->p[i])
8745 goto error;
8748 return map;
8749 error:
8750 isl_map_free(map);
8751 return NULL;
8754 /* Sort the local variables of "bset".
8756 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8757 __isl_take isl_basic_set *bset)
8759 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8762 /* Apply the expansion computed by isl_merge_divs.
8763 * The expansion itself is given by "exp" while the resulting
8764 * list of divs is given by "div".
8766 * Move the integer divisions of "bmap" into the right position
8767 * according to "exp" and then introduce the additional integer
8768 * divisions, adding div constraints.
8769 * The moving should be done first to avoid moving coefficients
8770 * in the definitions of the extra integer divisions.
8772 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8773 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8775 int i, j;
8776 int n_div;
8778 bmap = isl_basic_map_cow(bmap);
8779 if (!bmap || !div)
8780 goto error;
8782 if (div->n_row < bmap->n_div)
8783 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8784 "not an expansion", goto error);
8786 n_div = bmap->n_div;
8787 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8788 div->n_row - n_div, 0,
8789 2 * (div->n_row - n_div));
8791 for (i = n_div; i < div->n_row; ++i)
8792 if (isl_basic_map_alloc_div(bmap) < 0)
8793 goto error;
8795 for (j = n_div - 1; j >= 0; --j) {
8796 if (exp[j] == j)
8797 break;
8798 isl_basic_map_swap_div(bmap, j, exp[j]);
8800 j = 0;
8801 for (i = 0; i < div->n_row; ++i) {
8802 if (j < n_div && exp[j] == i) {
8803 j++;
8804 } else {
8805 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8806 if (isl_basic_map_div_is_marked_unknown(bmap, i))
8807 continue;
8808 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
8809 goto error;
8813 isl_mat_free(div);
8814 return bmap;
8815 error:
8816 isl_basic_map_free(bmap);
8817 isl_mat_free(div);
8818 return NULL;
8821 /* Apply the expansion computed by isl_merge_divs.
8822 * The expansion itself is given by "exp" while the resulting
8823 * list of divs is given by "div".
8825 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8826 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8828 return isl_basic_map_expand_divs(bset, div, exp);
8831 /* Look for a div in dst that corresponds to the div "div" in src.
8832 * The divs before "div" in src and dst are assumed to be the same.
8834 * Returns -1 if no corresponding div was found and the position
8835 * of the corresponding div in dst otherwise.
8837 static int find_div(__isl_keep isl_basic_map *dst,
8838 __isl_keep isl_basic_map *src, unsigned div)
8840 int i;
8842 unsigned total = isl_space_dim(src->dim, isl_dim_all);
8844 isl_assert(dst->ctx, div <= dst->n_div, return -1);
8845 for (i = div; i < dst->n_div; ++i)
8846 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8847 isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8848 dst->n_div - div) == -1)
8849 return i;
8850 return -1;
8853 /* Align the divs of "dst" to those of "src", adding divs from "src"
8854 * if needed. That is, make sure that the first src->n_div divs
8855 * of the result are equal to those of src.
8857 * The result is not finalized as by design it will have redundant
8858 * divs if any divs from "src" were copied.
8860 __isl_give isl_basic_map *isl_basic_map_align_divs(
8861 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8863 int i;
8864 isl_bool known;
8865 int extended;
8866 unsigned total;
8868 if (!dst || !src)
8869 return isl_basic_map_free(dst);
8871 if (src->n_div == 0)
8872 return dst;
8874 known = isl_basic_map_divs_known(src);
8875 if (known < 0)
8876 return isl_basic_map_free(dst);
8877 if (!known)
8878 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8879 "some src divs are unknown",
8880 return isl_basic_map_free(dst));
8882 src = isl_basic_map_order_divs(isl_basic_map_copy(src));
8883 if (!src)
8884 return isl_basic_map_free(dst);
8886 extended = 0;
8887 total = isl_space_dim(src->dim, isl_dim_all);
8888 for (i = 0; i < src->n_div; ++i) {
8889 int j = find_div(dst, src, i);
8890 if (j < 0) {
8891 if (!extended) {
8892 int extra = src->n_div - i;
8893 dst = isl_basic_map_cow(dst);
8894 if (!dst)
8895 goto error;
8896 dst = isl_basic_map_extend_space(dst,
8897 isl_space_copy(dst->dim),
8898 extra, 0, 2 * extra);
8899 extended = 1;
8901 j = isl_basic_map_alloc_div(dst);
8902 if (j < 0)
8903 goto error;
8904 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8905 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8906 if (isl_basic_map_add_div_constraints(dst, j) < 0)
8907 goto error;
8909 if (j != i)
8910 isl_basic_map_swap_div(dst, i, j);
8912 isl_basic_map_free(src);
8913 return dst;
8914 error:
8915 isl_basic_map_free(src);
8916 isl_basic_map_free(dst);
8917 return NULL;
8920 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
8922 int i;
8924 if (!map)
8925 return NULL;
8926 if (map->n == 0)
8927 return map;
8928 map = isl_map_compute_divs(map);
8929 map = isl_map_cow(map);
8930 if (!map)
8931 return NULL;
8933 for (i = 1; i < map->n; ++i)
8934 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8935 for (i = 1; i < map->n; ++i) {
8936 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8937 if (!map->p[i])
8938 return isl_map_free(map);
8941 map = isl_map_unmark_normalized(map);
8942 return map;
8945 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
8947 return isl_map_align_divs_internal(map);
8950 struct isl_set *isl_set_align_divs(struct isl_set *set)
8952 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
8955 /* Align the divs of the basic maps in "map" to those
8956 * of the basic maps in "list", as well as to the other basic maps in "map".
8957 * The elements in "list" are assumed to have known divs.
8959 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
8960 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
8962 int i, n;
8964 map = isl_map_compute_divs(map);
8965 map = isl_map_cow(map);
8966 if (!map || !list)
8967 return isl_map_free(map);
8968 if (map->n == 0)
8969 return map;
8971 n = isl_basic_map_list_n_basic_map(list);
8972 for (i = 0; i < n; ++i) {
8973 isl_basic_map *bmap;
8975 bmap = isl_basic_map_list_get_basic_map(list, i);
8976 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
8977 isl_basic_map_free(bmap);
8979 if (!map->p[0])
8980 return isl_map_free(map);
8982 return isl_map_align_divs_internal(map);
8985 /* Align the divs of each element of "list" to those of "bmap".
8986 * Both "bmap" and the elements of "list" are assumed to have known divs.
8988 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
8989 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
8991 int i, n;
8993 if (!list || !bmap)
8994 return isl_basic_map_list_free(list);
8996 n = isl_basic_map_list_n_basic_map(list);
8997 for (i = 0; i < n; ++i) {
8998 isl_basic_map *bmap_i;
9000 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9001 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9002 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9005 return list;
9008 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
9009 __isl_take isl_map *map)
9011 isl_bool ok;
9013 ok = isl_map_compatible_domain(map, set);
9014 if (ok < 0)
9015 goto error;
9016 if (!ok)
9017 isl_die(isl_set_get_ctx(set), isl_error_invalid,
9018 "incompatible spaces", goto error);
9019 map = isl_map_intersect_domain(map, set);
9020 set = isl_map_range(map);
9021 return set;
9022 error:
9023 isl_set_free(set);
9024 isl_map_free(map);
9025 return NULL;
9028 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9029 __isl_take isl_map *map)
9031 return isl_map_align_params_map_map_and(set, map, &set_apply);
9034 /* There is no need to cow as removing empty parts doesn't change
9035 * the meaning of the set.
9037 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9039 int i;
9041 if (!map)
9042 return NULL;
9044 for (i = map->n - 1; i >= 0; --i)
9045 map = remove_if_empty(map, i);
9047 return map;
9050 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
9052 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9055 /* Create a binary relation that maps the shared initial "pos" dimensions
9056 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9058 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9059 __isl_keep isl_basic_set *bset2, int pos)
9061 isl_basic_map *bmap1;
9062 isl_basic_map *bmap2;
9064 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9065 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9066 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9067 isl_dim_out, 0, pos);
9068 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9069 isl_dim_out, 0, pos);
9070 return isl_basic_map_range_product(bmap1, bmap2);
9073 /* Given two basic sets bset1 and bset2, compute the maximal difference
9074 * between the values of dimension pos in bset1 and those in bset2
9075 * for any common value of the parameters and dimensions preceding pos.
9077 static enum isl_lp_result basic_set_maximal_difference_at(
9078 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9079 int pos, isl_int *opt)
9081 isl_basic_map *bmap1;
9082 struct isl_ctx *ctx;
9083 struct isl_vec *obj;
9084 unsigned total;
9085 unsigned nparam;
9086 unsigned dim1;
9087 enum isl_lp_result res;
9089 if (!bset1 || !bset2)
9090 return isl_lp_error;
9092 nparam = isl_basic_set_n_param(bset1);
9093 dim1 = isl_basic_set_n_dim(bset1);
9095 bmap1 = join_initial(bset1, bset2, pos);
9096 if (!bmap1)
9097 return isl_lp_error;
9099 total = isl_basic_map_total_dim(bmap1);
9100 ctx = bmap1->ctx;
9101 obj = isl_vec_alloc(ctx, 1 + total);
9102 if (!obj)
9103 goto error;
9104 isl_seq_clr(obj->block.data, 1 + total);
9105 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9106 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9107 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9108 opt, NULL, NULL);
9109 isl_basic_map_free(bmap1);
9110 isl_vec_free(obj);
9111 return res;
9112 error:
9113 isl_basic_map_free(bmap1);
9114 return isl_lp_error;
9117 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9118 * for any common value of the parameters and dimensions preceding pos
9119 * in both basic sets, the values of dimension pos in bset1 are
9120 * smaller or larger than those in bset2.
9122 * Returns
9123 * 1 if bset1 follows bset2
9124 * -1 if bset1 precedes bset2
9125 * 0 if bset1 and bset2 are incomparable
9126 * -2 if some error occurred.
9128 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9129 __isl_keep isl_basic_set *bset2, int pos)
9131 isl_int opt;
9132 enum isl_lp_result res;
9133 int cmp;
9135 isl_int_init(opt);
9137 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9139 if (res == isl_lp_empty)
9140 cmp = 0;
9141 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9142 res == isl_lp_unbounded)
9143 cmp = 1;
9144 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9145 cmp = -1;
9146 else
9147 cmp = -2;
9149 isl_int_clear(opt);
9150 return cmp;
9153 /* Given two basic sets bset1 and bset2, check whether
9154 * for any common value of the parameters and dimensions preceding pos
9155 * there is a value of dimension pos in bset1 that is larger
9156 * than a value of the same dimension in bset2.
9158 * Return
9159 * 1 if there exists such a pair
9160 * 0 if there is no such pair, but there is a pair of equal values
9161 * -1 otherwise
9162 * -2 if some error occurred.
9164 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9165 __isl_keep isl_basic_set *bset2, int pos)
9167 isl_bool empty;
9168 isl_basic_map *bmap;
9169 unsigned dim1;
9171 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9172 bmap = join_initial(bset1, bset2, pos);
9173 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9174 isl_dim_out, dim1 - pos);
9175 empty = isl_basic_map_is_empty(bmap);
9176 if (empty < 0)
9177 goto error;
9178 if (empty) {
9179 isl_basic_map_free(bmap);
9180 return -1;
9182 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9183 isl_dim_out, dim1 - pos);
9184 empty = isl_basic_map_is_empty(bmap);
9185 if (empty < 0)
9186 goto error;
9187 isl_basic_map_free(bmap);
9188 if (empty)
9189 return 0;
9190 return 1;
9191 error:
9192 isl_basic_map_free(bmap);
9193 return -2;
9196 /* Given two sets set1 and set2, check whether
9197 * for any common value of the parameters and dimensions preceding pos
9198 * there is a value of dimension pos in set1 that is larger
9199 * than a value of the same dimension in set2.
9201 * Return
9202 * 1 if there exists such a pair
9203 * 0 if there is no such pair, but there is a pair of equal values
9204 * -1 otherwise
9205 * -2 if some error occurred.
9207 int isl_set_follows_at(__isl_keep isl_set *set1,
9208 __isl_keep isl_set *set2, int pos)
9210 int i, j;
9211 int follows = -1;
9213 if (!set1 || !set2)
9214 return -2;
9216 for (i = 0; i < set1->n; ++i)
9217 for (j = 0; j < set2->n; ++j) {
9218 int f;
9219 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9220 if (f == 1 || f == -2)
9221 return f;
9222 if (f > follows)
9223 follows = f;
9226 return follows;
9229 static isl_bool isl_basic_map_plain_has_fixed_var(
9230 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9232 int i;
9233 int d;
9234 unsigned total;
9236 if (!bmap)
9237 return isl_bool_error;
9238 total = isl_basic_map_total_dim(bmap);
9239 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9240 for (; d+1 > pos; --d)
9241 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9242 break;
9243 if (d != pos)
9244 continue;
9245 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9246 return isl_bool_false;
9247 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9248 return isl_bool_false;
9249 if (!isl_int_is_one(bmap->eq[i][1+d]))
9250 return isl_bool_false;
9251 if (val)
9252 isl_int_neg(*val, bmap->eq[i][0]);
9253 return isl_bool_true;
9255 return isl_bool_false;
9258 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9259 unsigned pos, isl_int *val)
9261 int i;
9262 isl_int v;
9263 isl_int tmp;
9264 isl_bool fixed;
9266 if (!map)
9267 return isl_bool_error;
9268 if (map->n == 0)
9269 return isl_bool_false;
9270 if (map->n == 1)
9271 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9272 isl_int_init(v);
9273 isl_int_init(tmp);
9274 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9275 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9276 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9277 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9278 fixed = isl_bool_false;
9280 if (val)
9281 isl_int_set(*val, v);
9282 isl_int_clear(tmp);
9283 isl_int_clear(v);
9284 return fixed;
9287 static isl_bool isl_basic_set_plain_has_fixed_var(
9288 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9290 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9291 pos, val);
9294 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9295 enum isl_dim_type type, unsigned pos, isl_int *val)
9297 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9298 return isl_bool_error;
9299 return isl_basic_map_plain_has_fixed_var(bmap,
9300 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9303 /* If "bmap" obviously lies on a hyperplane where the given dimension
9304 * has a fixed value, then return that value.
9305 * Otherwise return NaN.
9307 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9308 __isl_keep isl_basic_map *bmap,
9309 enum isl_dim_type type, unsigned pos)
9311 isl_ctx *ctx;
9312 isl_val *v;
9313 isl_bool fixed;
9315 if (!bmap)
9316 return NULL;
9317 ctx = isl_basic_map_get_ctx(bmap);
9318 v = isl_val_alloc(ctx);
9319 if (!v)
9320 return NULL;
9321 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9322 if (fixed < 0)
9323 return isl_val_free(v);
9324 if (fixed) {
9325 isl_int_set_si(v->d, 1);
9326 return v;
9328 isl_val_free(v);
9329 return isl_val_nan(ctx);
9332 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9333 enum isl_dim_type type, unsigned pos, isl_int *val)
9335 if (isl_map_check_range(map, type, pos, 1) < 0)
9336 return isl_bool_error;
9337 return isl_map_plain_has_fixed_var(map,
9338 map_offset(map, type) - 1 + pos, val);
9341 /* If "map" obviously lies on a hyperplane where the given dimension
9342 * has a fixed value, then return that value.
9343 * Otherwise return NaN.
9345 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9346 enum isl_dim_type type, unsigned pos)
9348 isl_ctx *ctx;
9349 isl_val *v;
9350 isl_bool fixed;
9352 if (!map)
9353 return NULL;
9354 ctx = isl_map_get_ctx(map);
9355 v = isl_val_alloc(ctx);
9356 if (!v)
9357 return NULL;
9358 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9359 if (fixed < 0)
9360 return isl_val_free(v);
9361 if (fixed) {
9362 isl_int_set_si(v->d, 1);
9363 return v;
9365 isl_val_free(v);
9366 return isl_val_nan(ctx);
9369 /* If "set" obviously lies on a hyperplane where the given dimension
9370 * has a fixed value, then return that value.
9371 * Otherwise return NaN.
9373 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
9374 enum isl_dim_type type, unsigned pos)
9376 return isl_map_plain_get_val_if_fixed(set, type, pos);
9379 /* Check if dimension dim has fixed value and if so and if val is not NULL,
9380 * then return this fixed value in *val.
9382 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
9383 unsigned dim, isl_int *val)
9385 return isl_basic_set_plain_has_fixed_var(bset,
9386 isl_basic_set_n_param(bset) + dim, val);
9389 /* Return -1 if the constraint "c1" should be sorted before "c2"
9390 * and 1 if it should be sorted after "c2".
9391 * Return 0 if the two constraints are the same (up to the constant term).
9393 * In particular, if a constraint involves later variables than another
9394 * then it is sorted after this other constraint.
9395 * uset_gist depends on constraints without existentially quantified
9396 * variables sorting first.
9398 * For constraints that have the same latest variable, those
9399 * with the same coefficient for this latest variable (first in absolute value
9400 * and then in actual value) are grouped together.
9401 * This is useful for detecting pairs of constraints that can
9402 * be chained in their printed representation.
9404 * Finally, within a group, constraints are sorted according to
9405 * their coefficients (excluding the constant term).
9407 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9409 isl_int **c1 = (isl_int **) p1;
9410 isl_int **c2 = (isl_int **) p2;
9411 int l1, l2;
9412 unsigned size = *(unsigned *) arg;
9413 int cmp;
9415 l1 = isl_seq_last_non_zero(*c1 + 1, size);
9416 l2 = isl_seq_last_non_zero(*c2 + 1, size);
9418 if (l1 != l2)
9419 return l1 - l2;
9421 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9422 if (cmp != 0)
9423 return cmp;
9424 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9425 if (cmp != 0)
9426 return -cmp;
9428 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9431 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
9432 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
9433 * and 0 if the two constraints are the same (up to the constant term).
9435 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
9436 isl_int *c1, isl_int *c2)
9438 unsigned total;
9440 if (!bmap)
9441 return -2;
9442 total = isl_basic_map_total_dim(bmap);
9443 return sort_constraint_cmp(&c1, &c2, &total);
9446 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9447 __isl_take isl_basic_map *bmap)
9449 unsigned total;
9451 if (!bmap)
9452 return NULL;
9453 if (bmap->n_ineq == 0)
9454 return bmap;
9455 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
9456 return bmap;
9457 total = isl_basic_map_total_dim(bmap);
9458 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9459 &sort_constraint_cmp, &total) < 0)
9460 return isl_basic_map_free(bmap);
9461 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
9462 return bmap;
9465 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9466 __isl_take isl_basic_set *bset)
9468 isl_basic_map *bmap = bset_to_bmap(bset);
9469 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9472 __isl_give isl_basic_map *isl_basic_map_normalize(
9473 __isl_take isl_basic_map *bmap)
9475 bmap = isl_basic_map_remove_redundancies(bmap);
9476 bmap = isl_basic_map_sort_constraints(bmap);
9477 return bmap;
9479 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9480 __isl_keep isl_basic_map *bmap2)
9482 int i, cmp;
9483 unsigned total;
9484 isl_space *space1, *space2;
9486 if (!bmap1 || !bmap2)
9487 return -1;
9489 if (bmap1 == bmap2)
9490 return 0;
9491 space1 = isl_basic_map_peek_space(bmap1);
9492 space2 = isl_basic_map_peek_space(bmap2);
9493 cmp = isl_space_cmp(space1, space2);
9494 if (cmp)
9495 return cmp;
9496 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9497 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9498 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9499 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9500 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9501 return 0;
9502 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9503 return 1;
9504 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9505 return -1;
9506 if (bmap1->n_eq != bmap2->n_eq)
9507 return bmap1->n_eq - bmap2->n_eq;
9508 if (bmap1->n_ineq != bmap2->n_ineq)
9509 return bmap1->n_ineq - bmap2->n_ineq;
9510 if (bmap1->n_div != bmap2->n_div)
9511 return bmap1->n_div - bmap2->n_div;
9512 total = isl_basic_map_total_dim(bmap1);
9513 for (i = 0; i < bmap1->n_eq; ++i) {
9514 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9515 if (cmp)
9516 return cmp;
9518 for (i = 0; i < bmap1->n_ineq; ++i) {
9519 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9520 if (cmp)
9521 return cmp;
9523 for (i = 0; i < bmap1->n_div; ++i) {
9524 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9525 if (cmp)
9526 return cmp;
9528 return 0;
9531 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9532 __isl_keep isl_basic_set *bset2)
9534 return isl_basic_map_plain_cmp(bset1, bset2);
9537 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9539 int i, cmp;
9541 if (set1 == set2)
9542 return 0;
9543 if (set1->n != set2->n)
9544 return set1->n - set2->n;
9546 for (i = 0; i < set1->n; ++i) {
9547 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9548 if (cmp)
9549 return cmp;
9552 return 0;
9555 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9556 __isl_keep isl_basic_map *bmap2)
9558 if (!bmap1 || !bmap2)
9559 return isl_bool_error;
9560 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9563 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9564 __isl_keep isl_basic_set *bset2)
9566 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9567 bset_to_bmap(bset2));
9570 static int qsort_bmap_cmp(const void *p1, const void *p2)
9572 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9573 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9575 return isl_basic_map_plain_cmp(bmap1, bmap2);
9578 /* Sort the basic maps of "map" and remove duplicate basic maps.
9580 * While removing basic maps, we make sure that the basic maps remain
9581 * sorted because isl_map_normalize expects the basic maps of the result
9582 * to be sorted.
9584 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9586 int i, j;
9588 map = isl_map_remove_empty_parts(map);
9589 if (!map)
9590 return NULL;
9591 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9592 for (i = map->n - 1; i >= 1; --i) {
9593 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9594 continue;
9595 isl_basic_map_free(map->p[i-1]);
9596 for (j = i; j < map->n; ++j)
9597 map->p[j - 1] = map->p[j];
9598 map->n--;
9601 return map;
9604 /* Remove obvious duplicates among the basic maps of "map".
9606 * Unlike isl_map_normalize, this function does not remove redundant
9607 * constraints and only removes duplicates that have exactly the same
9608 * constraints in the input. It does sort the constraints and
9609 * the basic maps to ease the detection of duplicates.
9611 * If "map" has already been normalized or if the basic maps are
9612 * disjoint, then there can be no duplicates.
9614 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9616 int i;
9617 isl_basic_map *bmap;
9619 if (!map)
9620 return NULL;
9621 if (map->n <= 1)
9622 return map;
9623 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9624 return map;
9625 for (i = 0; i < map->n; ++i) {
9626 bmap = isl_basic_map_copy(map->p[i]);
9627 bmap = isl_basic_map_sort_constraints(bmap);
9628 if (!bmap)
9629 return isl_map_free(map);
9630 isl_basic_map_free(map->p[i]);
9631 map->p[i] = bmap;
9634 map = sort_and_remove_duplicates(map);
9635 return map;
9638 /* We normalize in place, but if anything goes wrong we need
9639 * to return NULL, so we need to make sure we don't change the
9640 * meaning of any possible other copies of map.
9642 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9644 int i;
9645 struct isl_basic_map *bmap;
9647 if (!map)
9648 return NULL;
9649 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9650 return map;
9651 for (i = 0; i < map->n; ++i) {
9652 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9653 if (!bmap)
9654 goto error;
9655 isl_basic_map_free(map->p[i]);
9656 map->p[i] = bmap;
9659 map = sort_and_remove_duplicates(map);
9660 if (map)
9661 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9662 return map;
9663 error:
9664 isl_map_free(map);
9665 return NULL;
9668 struct isl_set *isl_set_normalize(struct isl_set *set)
9670 return set_from_map(isl_map_normalize(set_to_map(set)));
9673 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9674 __isl_keep isl_map *map2)
9676 int i;
9677 isl_bool equal;
9679 if (!map1 || !map2)
9680 return isl_bool_error;
9682 if (map1 == map2)
9683 return isl_bool_true;
9684 if (!isl_space_is_equal(map1->dim, map2->dim))
9685 return isl_bool_false;
9687 map1 = isl_map_copy(map1);
9688 map2 = isl_map_copy(map2);
9689 map1 = isl_map_normalize(map1);
9690 map2 = isl_map_normalize(map2);
9691 if (!map1 || !map2)
9692 goto error;
9693 equal = map1->n == map2->n;
9694 for (i = 0; equal && i < map1->n; ++i) {
9695 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9696 if (equal < 0)
9697 goto error;
9699 isl_map_free(map1);
9700 isl_map_free(map2);
9701 return equal;
9702 error:
9703 isl_map_free(map1);
9704 isl_map_free(map2);
9705 return isl_bool_error;
9708 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9709 __isl_keep isl_set *set2)
9711 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9714 /* Return the basic maps in "map" as a list.
9716 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9717 __isl_keep isl_map *map)
9719 int i;
9720 isl_ctx *ctx;
9721 isl_basic_map_list *list;
9723 if (!map)
9724 return NULL;
9725 ctx = isl_map_get_ctx(map);
9726 list = isl_basic_map_list_alloc(ctx, map->n);
9728 for (i = 0; i < map->n; ++i) {
9729 isl_basic_map *bmap;
9731 bmap = isl_basic_map_copy(map->p[i]);
9732 list = isl_basic_map_list_add(list, bmap);
9735 return list;
9738 /* Return the intersection of the elements in the non-empty list "list".
9739 * All elements are assumed to live in the same space.
9741 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9742 __isl_take isl_basic_map_list *list)
9744 int i, n;
9745 isl_basic_map *bmap;
9747 if (!list)
9748 return NULL;
9749 n = isl_basic_map_list_n_basic_map(list);
9750 if (n < 1)
9751 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9752 "expecting non-empty list", goto error);
9754 bmap = isl_basic_map_list_get_basic_map(list, 0);
9755 for (i = 1; i < n; ++i) {
9756 isl_basic_map *bmap_i;
9758 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9759 bmap = isl_basic_map_intersect(bmap, bmap_i);
9762 isl_basic_map_list_free(list);
9763 return bmap;
9764 error:
9765 isl_basic_map_list_free(list);
9766 return NULL;
9769 /* Return the intersection of the elements in the non-empty list "list".
9770 * All elements are assumed to live in the same space.
9772 __isl_give isl_basic_set *isl_basic_set_list_intersect(
9773 __isl_take isl_basic_set_list *list)
9775 return isl_basic_map_list_intersect(list);
9778 /* Return the union of the elements of "list".
9779 * The list is required to have at least one element.
9781 __isl_give isl_set *isl_basic_set_list_union(
9782 __isl_take isl_basic_set_list *list)
9784 int i, n;
9785 isl_space *space;
9786 isl_basic_set *bset;
9787 isl_set *set;
9789 if (!list)
9790 return NULL;
9791 n = isl_basic_set_list_n_basic_set(list);
9792 if (n < 1)
9793 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9794 "expecting non-empty list", goto error);
9796 bset = isl_basic_set_list_get_basic_set(list, 0);
9797 space = isl_basic_set_get_space(bset);
9798 isl_basic_set_free(bset);
9800 set = isl_set_alloc_space(space, n, 0);
9801 for (i = 0; i < n; ++i) {
9802 bset = isl_basic_set_list_get_basic_set(list, i);
9803 set = isl_set_add_basic_set(set, bset);
9806 isl_basic_set_list_free(list);
9807 return set;
9808 error:
9809 isl_basic_set_list_free(list);
9810 return NULL;
9813 /* Return the union of the elements in the non-empty list "list".
9814 * All elements are assumed to live in the same space.
9816 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9818 int i, n;
9819 isl_set *set;
9821 if (!list)
9822 return NULL;
9823 n = isl_set_list_n_set(list);
9824 if (n < 1)
9825 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9826 "expecting non-empty list", goto error);
9828 set = isl_set_list_get_set(list, 0);
9829 for (i = 1; i < n; ++i) {
9830 isl_set *set_i;
9832 set_i = isl_set_list_get_set(list, i);
9833 set = isl_set_union(set, set_i);
9836 isl_set_list_free(list);
9837 return set;
9838 error:
9839 isl_set_list_free(list);
9840 return NULL;
9843 __isl_give isl_basic_map *isl_basic_map_product(
9844 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9846 isl_space *space_result = NULL;
9847 struct isl_basic_map *bmap;
9848 unsigned in1, in2, out1, out2, nparam, total, pos;
9849 struct isl_dim_map *dim_map1, *dim_map2;
9851 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9852 goto error;
9853 space_result = isl_space_product(isl_space_copy(bmap1->dim),
9854 isl_space_copy(bmap2->dim));
9856 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9857 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9858 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9859 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9860 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9862 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9863 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9864 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9865 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9866 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9867 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9868 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9869 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9870 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9871 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9872 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9874 bmap = isl_basic_map_alloc_space(space_result,
9875 bmap1->n_div + bmap2->n_div,
9876 bmap1->n_eq + bmap2->n_eq,
9877 bmap1->n_ineq + bmap2->n_ineq);
9878 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9879 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9880 bmap = isl_basic_map_simplify(bmap);
9881 return isl_basic_map_finalize(bmap);
9882 error:
9883 isl_basic_map_free(bmap1);
9884 isl_basic_map_free(bmap2);
9885 return NULL;
9888 __isl_give isl_basic_map *isl_basic_map_flat_product(
9889 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9891 isl_basic_map *prod;
9893 prod = isl_basic_map_product(bmap1, bmap2);
9894 prod = isl_basic_map_flatten(prod);
9895 return prod;
9898 __isl_give isl_basic_set *isl_basic_set_flat_product(
9899 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9901 return isl_basic_map_flat_range_product(bset1, bset2);
9904 __isl_give isl_basic_map *isl_basic_map_domain_product(
9905 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9907 isl_space *space_result = NULL;
9908 isl_basic_map *bmap;
9909 unsigned in1, in2, out, nparam, total, pos;
9910 struct isl_dim_map *dim_map1, *dim_map2;
9912 if (!bmap1 || !bmap2)
9913 goto error;
9915 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9916 isl_space_copy(bmap2->dim));
9918 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9919 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9920 out = isl_basic_map_dim(bmap1, isl_dim_out);
9921 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9923 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9924 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9925 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9926 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9927 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9928 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9929 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9930 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9931 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9932 isl_dim_map_div(dim_map1, bmap1, pos += out);
9933 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9935 bmap = isl_basic_map_alloc_space(space_result,
9936 bmap1->n_div + bmap2->n_div,
9937 bmap1->n_eq + bmap2->n_eq,
9938 bmap1->n_ineq + bmap2->n_ineq);
9939 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9940 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9941 bmap = isl_basic_map_simplify(bmap);
9942 return isl_basic_map_finalize(bmap);
9943 error:
9944 isl_basic_map_free(bmap1);
9945 isl_basic_map_free(bmap2);
9946 return NULL;
9949 __isl_give isl_basic_map *isl_basic_map_range_product(
9950 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9952 isl_bool rational;
9953 isl_space *space_result = NULL;
9954 isl_basic_map *bmap;
9955 unsigned in, out1, out2, nparam, total, pos;
9956 struct isl_dim_map *dim_map1, *dim_map2;
9958 rational = isl_basic_map_is_rational(bmap1);
9959 if (rational >= 0 && rational)
9960 rational = isl_basic_map_is_rational(bmap2);
9961 if (!bmap1 || !bmap2 || rational < 0)
9962 goto error;
9964 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9965 goto error;
9967 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
9968 isl_space_copy(bmap2->dim));
9970 in = isl_basic_map_dim(bmap1, isl_dim_in);
9971 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9972 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9973 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9975 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
9976 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9977 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9978 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9979 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9980 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9981 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
9982 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
9983 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9984 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9985 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9987 bmap = isl_basic_map_alloc_space(space_result,
9988 bmap1->n_div + bmap2->n_div,
9989 bmap1->n_eq + bmap2->n_eq,
9990 bmap1->n_ineq + bmap2->n_ineq);
9991 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9992 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9993 if (rational)
9994 bmap = isl_basic_map_set_rational(bmap);
9995 bmap = isl_basic_map_simplify(bmap);
9996 return isl_basic_map_finalize(bmap);
9997 error:
9998 isl_basic_map_free(bmap1);
9999 isl_basic_map_free(bmap2);
10000 return NULL;
10003 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10004 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10006 isl_basic_map *prod;
10008 prod = isl_basic_map_range_product(bmap1, bmap2);
10009 prod = isl_basic_map_flatten_range(prod);
10010 return prod;
10013 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10014 * and collect the results.
10015 * The result live in the space obtained by calling "space_product"
10016 * on the spaces of "map1" and "map2".
10017 * If "remove_duplicates" is set then the result may contain duplicates
10018 * (even if the inputs do not) and so we try and remove the obvious
10019 * duplicates.
10021 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10022 __isl_take isl_map *map2,
10023 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10024 __isl_take isl_space *right),
10025 __isl_give isl_basic_map *(*basic_map_product)(
10026 __isl_take isl_basic_map *left,
10027 __isl_take isl_basic_map *right),
10028 int remove_duplicates)
10030 unsigned flags = 0;
10031 struct isl_map *result;
10032 int i, j;
10033 isl_bool m;
10035 m = isl_map_has_equal_params(map1, map2);
10036 if (m < 0)
10037 goto error;
10038 if (!m)
10039 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10040 "parameters don't match", goto error);
10042 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10043 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10044 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10046 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10047 isl_space_copy(map2->dim)),
10048 map1->n * map2->n, flags);
10049 if (!result)
10050 goto error;
10051 for (i = 0; i < map1->n; ++i)
10052 for (j = 0; j < map2->n; ++j) {
10053 struct isl_basic_map *part;
10054 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10055 isl_basic_map_copy(map2->p[j]));
10056 if (isl_basic_map_is_empty(part))
10057 isl_basic_map_free(part);
10058 else
10059 result = isl_map_add_basic_map(result, part);
10060 if (!result)
10061 goto error;
10063 if (remove_duplicates)
10064 result = isl_map_remove_obvious_duplicates(result);
10065 isl_map_free(map1);
10066 isl_map_free(map2);
10067 return result;
10068 error:
10069 isl_map_free(map1);
10070 isl_map_free(map2);
10071 return NULL;
10074 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10076 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
10077 __isl_take isl_map *map2)
10079 return map_product(map1, map2, &isl_space_product,
10080 &isl_basic_map_product, 0);
10083 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10084 __isl_take isl_map *map2)
10086 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
10089 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10091 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10092 __isl_take isl_map *map2)
10094 isl_map *prod;
10096 prod = isl_map_product(map1, map2);
10097 prod = isl_map_flatten(prod);
10098 return prod;
10101 /* Given two set A and B, construct its Cartesian product A x B.
10103 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
10105 return isl_map_range_product(set1, set2);
10108 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10109 __isl_take isl_set *set2)
10111 return isl_map_flat_range_product(set1, set2);
10114 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10116 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
10117 __isl_take isl_map *map2)
10119 return map_product(map1, map2, &isl_space_domain_product,
10120 &isl_basic_map_domain_product, 1);
10123 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10125 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
10126 __isl_take isl_map *map2)
10128 return map_product(map1, map2, &isl_space_range_product,
10129 &isl_basic_map_range_product, 1);
10132 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10133 __isl_take isl_map *map2)
10135 return isl_map_align_params_map_map_and(map1, map2,
10136 &map_domain_product_aligned);
10139 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10140 __isl_take isl_map *map2)
10142 return isl_map_align_params_map_map_and(map1, map2,
10143 &map_range_product_aligned);
10146 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10148 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10150 isl_space *space;
10151 int total1, keep1, total2, keep2;
10153 if (!map)
10154 return NULL;
10155 if (!isl_space_domain_is_wrapping(map->dim) ||
10156 !isl_space_range_is_wrapping(map->dim))
10157 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10158 "not a product", return isl_map_free(map));
10160 space = isl_map_get_space(map);
10161 total1 = isl_space_dim(space, isl_dim_in);
10162 total2 = isl_space_dim(space, isl_dim_out);
10163 space = isl_space_factor_domain(space);
10164 keep1 = isl_space_dim(space, isl_dim_in);
10165 keep2 = isl_space_dim(space, isl_dim_out);
10166 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10167 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10168 map = isl_map_reset_space(map, space);
10170 return map;
10173 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10175 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10177 isl_space *space;
10178 int total1, keep1, total2, keep2;
10180 if (!map)
10181 return NULL;
10182 if (!isl_space_domain_is_wrapping(map->dim) ||
10183 !isl_space_range_is_wrapping(map->dim))
10184 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10185 "not a product", return isl_map_free(map));
10187 space = isl_map_get_space(map);
10188 total1 = isl_space_dim(space, isl_dim_in);
10189 total2 = isl_space_dim(space, isl_dim_out);
10190 space = isl_space_factor_range(space);
10191 keep1 = isl_space_dim(space, isl_dim_in);
10192 keep2 = isl_space_dim(space, isl_dim_out);
10193 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10194 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10195 map = isl_map_reset_space(map, space);
10197 return map;
10200 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10202 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10204 isl_space *space;
10205 int total, keep;
10207 if (!map)
10208 return NULL;
10209 if (!isl_space_domain_is_wrapping(map->dim))
10210 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10211 "domain is not a product", return isl_map_free(map));
10213 space = isl_map_get_space(map);
10214 total = isl_space_dim(space, isl_dim_in);
10215 space = isl_space_domain_factor_domain(space);
10216 keep = isl_space_dim(space, isl_dim_in);
10217 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10218 map = isl_map_reset_space(map, space);
10220 return map;
10223 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10225 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10227 isl_space *space;
10228 int total, keep;
10230 if (!map)
10231 return NULL;
10232 if (!isl_space_domain_is_wrapping(map->dim))
10233 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10234 "domain is not a product", return isl_map_free(map));
10236 space = isl_map_get_space(map);
10237 total = isl_space_dim(space, isl_dim_in);
10238 space = isl_space_domain_factor_range(space);
10239 keep = isl_space_dim(space, isl_dim_in);
10240 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10241 map = isl_map_reset_space(map, space);
10243 return map;
10246 /* Given a map A -> [B -> C], extract the map A -> B.
10248 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10250 isl_space *space;
10251 int total, keep;
10253 if (!map)
10254 return NULL;
10255 if (!isl_space_range_is_wrapping(map->dim))
10256 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10257 "range is not a product", return isl_map_free(map));
10259 space = isl_map_get_space(map);
10260 total = isl_space_dim(space, isl_dim_out);
10261 space = isl_space_range_factor_domain(space);
10262 keep = isl_space_dim(space, isl_dim_out);
10263 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10264 map = isl_map_reset_space(map, space);
10266 return map;
10269 /* Given a map A -> [B -> C], extract the map A -> C.
10271 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10273 isl_space *space;
10274 int total, keep;
10276 if (!map)
10277 return NULL;
10278 if (!isl_space_range_is_wrapping(map->dim))
10279 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10280 "range is not a product", return isl_map_free(map));
10282 space = isl_map_get_space(map);
10283 total = isl_space_dim(space, isl_dim_out);
10284 space = isl_space_range_factor_range(space);
10285 keep = isl_space_dim(space, isl_dim_out);
10286 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10287 map = isl_map_reset_space(map, space);
10289 return map;
10292 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10294 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10295 __isl_take isl_map *map2)
10297 isl_map *prod;
10299 prod = isl_map_domain_product(map1, map2);
10300 prod = isl_map_flatten_domain(prod);
10301 return prod;
10304 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10306 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10307 __isl_take isl_map *map2)
10309 isl_map *prod;
10311 prod = isl_map_range_product(map1, map2);
10312 prod = isl_map_flatten_range(prod);
10313 return prod;
10316 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10318 int i;
10319 uint32_t hash = isl_hash_init();
10320 unsigned total;
10322 if (!bmap)
10323 return 0;
10324 bmap = isl_basic_map_copy(bmap);
10325 bmap = isl_basic_map_normalize(bmap);
10326 if (!bmap)
10327 return 0;
10328 total = isl_basic_map_total_dim(bmap);
10329 isl_hash_byte(hash, bmap->n_eq & 0xFF);
10330 for (i = 0; i < bmap->n_eq; ++i) {
10331 uint32_t c_hash;
10332 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
10333 isl_hash_hash(hash, c_hash);
10335 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
10336 for (i = 0; i < bmap->n_ineq; ++i) {
10337 uint32_t c_hash;
10338 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
10339 isl_hash_hash(hash, c_hash);
10341 isl_hash_byte(hash, bmap->n_div & 0xFF);
10342 for (i = 0; i < bmap->n_div; ++i) {
10343 uint32_t c_hash;
10344 if (isl_int_is_zero(bmap->div[i][0]))
10345 continue;
10346 isl_hash_byte(hash, i & 0xFF);
10347 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
10348 isl_hash_hash(hash, c_hash);
10350 isl_basic_map_free(bmap);
10351 return hash;
10354 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
10356 return isl_basic_map_get_hash(bset_to_bmap(bset));
10359 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
10361 int i;
10362 uint32_t hash;
10364 if (!map)
10365 return 0;
10366 map = isl_map_copy(map);
10367 map = isl_map_normalize(map);
10368 if (!map)
10369 return 0;
10371 hash = isl_hash_init();
10372 for (i = 0; i < map->n; ++i) {
10373 uint32_t bmap_hash;
10374 bmap_hash = isl_basic_map_get_hash(map->p[i]);
10375 isl_hash_hash(hash, bmap_hash);
10378 isl_map_free(map);
10380 return hash;
10383 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
10385 return isl_map_get_hash(set_to_map(set));
10388 /* Return the number of basic maps in the (current) representation of "map".
10390 int isl_map_n_basic_map(__isl_keep isl_map *map)
10392 return map ? map->n : 0;
10395 int isl_set_n_basic_set(__isl_keep isl_set *set)
10397 return set ? set->n : 0;
10400 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
10401 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10403 int i;
10405 if (!map)
10406 return isl_stat_error;
10408 for (i = 0; i < map->n; ++i)
10409 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10410 return isl_stat_error;
10412 return isl_stat_ok;
10415 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10416 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10418 int i;
10420 if (!set)
10421 return isl_stat_error;
10423 for (i = 0; i < set->n; ++i)
10424 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10425 return isl_stat_error;
10427 return isl_stat_ok;
10430 /* Return a list of basic sets, the union of which is equal to "set".
10432 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10433 __isl_keep isl_set *set)
10435 int i;
10436 isl_basic_set_list *list;
10438 if (!set)
10439 return NULL;
10441 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10442 for (i = 0; i < set->n; ++i) {
10443 isl_basic_set *bset;
10445 bset = isl_basic_set_copy(set->p[i]);
10446 list = isl_basic_set_list_add(list, bset);
10449 return list;
10452 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10454 isl_space *space;
10456 if (!bset)
10457 return NULL;
10459 bset = isl_basic_set_cow(bset);
10460 if (!bset)
10461 return NULL;
10463 space = isl_basic_set_get_space(bset);
10464 space = isl_space_lift(space, bset->n_div);
10465 if (!space)
10466 goto error;
10467 isl_space_free(bset->dim);
10468 bset->dim = space;
10469 bset->extra -= bset->n_div;
10470 bset->n_div = 0;
10472 bset = isl_basic_set_finalize(bset);
10474 return bset;
10475 error:
10476 isl_basic_set_free(bset);
10477 return NULL;
10480 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10482 int i;
10483 isl_space *space;
10484 unsigned n_div;
10486 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10488 if (!set)
10489 return NULL;
10491 set = isl_set_cow(set);
10492 if (!set)
10493 return NULL;
10495 n_div = set->p[0]->n_div;
10496 space = isl_set_get_space(set);
10497 space = isl_space_lift(space, n_div);
10498 if (!space)
10499 goto error;
10500 isl_space_free(set->dim);
10501 set->dim = space;
10503 for (i = 0; i < set->n; ++i) {
10504 set->p[i] = isl_basic_set_lift(set->p[i]);
10505 if (!set->p[i])
10506 goto error;
10509 return set;
10510 error:
10511 isl_set_free(set);
10512 return NULL;
10515 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10517 unsigned dim;
10518 int size = 0;
10520 if (!bset)
10521 return -1;
10523 dim = isl_basic_set_total_dim(bset);
10524 size += bset->n_eq * (1 + dim);
10525 size += bset->n_ineq * (1 + dim);
10526 size += bset->n_div * (2 + dim);
10528 return size;
10531 int isl_set_size(__isl_keep isl_set *set)
10533 int i;
10534 int size = 0;
10536 if (!set)
10537 return -1;
10539 for (i = 0; i < set->n; ++i)
10540 size += isl_basic_set_size(set->p[i]);
10542 return size;
10545 /* Check if there is any lower bound (if lower == 0) and/or upper
10546 * bound (if upper == 0) on the specified dim.
10548 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10549 enum isl_dim_type type, unsigned pos, int lower, int upper)
10551 int i;
10553 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10554 return isl_bool_error;
10556 pos += isl_basic_map_offset(bmap, type);
10558 for (i = 0; i < bmap->n_div; ++i) {
10559 if (isl_int_is_zero(bmap->div[i][0]))
10560 continue;
10561 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10562 return isl_bool_true;
10565 for (i = 0; i < bmap->n_eq; ++i)
10566 if (!isl_int_is_zero(bmap->eq[i][pos]))
10567 return isl_bool_true;
10569 for (i = 0; i < bmap->n_ineq; ++i) {
10570 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10571 if (sgn > 0)
10572 lower = 1;
10573 if (sgn < 0)
10574 upper = 1;
10577 return lower && upper;
10580 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10581 enum isl_dim_type type, unsigned pos)
10583 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10586 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10587 enum isl_dim_type type, unsigned pos)
10589 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10592 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10593 enum isl_dim_type type, unsigned pos)
10595 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10598 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10599 enum isl_dim_type type, unsigned pos)
10601 int i;
10603 if (!map)
10604 return isl_bool_error;
10606 for (i = 0; i < map->n; ++i) {
10607 isl_bool bounded;
10608 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10609 if (bounded < 0 || !bounded)
10610 return bounded;
10613 return isl_bool_true;
10616 /* Return true if the specified dim is involved in both an upper bound
10617 * and a lower bound.
10619 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10620 enum isl_dim_type type, unsigned pos)
10622 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10625 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10627 static isl_bool has_any_bound(__isl_keep isl_map *map,
10628 enum isl_dim_type type, unsigned pos,
10629 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10630 enum isl_dim_type type, unsigned pos))
10632 int i;
10634 if (!map)
10635 return isl_bool_error;
10637 for (i = 0; i < map->n; ++i) {
10638 isl_bool bounded;
10639 bounded = fn(map->p[i], type, pos);
10640 if (bounded < 0 || bounded)
10641 return bounded;
10644 return isl_bool_false;
10647 /* Return 1 if the specified dim is involved in any lower bound.
10649 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10650 enum isl_dim_type type, unsigned pos)
10652 return has_any_bound(set, type, pos,
10653 &isl_basic_map_dim_has_lower_bound);
10656 /* Return 1 if the specified dim is involved in any upper bound.
10658 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10659 enum isl_dim_type type, unsigned pos)
10661 return has_any_bound(set, type, pos,
10662 &isl_basic_map_dim_has_upper_bound);
10665 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10667 static isl_bool has_bound(__isl_keep isl_map *map,
10668 enum isl_dim_type type, unsigned pos,
10669 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10670 enum isl_dim_type type, unsigned pos))
10672 int i;
10674 if (!map)
10675 return isl_bool_error;
10677 for (i = 0; i < map->n; ++i) {
10678 isl_bool bounded;
10679 bounded = fn(map->p[i], type, pos);
10680 if (bounded < 0 || !bounded)
10681 return bounded;
10684 return isl_bool_true;
10687 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10689 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10690 enum isl_dim_type type, unsigned pos)
10692 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10695 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10697 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10698 enum isl_dim_type type, unsigned pos)
10700 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10703 /* For each of the "n" variables starting at "first", determine
10704 * the sign of the variable and put the results in the first "n"
10705 * elements of the array "signs".
10706 * Sign
10707 * 1 means that the variable is non-negative
10708 * -1 means that the variable is non-positive
10709 * 0 means the variable attains both positive and negative values.
10711 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10712 unsigned first, unsigned n, int *signs)
10714 isl_vec *bound = NULL;
10715 struct isl_tab *tab = NULL;
10716 struct isl_tab_undo *snap;
10717 int i;
10719 if (!bset || !signs)
10720 return isl_stat_error;
10722 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10723 tab = isl_tab_from_basic_set(bset, 0);
10724 if (!bound || !tab)
10725 goto error;
10727 isl_seq_clr(bound->el, bound->size);
10728 isl_int_set_si(bound->el[0], -1);
10730 snap = isl_tab_snap(tab);
10731 for (i = 0; i < n; ++i) {
10732 int empty;
10734 isl_int_set_si(bound->el[1 + first + i], -1);
10735 if (isl_tab_add_ineq(tab, bound->el) < 0)
10736 goto error;
10737 empty = tab->empty;
10738 isl_int_set_si(bound->el[1 + first + i], 0);
10739 if (isl_tab_rollback(tab, snap) < 0)
10740 goto error;
10742 if (empty) {
10743 signs[i] = 1;
10744 continue;
10747 isl_int_set_si(bound->el[1 + first + i], 1);
10748 if (isl_tab_add_ineq(tab, bound->el) < 0)
10749 goto error;
10750 empty = tab->empty;
10751 isl_int_set_si(bound->el[1 + first + i], 0);
10752 if (isl_tab_rollback(tab, snap) < 0)
10753 goto error;
10755 signs[i] = empty ? -1 : 0;
10758 isl_tab_free(tab);
10759 isl_vec_free(bound);
10760 return isl_stat_ok;
10761 error:
10762 isl_tab_free(tab);
10763 isl_vec_free(bound);
10764 return isl_stat_error;
10767 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10768 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10770 if (!bset || !signs)
10771 return isl_stat_error;
10772 isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
10773 return isl_stat_error);
10775 first += pos(bset->dim, type) - 1;
10776 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10779 /* Is it possible for the integer division "div" to depend (possibly
10780 * indirectly) on any output dimensions?
10782 * If the div is undefined, then we conservatively assume that it
10783 * may depend on them.
10784 * Otherwise, we check if it actually depends on them or on any integer
10785 * divisions that may depend on them.
10787 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10789 int i;
10790 unsigned n_out, o_out;
10791 unsigned n_div, o_div;
10793 if (isl_int_is_zero(bmap->div[div][0]))
10794 return isl_bool_true;
10796 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10797 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10799 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10800 return isl_bool_true;
10802 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10803 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10805 for (i = 0; i < n_div; ++i) {
10806 isl_bool may_involve;
10808 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10809 continue;
10810 may_involve = div_may_involve_output(bmap, i);
10811 if (may_involve < 0 || may_involve)
10812 return may_involve;
10815 return isl_bool_false;
10818 /* Return the first integer division of "bmap" in the range
10819 * [first, first + n[ that may depend on any output dimensions and
10820 * that has a non-zero coefficient in "c" (where the first coefficient
10821 * in "c" corresponds to integer division "first").
10823 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10824 isl_int *c, int first, int n)
10826 int k;
10828 if (!bmap)
10829 return -1;
10831 for (k = first; k < first + n; ++k) {
10832 isl_bool may_involve;
10834 if (isl_int_is_zero(c[k]))
10835 continue;
10836 may_involve = div_may_involve_output(bmap, k);
10837 if (may_involve < 0)
10838 return -1;
10839 if (may_involve)
10840 return k;
10843 return first + n;
10846 /* Look for a pair of inequality constraints in "bmap" of the form
10848 * -l + i >= 0 or i >= l
10849 * and
10850 * n + l - i >= 0 or i <= l + n
10852 * with n < "m" and i the output dimension at position "pos".
10853 * (Note that n >= 0 as otherwise the two constraints would conflict.)
10854 * Furthermore, "l" is only allowed to involve parameters, input dimensions
10855 * and earlier output dimensions, as well as integer divisions that do
10856 * not involve any of the output dimensions.
10858 * Return the index of the first inequality constraint or bmap->n_ineq
10859 * if no such pair can be found.
10861 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10862 int pos, isl_int m)
10864 int i, j;
10865 isl_ctx *ctx;
10866 unsigned total;
10867 unsigned n_div, o_div;
10868 unsigned n_out, o_out;
10869 int less;
10871 if (!bmap)
10872 return -1;
10874 ctx = isl_basic_map_get_ctx(bmap);
10875 total = isl_basic_map_total_dim(bmap);
10876 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10877 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10878 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10879 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10880 for (i = 0; i < bmap->n_ineq; ++i) {
10881 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
10882 continue;
10883 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
10884 n_out - (pos + 1)) != -1)
10885 continue;
10886 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
10887 0, n_div) < n_div)
10888 continue;
10889 for (j = i + 1; j < bmap->n_ineq; ++j) {
10890 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
10891 ctx->one))
10892 continue;
10893 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
10894 bmap->ineq[j] + 1, total))
10895 continue;
10896 break;
10898 if (j >= bmap->n_ineq)
10899 continue;
10900 isl_int_add(bmap->ineq[i][0],
10901 bmap->ineq[i][0], bmap->ineq[j][0]);
10902 less = isl_int_abs_lt(bmap->ineq[i][0], m);
10903 isl_int_sub(bmap->ineq[i][0],
10904 bmap->ineq[i][0], bmap->ineq[j][0]);
10905 if (!less)
10906 continue;
10907 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
10908 return i;
10909 else
10910 return j;
10913 return bmap->n_ineq;
10916 /* Return the index of the equality of "bmap" that defines
10917 * the output dimension "pos" in terms of earlier dimensions.
10918 * The equality may also involve integer divisions, as long
10919 * as those integer divisions are defined in terms of
10920 * parameters or input dimensions.
10921 * In this case, *div is set to the number of integer divisions and
10922 * *ineq is set to the number of inequality constraints (provided
10923 * div and ineq are not NULL).
10925 * The equality may also involve a single integer division involving
10926 * the output dimensions (typically only output dimension "pos") as
10927 * long as the coefficient of output dimension "pos" is 1 or -1 and
10928 * there is a pair of constraints i >= l and i <= l + n, with i referring
10929 * to output dimension "pos", l an expression involving only earlier
10930 * dimensions and n smaller than the coefficient of the integer division
10931 * in the equality. In this case, the output dimension can be defined
10932 * in terms of a modulo expression that does not involve the integer division.
10933 * *div is then set to this single integer division and
10934 * *ineq is set to the index of constraint i >= l.
10936 * Return bmap->n_eq if there is no such equality.
10937 * Return -1 on error.
10939 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
10940 int pos, int *div, int *ineq)
10942 int j, k, l;
10943 unsigned n_out, o_out;
10944 unsigned n_div, o_div;
10946 if (!bmap)
10947 return -1;
10949 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10950 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10951 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10952 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10954 if (ineq)
10955 *ineq = bmap->n_ineq;
10956 if (div)
10957 *div = n_div;
10958 for (j = 0; j < bmap->n_eq; ++j) {
10959 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
10960 continue;
10961 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
10962 n_out - (pos + 1)) != -1)
10963 continue;
10964 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10965 0, n_div);
10966 if (k >= n_div)
10967 return j;
10968 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
10969 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
10970 continue;
10971 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10972 k + 1, n_div - (k+1)) < n_div)
10973 continue;
10974 l = find_modulo_constraint_pair(bmap, pos,
10975 bmap->eq[j][o_div + k]);
10976 if (l < 0)
10977 return -1;
10978 if (l >= bmap->n_ineq)
10979 continue;
10980 if (div)
10981 *div = k;
10982 if (ineq)
10983 *ineq = l;
10984 return j;
10987 return bmap->n_eq;
10990 /* Check if the given basic map is obviously single-valued.
10991 * In particular, for each output dimension, check that there is
10992 * an equality that defines the output dimension in terms of
10993 * earlier dimensions.
10995 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
10997 int i;
10998 unsigned n_out;
11000 if (!bmap)
11001 return isl_bool_error;
11003 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11005 for (i = 0; i < n_out; ++i) {
11006 int eq;
11008 eq = isl_basic_map_output_defining_equality(bmap, i,
11009 NULL, NULL);
11010 if (eq < 0)
11011 return isl_bool_error;
11012 if (eq >= bmap->n_eq)
11013 return isl_bool_false;
11016 return isl_bool_true;
11019 /* Check if the given basic map is single-valued.
11020 * We simply compute
11022 * M \circ M^-1
11024 * and check if the result is a subset of the identity mapping.
11026 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11028 isl_space *space;
11029 isl_basic_map *test;
11030 isl_basic_map *id;
11031 isl_bool sv;
11033 sv = isl_basic_map_plain_is_single_valued(bmap);
11034 if (sv < 0 || sv)
11035 return sv;
11037 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11038 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11040 space = isl_basic_map_get_space(bmap);
11041 space = isl_space_map_from_set(isl_space_range(space));
11042 id = isl_basic_map_identity(space);
11044 sv = isl_basic_map_is_subset(test, id);
11046 isl_basic_map_free(test);
11047 isl_basic_map_free(id);
11049 return sv;
11052 /* Check if the given map is obviously single-valued.
11054 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11056 if (!map)
11057 return isl_bool_error;
11058 if (map->n == 0)
11059 return isl_bool_true;
11060 if (map->n >= 2)
11061 return isl_bool_false;
11063 return isl_basic_map_plain_is_single_valued(map->p[0]);
11066 /* Check if the given map is single-valued.
11067 * We simply compute
11069 * M \circ M^-1
11071 * and check if the result is a subset of the identity mapping.
11073 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11075 isl_space *dim;
11076 isl_map *test;
11077 isl_map *id;
11078 isl_bool sv;
11080 sv = isl_map_plain_is_single_valued(map);
11081 if (sv < 0 || sv)
11082 return sv;
11084 test = isl_map_reverse(isl_map_copy(map));
11085 test = isl_map_apply_range(test, isl_map_copy(map));
11087 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11088 id = isl_map_identity(dim);
11090 sv = isl_map_is_subset(test, id);
11092 isl_map_free(test);
11093 isl_map_free(id);
11095 return sv;
11098 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11100 isl_bool in;
11102 map = isl_map_copy(map);
11103 map = isl_map_reverse(map);
11104 in = isl_map_is_single_valued(map);
11105 isl_map_free(map);
11107 return in;
11110 /* Check if the given map is obviously injective.
11112 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11114 isl_bool in;
11116 map = isl_map_copy(map);
11117 map = isl_map_reverse(map);
11118 in = isl_map_plain_is_single_valued(map);
11119 isl_map_free(map);
11121 return in;
11124 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11126 isl_bool sv;
11128 sv = isl_map_is_single_valued(map);
11129 if (sv < 0 || !sv)
11130 return sv;
11132 return isl_map_is_injective(map);
11135 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11137 return isl_map_is_single_valued(set_to_map(set));
11140 /* Does "map" only map elements to themselves?
11142 * If the domain and range spaces are different, then "map"
11143 * is considered not to be an identity relation, even if it is empty.
11144 * Otherwise, construct the maximal identity relation and
11145 * check whether "map" is a subset of this relation.
11147 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11149 isl_space *space;
11150 isl_map *id;
11151 isl_bool equal, is_identity;
11153 space = isl_map_get_space(map);
11154 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
11155 isl_space_free(space);
11156 if (equal < 0 || !equal)
11157 return equal;
11159 id = isl_map_identity(isl_map_get_space(map));
11160 is_identity = isl_map_is_subset(map, id);
11161 isl_map_free(id);
11163 return is_identity;
11166 int isl_map_is_translation(__isl_keep isl_map *map)
11168 int ok;
11169 isl_set *delta;
11171 delta = isl_map_deltas(isl_map_copy(map));
11172 ok = isl_set_is_singleton(delta);
11173 isl_set_free(delta);
11175 return ok;
11178 static int unique(isl_int *p, unsigned pos, unsigned len)
11180 if (isl_seq_first_non_zero(p, pos) != -1)
11181 return 0;
11182 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11183 return 0;
11184 return 1;
11187 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11189 int i, j;
11190 unsigned nvar;
11191 unsigned ovar;
11193 if (!bset)
11194 return isl_bool_error;
11196 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
11197 return isl_bool_false;
11199 nvar = isl_basic_set_dim(bset, isl_dim_set);
11200 ovar = isl_space_offset(bset->dim, isl_dim_set);
11201 for (j = 0; j < nvar; ++j) {
11202 int lower = 0, upper = 0;
11203 for (i = 0; i < bset->n_eq; ++i) {
11204 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11205 continue;
11206 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11207 return isl_bool_false;
11208 break;
11210 if (i < bset->n_eq)
11211 continue;
11212 for (i = 0; i < bset->n_ineq; ++i) {
11213 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11214 continue;
11215 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11216 return isl_bool_false;
11217 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11218 lower = 1;
11219 else
11220 upper = 1;
11222 if (!lower || !upper)
11223 return isl_bool_false;
11226 return isl_bool_true;
11229 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11231 if (!set)
11232 return isl_bool_error;
11233 if (set->n != 1)
11234 return isl_bool_false;
11236 return isl_basic_set_is_box(set->p[0]);
11239 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11241 if (!bset)
11242 return isl_bool_error;
11244 return isl_space_is_wrapping(bset->dim);
11247 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11249 if (!set)
11250 return isl_bool_error;
11252 return isl_space_is_wrapping(set->dim);
11255 /* Modify the space of "map" through a call to "change".
11256 * If "can_change" is set (not NULL), then first call it to check
11257 * if the modification is allowed, printing the error message "cannot_change"
11258 * if it is not.
11260 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11261 isl_bool (*can_change)(__isl_keep isl_map *map),
11262 const char *cannot_change,
11263 __isl_give isl_space *(*change)(__isl_take isl_space *space))
11265 isl_bool ok;
11266 isl_space *space;
11268 if (!map)
11269 return NULL;
11271 ok = can_change ? can_change(map) : isl_bool_true;
11272 if (ok < 0)
11273 return isl_map_free(map);
11274 if (!ok)
11275 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11276 return isl_map_free(map));
11278 space = change(isl_map_get_space(map));
11279 map = isl_map_reset_space(map, space);
11281 return map;
11284 /* Is the domain of "map" a wrapped relation?
11286 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11288 if (!map)
11289 return isl_bool_error;
11291 return isl_space_domain_is_wrapping(map->dim);
11294 /* Does "map" have a wrapped relation in both domain and range?
11296 isl_bool isl_map_is_product(__isl_keep isl_map *map)
11298 return isl_space_is_product(isl_map_peek_space(map));
11301 /* Is the range of "map" a wrapped relation?
11303 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
11305 if (!map)
11306 return isl_bool_error;
11308 return isl_space_range_is_wrapping(map->dim);
11311 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
11313 bmap = isl_basic_map_cow(bmap);
11314 if (!bmap)
11315 return NULL;
11317 bmap->dim = isl_space_wrap(bmap->dim);
11318 if (!bmap->dim)
11319 goto error;
11321 bmap = isl_basic_map_finalize(bmap);
11323 return bset_from_bmap(bmap);
11324 error:
11325 isl_basic_map_free(bmap);
11326 return NULL;
11329 /* Given a map A -> B, return the set (A -> B).
11331 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
11333 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
11336 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
11338 bset = isl_basic_set_cow(bset);
11339 if (!bset)
11340 return NULL;
11342 bset->dim = isl_space_unwrap(bset->dim);
11343 if (!bset->dim)
11344 goto error;
11346 bset = isl_basic_set_finalize(bset);
11348 return bset_to_bmap(bset);
11349 error:
11350 isl_basic_set_free(bset);
11351 return NULL;
11354 /* Given a set (A -> B), return the map A -> B.
11355 * Error out if "set" is not of the form (A -> B).
11357 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
11359 return isl_map_change_space(set, &isl_set_is_wrapping,
11360 "not a wrapping set", &isl_space_unwrap);
11363 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
11364 enum isl_dim_type type)
11366 if (!bmap)
11367 return NULL;
11369 if (!isl_space_is_named_or_nested(bmap->dim, type))
11370 return bmap;
11372 bmap = isl_basic_map_cow(bmap);
11373 if (!bmap)
11374 return NULL;
11376 bmap->dim = isl_space_reset(bmap->dim, type);
11377 if (!bmap->dim)
11378 goto error;
11380 bmap = isl_basic_map_finalize(bmap);
11382 return bmap;
11383 error:
11384 isl_basic_map_free(bmap);
11385 return NULL;
11388 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
11389 enum isl_dim_type type)
11391 int i;
11393 if (!map)
11394 return NULL;
11396 if (!isl_space_is_named_or_nested(map->dim, type))
11397 return map;
11399 map = isl_map_cow(map);
11400 if (!map)
11401 return NULL;
11403 for (i = 0; i < map->n; ++i) {
11404 map->p[i] = isl_basic_map_reset(map->p[i], type);
11405 if (!map->p[i])
11406 goto error;
11408 map->dim = isl_space_reset(map->dim, type);
11409 if (!map->dim)
11410 goto error;
11412 return map;
11413 error:
11414 isl_map_free(map);
11415 return NULL;
11418 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11420 if (!bmap)
11421 return NULL;
11423 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11424 return bmap;
11426 bmap = isl_basic_map_cow(bmap);
11427 if (!bmap)
11428 return NULL;
11430 bmap->dim = isl_space_flatten(bmap->dim);
11431 if (!bmap->dim)
11432 goto error;
11434 bmap = isl_basic_map_finalize(bmap);
11436 return bmap;
11437 error:
11438 isl_basic_map_free(bmap);
11439 return NULL;
11442 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11444 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11447 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11448 __isl_take isl_basic_map *bmap)
11450 if (!bmap)
11451 return NULL;
11453 if (!bmap->dim->nested[0])
11454 return bmap;
11456 bmap = isl_basic_map_cow(bmap);
11457 if (!bmap)
11458 return NULL;
11460 bmap->dim = isl_space_flatten_domain(bmap->dim);
11461 if (!bmap->dim)
11462 goto error;
11464 bmap = isl_basic_map_finalize(bmap);
11466 return bmap;
11467 error:
11468 isl_basic_map_free(bmap);
11469 return NULL;
11472 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11473 __isl_take isl_basic_map *bmap)
11475 if (!bmap)
11476 return NULL;
11478 if (!bmap->dim->nested[1])
11479 return bmap;
11481 bmap = isl_basic_map_cow(bmap);
11482 if (!bmap)
11483 return NULL;
11485 bmap->dim = isl_space_flatten_range(bmap->dim);
11486 if (!bmap->dim)
11487 goto error;
11489 bmap = isl_basic_map_finalize(bmap);
11491 return bmap;
11492 error:
11493 isl_basic_map_free(bmap);
11494 return NULL;
11497 /* Remove any internal structure from the spaces of domain and range of "map".
11499 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11501 if (!map)
11502 return NULL;
11504 if (!map->dim->nested[0] && !map->dim->nested[1])
11505 return map;
11507 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11510 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11512 return set_from_map(isl_map_flatten(set_to_map(set)));
11515 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11517 isl_space *space, *flat_space;
11518 isl_map *map;
11520 space = isl_set_get_space(set);
11521 flat_space = isl_space_flatten(isl_space_copy(space));
11522 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
11523 flat_space));
11524 map = isl_map_intersect_domain(map, set);
11526 return map;
11529 /* Remove any internal structure from the space of the domain of "map".
11531 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11533 if (!map)
11534 return NULL;
11536 if (!map->dim->nested[0])
11537 return map;
11539 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11542 /* Remove any internal structure from the space of the range of "map".
11544 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11546 if (!map)
11547 return NULL;
11549 if (!map->dim->nested[1])
11550 return map;
11552 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11555 /* Reorder the dimensions of "bmap" according to the given dim_map
11556 * and set the dimension specification to "space" and
11557 * perform Gaussian elimination on the result.
11559 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11560 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
11562 isl_basic_map *res;
11563 unsigned flags;
11564 unsigned n_div;
11566 if (!bmap || !space || !dim_map)
11567 goto error;
11569 flags = bmap->flags;
11570 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11571 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
11572 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11573 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11574 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
11575 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11576 if (res)
11577 res->flags = flags;
11578 res = isl_basic_map_gauss(res, NULL);
11579 res = isl_basic_map_finalize(res);
11580 return res;
11581 error:
11582 free(dim_map);
11583 isl_basic_map_free(bmap);
11584 isl_space_free(space);
11585 return NULL;
11588 /* Reorder the dimensions of "map" according to given reordering.
11590 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11591 __isl_take isl_reordering *r)
11593 int i;
11594 struct isl_dim_map *dim_map;
11596 map = isl_map_cow(map);
11597 dim_map = isl_dim_map_from_reordering(r);
11598 if (!map || !r || !dim_map)
11599 goto error;
11601 for (i = 0; i < map->n; ++i) {
11602 struct isl_dim_map *dim_map_i;
11603 isl_space *space;
11605 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11607 space = isl_reordering_get_space(r);
11608 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
11610 if (!map->p[i])
11611 goto error;
11614 map = isl_map_reset_space(map, isl_reordering_get_space(r));
11615 map = isl_map_unmark_normalized(map);
11617 isl_reordering_free(r);
11618 free(dim_map);
11619 return map;
11620 error:
11621 free(dim_map);
11622 isl_map_free(map);
11623 isl_reordering_free(r);
11624 return NULL;
11627 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11628 __isl_take isl_reordering *r)
11630 return set_from_map(isl_map_realign(set_to_map(set), r));
11633 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11634 __isl_take isl_space *model)
11636 isl_ctx *ctx;
11637 isl_bool aligned;
11639 if (!map || !model)
11640 goto error;
11642 ctx = isl_space_get_ctx(model);
11643 if (!isl_space_has_named_params(model))
11644 isl_die(ctx, isl_error_invalid,
11645 "model has unnamed parameters", goto error);
11646 if (isl_map_check_named_params(map) < 0)
11647 goto error;
11648 aligned = isl_map_space_has_equal_params(map, model);
11649 if (aligned < 0)
11650 goto error;
11651 if (!aligned) {
11652 isl_reordering *exp;
11654 exp = isl_parameter_alignment_reordering(map->dim, model);
11655 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11656 map = isl_map_realign(map, exp);
11659 isl_space_free(model);
11660 return map;
11661 error:
11662 isl_space_free(model);
11663 isl_map_free(map);
11664 return NULL;
11667 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11668 __isl_take isl_space *model)
11670 return isl_map_align_params(set, model);
11673 /* Align the parameters of "bmap" to those of "model", introducing
11674 * additional parameters if needed.
11676 __isl_give isl_basic_map *isl_basic_map_align_params(
11677 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11679 isl_ctx *ctx;
11680 isl_bool equal_params;
11682 if (!bmap || !model)
11683 goto error;
11685 ctx = isl_space_get_ctx(model);
11686 if (!isl_space_has_named_params(model))
11687 isl_die(ctx, isl_error_invalid,
11688 "model has unnamed parameters", goto error);
11689 if (isl_basic_map_check_named_params(bmap) < 0)
11690 goto error;
11691 equal_params = isl_space_has_equal_params(bmap->dim, model);
11692 if (equal_params < 0)
11693 goto error;
11694 if (!equal_params) {
11695 isl_reordering *exp;
11696 struct isl_dim_map *dim_map;
11698 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11699 exp = isl_reordering_extend_space(exp,
11700 isl_basic_map_get_space(bmap));
11701 dim_map = isl_dim_map_from_reordering(exp);
11702 bmap = isl_basic_map_realign(bmap,
11703 isl_reordering_get_space(exp),
11704 isl_dim_map_extend(dim_map, bmap));
11705 isl_reordering_free(exp);
11706 free(dim_map);
11709 isl_space_free(model);
11710 return bmap;
11711 error:
11712 isl_space_free(model);
11713 isl_basic_map_free(bmap);
11714 return NULL;
11717 /* Do "bset" and "space" have the same parameters?
11719 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
11720 __isl_keep isl_space *space)
11722 isl_space *bset_space;
11724 bset_space = isl_basic_set_peek_space(bset);
11725 return isl_space_has_equal_params(bset_space, space);
11728 /* Do "map" and "space" have the same parameters?
11730 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
11731 __isl_keep isl_space *space)
11733 isl_space *map_space;
11735 map_space = isl_map_peek_space(map);
11736 return isl_space_has_equal_params(map_space, space);
11739 /* Do "set" and "space" have the same parameters?
11741 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
11742 __isl_keep isl_space *space)
11744 return isl_map_space_has_equal_params(set_to_map(set), space);
11747 /* Align the parameters of "bset" to those of "model", introducing
11748 * additional parameters if needed.
11750 __isl_give isl_basic_set *isl_basic_set_align_params(
11751 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11753 return isl_basic_map_align_params(bset, model);
11756 /* Drop all parameters not referenced by "map".
11758 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
11760 int i;
11762 if (isl_map_check_named_params(map) < 0)
11763 return isl_map_free(map);
11765 for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
11766 isl_bool involves;
11768 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
11769 if (involves < 0)
11770 return isl_map_free(map);
11771 if (!involves)
11772 map = isl_map_project_out(map, isl_dim_param, i, 1);
11775 return map;
11778 /* Drop all parameters not referenced by "set".
11780 __isl_give isl_set *isl_set_drop_unused_params(
11781 __isl_take isl_set *set)
11783 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
11786 /* Drop all parameters not referenced by "bmap".
11788 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
11789 __isl_take isl_basic_map *bmap)
11791 int i;
11793 if (isl_basic_map_check_named_params(bmap) < 0)
11794 return isl_basic_map_free(bmap);
11796 for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
11797 isl_bool involves;
11799 involves = isl_basic_map_involves_dims(bmap,
11800 isl_dim_param, i, 1);
11801 if (involves < 0)
11802 return isl_basic_map_free(bmap);
11803 if (!involves)
11804 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
11807 return bmap;
11810 /* Drop all parameters not referenced by "bset".
11812 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
11813 __isl_take isl_basic_set *bset)
11815 return bset_from_bmap(isl_basic_map_drop_unused_params(
11816 bset_to_bmap(bset)));
11819 __isl_give isl_mat *isl_basic_map_equalities_matrix(
11820 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11821 enum isl_dim_type c2, enum isl_dim_type c3,
11822 enum isl_dim_type c4, enum isl_dim_type c5)
11824 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11825 struct isl_mat *mat;
11826 int i, j, k;
11827 int pos;
11829 if (!bmap)
11830 return NULL;
11831 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11832 isl_basic_map_total_dim(bmap) + 1);
11833 if (!mat)
11834 return NULL;
11835 for (i = 0; i < bmap->n_eq; ++i)
11836 for (j = 0, pos = 0; j < 5; ++j) {
11837 int off = isl_basic_map_offset(bmap, c[j]);
11838 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11839 isl_int_set(mat->row[i][pos],
11840 bmap->eq[i][off + k]);
11841 ++pos;
11845 return mat;
11848 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11849 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11850 enum isl_dim_type c2, enum isl_dim_type c3,
11851 enum isl_dim_type c4, enum isl_dim_type c5)
11853 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11854 struct isl_mat *mat;
11855 int i, j, k;
11856 int pos;
11858 if (!bmap)
11859 return NULL;
11860 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11861 isl_basic_map_total_dim(bmap) + 1);
11862 if (!mat)
11863 return NULL;
11864 for (i = 0; i < bmap->n_ineq; ++i)
11865 for (j = 0, pos = 0; j < 5; ++j) {
11866 int off = isl_basic_map_offset(bmap, c[j]);
11867 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11868 isl_int_set(mat->row[i][pos],
11869 bmap->ineq[i][off + k]);
11870 ++pos;
11874 return mat;
11877 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11878 __isl_take isl_space *space,
11879 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11880 enum isl_dim_type c2, enum isl_dim_type c3,
11881 enum isl_dim_type c4, enum isl_dim_type c5)
11883 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11884 isl_basic_map *bmap = NULL;
11885 unsigned total;
11886 unsigned extra;
11887 int i, j, k, l;
11888 int pos;
11890 if (!space || !eq || !ineq)
11891 goto error;
11893 if (eq->n_col != ineq->n_col)
11894 isl_die(space->ctx, isl_error_invalid,
11895 "equalities and inequalities matrices should have "
11896 "same number of columns", goto error);
11898 total = 1 + isl_space_dim(space, isl_dim_all);
11900 if (eq->n_col < total)
11901 isl_die(space->ctx, isl_error_invalid,
11902 "number of columns too small", goto error);
11904 extra = eq->n_col - total;
11906 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
11907 eq->n_row, ineq->n_row);
11908 if (!bmap)
11909 goto error;
11910 for (i = 0; i < extra; ++i) {
11911 k = isl_basic_map_alloc_div(bmap);
11912 if (k < 0)
11913 goto error;
11914 isl_int_set_si(bmap->div[k][0], 0);
11916 for (i = 0; i < eq->n_row; ++i) {
11917 l = isl_basic_map_alloc_equality(bmap);
11918 if (l < 0)
11919 goto error;
11920 for (j = 0, pos = 0; j < 5; ++j) {
11921 int off = isl_basic_map_offset(bmap, c[j]);
11922 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11923 isl_int_set(bmap->eq[l][off + k],
11924 eq->row[i][pos]);
11925 ++pos;
11929 for (i = 0; i < ineq->n_row; ++i) {
11930 l = isl_basic_map_alloc_inequality(bmap);
11931 if (l < 0)
11932 goto error;
11933 for (j = 0, pos = 0; j < 5; ++j) {
11934 int off = isl_basic_map_offset(bmap, c[j]);
11935 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11936 isl_int_set(bmap->ineq[l][off + k],
11937 ineq->row[i][pos]);
11938 ++pos;
11943 isl_space_free(space);
11944 isl_mat_free(eq);
11945 isl_mat_free(ineq);
11947 bmap = isl_basic_map_simplify(bmap);
11948 return isl_basic_map_finalize(bmap);
11949 error:
11950 isl_space_free(space);
11951 isl_mat_free(eq);
11952 isl_mat_free(ineq);
11953 isl_basic_map_free(bmap);
11954 return NULL;
11957 __isl_give isl_mat *isl_basic_set_equalities_matrix(
11958 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11959 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11961 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
11962 c1, c2, c3, c4, isl_dim_in);
11965 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
11966 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11967 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11969 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
11970 c1, c2, c3, c4, isl_dim_in);
11973 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
11974 __isl_take isl_space *dim,
11975 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11976 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11978 isl_basic_map *bmap;
11979 bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
11980 c1, c2, c3, c4, isl_dim_in);
11981 return bset_from_bmap(bmap);
11984 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
11986 if (!bmap)
11987 return isl_bool_error;
11989 return isl_space_can_zip(bmap->dim);
11992 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
11994 if (!map)
11995 return isl_bool_error;
11997 return isl_space_can_zip(map->dim);
12000 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12001 * (A -> C) -> (B -> D).
12003 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12005 unsigned pos;
12006 unsigned n1;
12007 unsigned n2;
12009 if (!bmap)
12010 return NULL;
12012 if (!isl_basic_map_can_zip(bmap))
12013 isl_die(bmap->ctx, isl_error_invalid,
12014 "basic map cannot be zipped", goto error);
12015 pos = isl_basic_map_offset(bmap, isl_dim_in) +
12016 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12017 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12018 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12019 bmap = isl_basic_map_cow(bmap);
12020 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12021 if (!bmap)
12022 return NULL;
12023 bmap->dim = isl_space_zip(bmap->dim);
12024 if (!bmap->dim)
12025 goto error;
12026 bmap = isl_basic_map_mark_final(bmap);
12027 return bmap;
12028 error:
12029 isl_basic_map_free(bmap);
12030 return NULL;
12033 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12034 * (A -> C) -> (B -> D).
12036 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12038 int i;
12040 if (!map)
12041 return NULL;
12043 if (!isl_map_can_zip(map))
12044 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12045 goto error);
12047 map = isl_map_cow(map);
12048 if (!map)
12049 return NULL;
12051 for (i = 0; i < map->n; ++i) {
12052 map->p[i] = isl_basic_map_zip(map->p[i]);
12053 if (!map->p[i])
12054 goto error;
12057 map->dim = isl_space_zip(map->dim);
12058 if (!map->dim)
12059 goto error;
12061 return map;
12062 error:
12063 isl_map_free(map);
12064 return NULL;
12067 /* Can we apply isl_basic_map_curry to "bmap"?
12068 * That is, does it have a nested relation in its domain?
12070 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12072 if (!bmap)
12073 return isl_bool_error;
12075 return isl_space_can_curry(bmap->dim);
12078 /* Can we apply isl_map_curry to "map"?
12079 * That is, does it have a nested relation in its domain?
12081 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12083 if (!map)
12084 return isl_bool_error;
12086 return isl_space_can_curry(map->dim);
12089 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12090 * A -> (B -> C).
12092 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12095 if (!bmap)
12096 return NULL;
12098 if (!isl_basic_map_can_curry(bmap))
12099 isl_die(bmap->ctx, isl_error_invalid,
12100 "basic map cannot be curried", goto error);
12101 bmap = isl_basic_map_cow(bmap);
12102 if (!bmap)
12103 return NULL;
12104 bmap->dim = isl_space_curry(bmap->dim);
12105 if (!bmap->dim)
12106 goto error;
12107 bmap = isl_basic_map_mark_final(bmap);
12108 return bmap;
12109 error:
12110 isl_basic_map_free(bmap);
12111 return NULL;
12114 /* Given a map (A -> B) -> C, return the corresponding map
12115 * A -> (B -> C).
12117 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
12119 return isl_map_change_space(map, &isl_map_can_curry,
12120 "map cannot be curried", &isl_space_curry);
12123 /* Can isl_map_range_curry be applied to "map"?
12124 * That is, does it have a nested relation in its range,
12125 * the domain of which is itself a nested relation?
12127 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
12129 if (!map)
12130 return isl_bool_error;
12132 return isl_space_can_range_curry(map->dim);
12135 /* Given a map A -> ((B -> C) -> D), return the corresponding map
12136 * A -> (B -> (C -> D)).
12138 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
12140 return isl_map_change_space(map, &isl_map_can_range_curry,
12141 "map range cannot be curried",
12142 &isl_space_range_curry);
12145 /* Can we apply isl_basic_map_uncurry to "bmap"?
12146 * That is, does it have a nested relation in its domain?
12148 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
12150 if (!bmap)
12151 return isl_bool_error;
12153 return isl_space_can_uncurry(bmap->dim);
12156 /* Can we apply isl_map_uncurry to "map"?
12157 * That is, does it have a nested relation in its domain?
12159 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
12161 if (!map)
12162 return isl_bool_error;
12164 return isl_space_can_uncurry(map->dim);
12167 /* Given a basic map A -> (B -> C), return the corresponding basic map
12168 * (A -> B) -> C.
12170 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
12173 if (!bmap)
12174 return NULL;
12176 if (!isl_basic_map_can_uncurry(bmap))
12177 isl_die(bmap->ctx, isl_error_invalid,
12178 "basic map cannot be uncurried",
12179 return isl_basic_map_free(bmap));
12180 bmap = isl_basic_map_cow(bmap);
12181 if (!bmap)
12182 return NULL;
12183 bmap->dim = isl_space_uncurry(bmap->dim);
12184 if (!bmap->dim)
12185 return isl_basic_map_free(bmap);
12186 bmap = isl_basic_map_mark_final(bmap);
12187 return bmap;
12190 /* Given a map A -> (B -> C), return the corresponding map
12191 * (A -> B) -> C.
12193 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
12195 return isl_map_change_space(map, &isl_map_can_uncurry,
12196 "map cannot be uncurried", &isl_space_uncurry);
12199 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
12200 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12202 return isl_map_equate(set, type1, pos1, type2, pos2);
12205 /* Construct a basic map where the given dimensions are equal to each other.
12207 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
12208 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12210 isl_basic_map *bmap = NULL;
12211 int i;
12213 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12214 isl_space_check_range(space, type2, pos2, 1) < 0)
12215 goto error;
12217 if (type1 == type2 && pos1 == pos2)
12218 return isl_basic_map_universe(space);
12220 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
12221 i = isl_basic_map_alloc_equality(bmap);
12222 if (i < 0)
12223 goto error;
12224 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12225 pos1 += isl_basic_map_offset(bmap, type1);
12226 pos2 += isl_basic_map_offset(bmap, type2);
12227 isl_int_set_si(bmap->eq[i][pos1], -1);
12228 isl_int_set_si(bmap->eq[i][pos2], 1);
12229 bmap = isl_basic_map_finalize(bmap);
12230 isl_space_free(space);
12231 return bmap;
12232 error:
12233 isl_space_free(space);
12234 isl_basic_map_free(bmap);
12235 return NULL;
12238 /* Add a constraint imposing that the given two dimensions are equal.
12240 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
12241 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12243 isl_basic_map *eq;
12245 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12247 bmap = isl_basic_map_intersect(bmap, eq);
12249 return bmap;
12252 /* Add a constraint imposing that the given two dimensions are equal.
12254 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
12255 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12257 isl_basic_map *bmap;
12259 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
12261 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12263 return map;
12266 /* Add a constraint imposing that the given two dimensions have opposite values.
12268 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
12269 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12271 isl_basic_map *bmap = NULL;
12272 int i;
12274 if (isl_map_check_range(map, type1, pos1, 1) < 0)
12275 return isl_map_free(map);
12276 if (isl_map_check_range(map, type2, pos2, 1) < 0)
12277 return isl_map_free(map);
12279 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
12280 i = isl_basic_map_alloc_equality(bmap);
12281 if (i < 0)
12282 goto error;
12283 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12284 pos1 += isl_basic_map_offset(bmap, type1);
12285 pos2 += isl_basic_map_offset(bmap, type2);
12286 isl_int_set_si(bmap->eq[i][pos1], 1);
12287 isl_int_set_si(bmap->eq[i][pos2], 1);
12288 bmap = isl_basic_map_finalize(bmap);
12290 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12292 return map;
12293 error:
12294 isl_basic_map_free(bmap);
12295 isl_map_free(map);
12296 return NULL;
12299 /* Construct a constraint imposing that the value of the first dimension is
12300 * greater than or equal to that of the second.
12302 static __isl_give isl_constraint *constraint_order_ge(
12303 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
12304 enum isl_dim_type type2, int pos2)
12306 isl_constraint *c;
12308 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12309 isl_space_check_range(space, type2, pos2, 1) < 0)
12310 space = isl_space_free(space);
12311 if (!space)
12312 return NULL;
12314 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
12316 if (type1 == type2 && pos1 == pos2)
12317 return c;
12319 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
12320 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
12322 return c;
12325 /* Add a constraint imposing that the value of the first dimension is
12326 * greater than or equal to that of the second.
12328 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
12329 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12331 isl_constraint *c;
12332 isl_space *space;
12334 if (type1 == type2 && pos1 == pos2)
12335 return bmap;
12336 space = isl_basic_map_get_space(bmap);
12337 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12338 bmap = isl_basic_map_add_constraint(bmap, c);
12340 return bmap;
12343 /* Add a constraint imposing that the value of the first dimension is
12344 * greater than or equal to that of the second.
12346 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12347 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12349 isl_constraint *c;
12350 isl_space *space;
12352 if (type1 == type2 && pos1 == pos2)
12353 return map;
12354 space = isl_map_get_space(map);
12355 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12356 map = isl_map_add_constraint(map, c);
12358 return map;
12361 /* Add a constraint imposing that the value of the first dimension is
12362 * less than or equal to that of the second.
12364 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12365 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12367 return isl_map_order_ge(map, type2, pos2, type1, pos1);
12370 /* Construct a basic map where the value of the first dimension is
12371 * greater than that of the second.
12373 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12374 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12376 isl_basic_map *bmap = NULL;
12377 int i;
12379 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12380 isl_space_check_range(space, type2, pos2, 1) < 0)
12381 goto error;
12383 if (type1 == type2 && pos1 == pos2)
12384 return isl_basic_map_empty(space);
12386 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12387 i = isl_basic_map_alloc_inequality(bmap);
12388 if (i < 0)
12389 return isl_basic_map_free(bmap);
12390 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12391 pos1 += isl_basic_map_offset(bmap, type1);
12392 pos2 += isl_basic_map_offset(bmap, type2);
12393 isl_int_set_si(bmap->ineq[i][pos1], 1);
12394 isl_int_set_si(bmap->ineq[i][pos2], -1);
12395 isl_int_set_si(bmap->ineq[i][0], -1);
12396 bmap = isl_basic_map_finalize(bmap);
12398 return bmap;
12399 error:
12400 isl_space_free(space);
12401 isl_basic_map_free(bmap);
12402 return NULL;
12405 /* Add a constraint imposing that the value of the first dimension is
12406 * greater than that of the second.
12408 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12409 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12411 isl_basic_map *gt;
12413 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12415 bmap = isl_basic_map_intersect(bmap, gt);
12417 return bmap;
12420 /* Add a constraint imposing that the value of the first dimension is
12421 * greater than that of the second.
12423 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12424 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12426 isl_basic_map *bmap;
12428 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12430 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12432 return map;
12435 /* Add a constraint imposing that the value of the first dimension is
12436 * smaller than that of the second.
12438 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12439 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12441 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12444 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12445 int pos)
12447 isl_aff *div;
12448 isl_local_space *ls;
12450 if (!bmap)
12451 return NULL;
12453 if (!isl_basic_map_divs_known(bmap))
12454 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12455 "some divs are unknown", return NULL);
12457 ls = isl_basic_map_get_local_space(bmap);
12458 div = isl_local_space_get_div(ls, pos);
12459 isl_local_space_free(ls);
12461 return div;
12464 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12465 int pos)
12467 return isl_basic_map_get_div(bset, pos);
12470 /* Plug in "subs" for dimension "type", "pos" of "bset".
12472 * Let i be the dimension to replace and let "subs" be of the form
12474 * f/d
12476 * Any integer division with a non-zero coefficient for i,
12478 * floor((a i + g)/m)
12480 * is replaced by
12482 * floor((a f + d g)/(m d))
12484 * Constraints of the form
12486 * a i + g
12488 * are replaced by
12490 * a f + d g
12492 * We currently require that "subs" is an integral expression.
12493 * Handling rational expressions may require us to add stride constraints
12494 * as we do in isl_basic_set_preimage_multi_aff.
12496 __isl_give isl_basic_set *isl_basic_set_substitute(
12497 __isl_take isl_basic_set *bset,
12498 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12500 int i;
12501 isl_int v;
12502 isl_ctx *ctx;
12504 if (bset && isl_basic_set_plain_is_empty(bset))
12505 return bset;
12507 bset = isl_basic_set_cow(bset);
12508 if (!bset || !subs)
12509 goto error;
12511 ctx = isl_basic_set_get_ctx(bset);
12512 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12513 isl_die(ctx, isl_error_invalid,
12514 "spaces don't match", goto error);
12515 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12516 isl_die(ctx, isl_error_unsupported,
12517 "cannot handle divs yet", goto error);
12518 if (!isl_int_is_one(subs->v->el[0]))
12519 isl_die(ctx, isl_error_invalid,
12520 "can only substitute integer expressions", goto error);
12522 pos += isl_basic_set_offset(bset, type);
12524 isl_int_init(v);
12526 for (i = 0; i < bset->n_eq; ++i) {
12527 if (isl_int_is_zero(bset->eq[i][pos]))
12528 continue;
12529 isl_int_set(v, bset->eq[i][pos]);
12530 isl_int_set_si(bset->eq[i][pos], 0);
12531 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12532 v, subs->v->el + 1, subs->v->size - 1);
12535 for (i = 0; i < bset->n_ineq; ++i) {
12536 if (isl_int_is_zero(bset->ineq[i][pos]))
12537 continue;
12538 isl_int_set(v, bset->ineq[i][pos]);
12539 isl_int_set_si(bset->ineq[i][pos], 0);
12540 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12541 v, subs->v->el + 1, subs->v->size - 1);
12544 for (i = 0; i < bset->n_div; ++i) {
12545 if (isl_int_is_zero(bset->div[i][1 + pos]))
12546 continue;
12547 isl_int_set(v, bset->div[i][1 + pos]);
12548 isl_int_set_si(bset->div[i][1 + pos], 0);
12549 isl_seq_combine(bset->div[i] + 1,
12550 subs->v->el[0], bset->div[i] + 1,
12551 v, subs->v->el + 1, subs->v->size - 1);
12552 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12555 isl_int_clear(v);
12557 bset = isl_basic_set_simplify(bset);
12558 return isl_basic_set_finalize(bset);
12559 error:
12560 isl_basic_set_free(bset);
12561 return NULL;
12564 /* Plug in "subs" for dimension "type", "pos" of "set".
12566 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12567 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12569 int i;
12571 if (set && isl_set_plain_is_empty(set))
12572 return set;
12574 set = isl_set_cow(set);
12575 if (!set || !subs)
12576 goto error;
12578 for (i = set->n - 1; i >= 0; --i) {
12579 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12580 set = set_from_map(remove_if_empty(set_to_map(set), i));
12581 if (!set)
12582 return NULL;
12585 return set;
12586 error:
12587 isl_set_free(set);
12588 return NULL;
12591 /* Check if the range of "ma" is compatible with the domain or range
12592 * (depending on "type") of "bmap".
12594 static isl_stat check_basic_map_compatible_range_multi_aff(
12595 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12596 __isl_keep isl_multi_aff *ma)
12598 isl_bool m;
12599 isl_space *ma_space;
12601 ma_space = isl_multi_aff_get_space(ma);
12603 m = isl_space_has_equal_params(bmap->dim, ma_space);
12604 if (m < 0)
12605 goto error;
12606 if (!m)
12607 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12608 "parameters don't match", goto error);
12609 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12610 if (m < 0)
12611 goto error;
12612 if (!m)
12613 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12614 "spaces don't match", goto error);
12616 isl_space_free(ma_space);
12617 return isl_stat_ok;
12618 error:
12619 isl_space_free(ma_space);
12620 return isl_stat_error;
12623 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12624 * coefficients before the transformed range of dimensions,
12625 * the "n_after" coefficients after the transformed range of dimensions
12626 * and the coefficients of the other divs in "bmap".
12628 static int set_ma_divs(__isl_keep isl_basic_map *bmap,
12629 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12631 int i;
12632 int n_param;
12633 int n_set;
12634 isl_local_space *ls;
12636 if (n_div == 0)
12637 return 0;
12639 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
12640 if (!ls)
12641 return -1;
12643 n_param = isl_local_space_dim(ls, isl_dim_param);
12644 n_set = isl_local_space_dim(ls, isl_dim_set);
12645 for (i = 0; i < n_div; ++i) {
12646 int o_bmap = 0, o_ls = 0;
12648 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12649 o_bmap += 1 + 1 + n_param;
12650 o_ls += 1 + 1 + n_param;
12651 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12652 o_bmap += n_before;
12653 isl_seq_cpy(bmap->div[i] + o_bmap,
12654 ls->div->row[i] + o_ls, n_set);
12655 o_bmap += n_set;
12656 o_ls += n_set;
12657 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12658 o_bmap += n_after;
12659 isl_seq_cpy(bmap->div[i] + o_bmap,
12660 ls->div->row[i] + o_ls, n_div);
12661 o_bmap += n_div;
12662 o_ls += n_div;
12663 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12664 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
12665 goto error;
12668 isl_local_space_free(ls);
12669 return 0;
12670 error:
12671 isl_local_space_free(ls);
12672 return -1;
12675 /* How many stride constraints does "ma" enforce?
12676 * That is, how many of the affine expressions have a denominator
12677 * different from one?
12679 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12681 int i;
12682 int strides = 0;
12684 for (i = 0; i < ma->n; ++i)
12685 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
12686 strides++;
12688 return strides;
12691 /* For each affine expression in ma of the form
12693 * x_i = (f_i y + h_i)/m_i
12695 * with m_i different from one, add a constraint to "bmap"
12696 * of the form
12698 * f_i y + h_i = m_i alpha_i
12700 * with alpha_i an additional existentially quantified variable.
12702 * The input variables of "ma" correspond to a subset of the variables
12703 * of "bmap". There are "n_before" variables in "bmap" before this
12704 * subset and "n_after" variables after this subset.
12705 * The integer divisions of the affine expressions in "ma" are assumed
12706 * to have been aligned. There are "n_div_ma" of them and
12707 * they appear first in "bmap", straight after the "n_after" variables.
12709 static __isl_give isl_basic_map *add_ma_strides(
12710 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12711 int n_before, int n_after, int n_div_ma)
12713 int i, k;
12714 int div;
12715 int total;
12716 int n_param;
12717 int n_in;
12719 total = isl_basic_map_total_dim(bmap);
12720 n_param = isl_multi_aff_dim(ma, isl_dim_param);
12721 n_in = isl_multi_aff_dim(ma, isl_dim_in);
12722 for (i = 0; i < ma->n; ++i) {
12723 int o_bmap = 0, o_ma = 1;
12725 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
12726 continue;
12727 div = isl_basic_map_alloc_div(bmap);
12728 k = isl_basic_map_alloc_equality(bmap);
12729 if (div < 0 || k < 0)
12730 goto error;
12731 isl_int_set_si(bmap->div[div][0], 0);
12732 isl_seq_cpy(bmap->eq[k] + o_bmap,
12733 ma->u.p[i]->v->el + o_ma, 1 + n_param);
12734 o_bmap += 1 + n_param;
12735 o_ma += 1 + n_param;
12736 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12737 o_bmap += n_before;
12738 isl_seq_cpy(bmap->eq[k] + o_bmap,
12739 ma->u.p[i]->v->el + o_ma, n_in);
12740 o_bmap += n_in;
12741 o_ma += n_in;
12742 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12743 o_bmap += n_after;
12744 isl_seq_cpy(bmap->eq[k] + o_bmap,
12745 ma->u.p[i]->v->el + o_ma, n_div_ma);
12746 o_bmap += n_div_ma;
12747 o_ma += n_div_ma;
12748 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12749 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
12750 total++;
12753 return bmap;
12754 error:
12755 isl_basic_map_free(bmap);
12756 return NULL;
12759 /* Replace the domain or range space (depending on "type) of "space" by "set".
12761 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12762 enum isl_dim_type type, __isl_take isl_space *set)
12764 if (type == isl_dim_in) {
12765 space = isl_space_range(space);
12766 space = isl_space_map_from_domain_and_range(set, space);
12767 } else {
12768 space = isl_space_domain(space);
12769 space = isl_space_map_from_domain_and_range(space, set);
12772 return space;
12775 /* Compute the preimage of the domain or range (depending on "type")
12776 * of "bmap" under the function represented by "ma".
12777 * In other words, plug in "ma" in the domain or range of "bmap".
12778 * The result is a basic map that lives in the same space as "bmap"
12779 * except that the domain or range has been replaced by
12780 * the domain space of "ma".
12782 * If bmap is represented by
12784 * A(p) + S u + B x + T v + C(divs) >= 0,
12786 * where u and x are input and output dimensions if type == isl_dim_out
12787 * while x and v are input and output dimensions if type == isl_dim_in,
12788 * and ma is represented by
12790 * x = D(p) + F(y) + G(divs')
12792 * then the result is
12794 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12796 * The divs in the input set are similarly adjusted.
12797 * In particular
12799 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12801 * becomes
12803 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12804 * B_i G(divs') + c_i(divs))/n_i)
12806 * If bmap is not a rational map and if F(y) involves any denominators
12808 * x_i = (f_i y + h_i)/m_i
12810 * then additional constraints are added to ensure that we only
12811 * map back integer points. That is we enforce
12813 * f_i y + h_i = m_i alpha_i
12815 * with alpha_i an additional existentially quantified variable.
12817 * We first copy over the divs from "ma".
12818 * Then we add the modified constraints and divs from "bmap".
12819 * Finally, we add the stride constraints, if needed.
12821 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12822 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12823 __isl_take isl_multi_aff *ma)
12825 int i, k;
12826 isl_space *space;
12827 isl_basic_map *res = NULL;
12828 int n_before, n_after, n_div_bmap, n_div_ma;
12829 isl_int f, c1, c2, g;
12830 isl_bool rational;
12831 int strides;
12833 isl_int_init(f);
12834 isl_int_init(c1);
12835 isl_int_init(c2);
12836 isl_int_init(g);
12838 ma = isl_multi_aff_align_divs(ma);
12839 if (!bmap || !ma)
12840 goto error;
12841 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12842 goto error;
12844 if (type == isl_dim_in) {
12845 n_before = 0;
12846 n_after = isl_basic_map_dim(bmap, isl_dim_out);
12847 } else {
12848 n_before = isl_basic_map_dim(bmap, isl_dim_in);
12849 n_after = 0;
12851 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12852 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
12854 space = isl_multi_aff_get_domain_space(ma);
12855 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12856 rational = isl_basic_map_is_rational(bmap);
12857 strides = rational ? 0 : multi_aff_strides(ma);
12858 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12859 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12860 if (rational)
12861 res = isl_basic_map_set_rational(res);
12863 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12864 if (isl_basic_map_alloc_div(res) < 0)
12865 goto error;
12867 if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
12868 goto error;
12870 for (i = 0; i < bmap->n_eq; ++i) {
12871 k = isl_basic_map_alloc_equality(res);
12872 if (k < 0)
12873 goto error;
12874 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
12875 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12878 for (i = 0; i < bmap->n_ineq; ++i) {
12879 k = isl_basic_map_alloc_inequality(res);
12880 if (k < 0)
12881 goto error;
12882 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
12883 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12886 for (i = 0; i < bmap->n_div; ++i) {
12887 if (isl_int_is_zero(bmap->div[i][0])) {
12888 isl_int_set_si(res->div[n_div_ma + i][0], 0);
12889 continue;
12891 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
12892 n_before, n_after, n_div_ma, n_div_bmap,
12893 f, c1, c2, g, 1);
12896 if (strides)
12897 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
12899 isl_int_clear(f);
12900 isl_int_clear(c1);
12901 isl_int_clear(c2);
12902 isl_int_clear(g);
12903 isl_basic_map_free(bmap);
12904 isl_multi_aff_free(ma);
12905 res = isl_basic_map_simplify(res);
12906 return isl_basic_map_finalize(res);
12907 error:
12908 isl_int_clear(f);
12909 isl_int_clear(c1);
12910 isl_int_clear(c2);
12911 isl_int_clear(g);
12912 isl_basic_map_free(bmap);
12913 isl_multi_aff_free(ma);
12914 isl_basic_map_free(res);
12915 return NULL;
12918 /* Compute the preimage of "bset" under the function represented by "ma".
12919 * In other words, plug in "ma" in "bset". The result is a basic set
12920 * that lives in the domain space of "ma".
12922 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
12923 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
12925 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
12928 /* Compute the preimage of the domain of "bmap" under the function
12929 * represented by "ma".
12930 * In other words, plug in "ma" in the domain of "bmap".
12931 * The result is a basic map that lives in the same space as "bmap"
12932 * except that the domain has been replaced by the domain space of "ma".
12934 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
12935 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12937 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
12940 /* Compute the preimage of the range of "bmap" under the function
12941 * represented by "ma".
12942 * In other words, plug in "ma" in the range of "bmap".
12943 * The result is a basic map that lives in the same space as "bmap"
12944 * except that the range has been replaced by the domain space of "ma".
12946 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
12947 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12949 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
12952 /* Check if the range of "ma" is compatible with the domain or range
12953 * (depending on "type") of "map".
12954 * Return isl_stat_error if anything is wrong.
12956 static isl_stat check_map_compatible_range_multi_aff(
12957 __isl_keep isl_map *map, enum isl_dim_type type,
12958 __isl_keep isl_multi_aff *ma)
12960 isl_bool m;
12961 isl_space *ma_space;
12963 ma_space = isl_multi_aff_get_space(ma);
12964 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
12965 isl_space_free(ma_space);
12966 if (m < 0)
12967 return isl_stat_error;
12968 if (!m)
12969 isl_die(isl_map_get_ctx(map), isl_error_invalid,
12970 "spaces don't match", return isl_stat_error);
12971 return isl_stat_ok;
12974 /* Compute the preimage of the domain or range (depending on "type")
12975 * of "map" under the function represented by "ma".
12976 * In other words, plug in "ma" in the domain or range of "map".
12977 * The result is a map that lives in the same space as "map"
12978 * except that the domain or range has been replaced by
12979 * the domain space of "ma".
12981 * The parameters are assumed to have been aligned.
12983 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
12984 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12986 int i;
12987 isl_space *space;
12989 map = isl_map_cow(map);
12990 ma = isl_multi_aff_align_divs(ma);
12991 if (!map || !ma)
12992 goto error;
12993 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
12994 goto error;
12996 for (i = 0; i < map->n; ++i) {
12997 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
12998 isl_multi_aff_copy(ma));
12999 if (!map->p[i])
13000 goto error;
13003 space = isl_multi_aff_get_domain_space(ma);
13004 space = isl_space_set(isl_map_get_space(map), type, space);
13006 isl_space_free(map->dim);
13007 map->dim = space;
13008 if (!map->dim)
13009 goto error;
13011 isl_multi_aff_free(ma);
13012 if (map->n > 1)
13013 ISL_F_CLR(map, ISL_MAP_DISJOINT);
13014 ISL_F_CLR(map, ISL_SET_NORMALIZED);
13015 return map;
13016 error:
13017 isl_multi_aff_free(ma);
13018 isl_map_free(map);
13019 return NULL;
13022 /* Compute the preimage of the domain or range (depending on "type")
13023 * of "map" under the function represented by "ma".
13024 * In other words, plug in "ma" in the domain or range of "map".
13025 * The result is a map that lives in the same space as "map"
13026 * except that the domain or range has been replaced by
13027 * the domain space of "ma".
13029 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13030 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13032 isl_bool aligned;
13034 if (!map || !ma)
13035 goto error;
13037 aligned = isl_map_space_has_equal_params(map, ma->space);
13038 if (aligned < 0)
13039 goto error;
13040 if (aligned)
13041 return map_preimage_multi_aff(map, type, ma);
13043 if (isl_map_check_named_params(map) < 0)
13044 goto error;
13045 if (!isl_space_has_named_params(ma->space))
13046 isl_die(map->ctx, isl_error_invalid,
13047 "unaligned unnamed parameters", goto error);
13048 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13049 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13051 return map_preimage_multi_aff(map, type, ma);
13052 error:
13053 isl_multi_aff_free(ma);
13054 return isl_map_free(map);
13057 /* Compute the preimage of "set" under the function represented by "ma".
13058 * In other words, plug in "ma" in "set". The result is a set
13059 * that lives in the domain space of "ma".
13061 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13062 __isl_take isl_multi_aff *ma)
13064 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13067 /* Compute the preimage of the domain of "map" under the function
13068 * represented by "ma".
13069 * In other words, plug in "ma" in the domain of "map".
13070 * The result is a map that lives in the same space as "map"
13071 * except that the domain has been replaced by the domain space of "ma".
13073 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13074 __isl_take isl_multi_aff *ma)
13076 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13079 /* Compute the preimage of the range of "map" under the function
13080 * represented by "ma".
13081 * In other words, plug in "ma" in the range of "map".
13082 * The result is a map that lives in the same space as "map"
13083 * except that the range has been replaced by the domain space of "ma".
13085 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13086 __isl_take isl_multi_aff *ma)
13088 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
13091 /* Compute the preimage of "map" under the function represented by "pma".
13092 * In other words, plug in "pma" in the domain or range of "map".
13093 * The result is a map that lives in the same space as "map",
13094 * except that the space of type "type" has been replaced by
13095 * the domain space of "pma".
13097 * The parameters of "map" and "pma" are assumed to have been aligned.
13099 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
13100 __isl_take isl_map *map, enum isl_dim_type type,
13101 __isl_take isl_pw_multi_aff *pma)
13103 int i;
13104 isl_map *res;
13106 if (!pma)
13107 goto error;
13109 if (pma->n == 0) {
13110 isl_pw_multi_aff_free(pma);
13111 res = isl_map_empty(isl_map_get_space(map));
13112 isl_map_free(map);
13113 return res;
13116 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13117 isl_multi_aff_copy(pma->p[0].maff));
13118 if (type == isl_dim_in)
13119 res = isl_map_intersect_domain(res,
13120 isl_map_copy(pma->p[0].set));
13121 else
13122 res = isl_map_intersect_range(res,
13123 isl_map_copy(pma->p[0].set));
13125 for (i = 1; i < pma->n; ++i) {
13126 isl_map *res_i;
13128 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13129 isl_multi_aff_copy(pma->p[i].maff));
13130 if (type == isl_dim_in)
13131 res_i = isl_map_intersect_domain(res_i,
13132 isl_map_copy(pma->p[i].set));
13133 else
13134 res_i = isl_map_intersect_range(res_i,
13135 isl_map_copy(pma->p[i].set));
13136 res = isl_map_union(res, res_i);
13139 isl_pw_multi_aff_free(pma);
13140 isl_map_free(map);
13141 return res;
13142 error:
13143 isl_pw_multi_aff_free(pma);
13144 isl_map_free(map);
13145 return NULL;
13148 /* Compute the preimage of "map" under the function represented by "pma".
13149 * In other words, plug in "pma" in the domain or range of "map".
13150 * The result is a map that lives in the same space as "map",
13151 * except that the space of type "type" has been replaced by
13152 * the domain space of "pma".
13154 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
13155 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
13157 isl_bool aligned;
13159 if (!map || !pma)
13160 goto error;
13162 aligned = isl_map_space_has_equal_params(map, pma->dim);
13163 if (aligned < 0)
13164 goto error;
13165 if (aligned)
13166 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13168 if (isl_map_check_named_params(map) < 0)
13169 goto error;
13170 if (isl_pw_multi_aff_check_named_params(pma) < 0)
13171 goto error;
13172 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
13173 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
13175 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13176 error:
13177 isl_pw_multi_aff_free(pma);
13178 return isl_map_free(map);
13181 /* Compute the preimage of "set" under the function represented by "pma".
13182 * In other words, plug in "pma" in "set". The result is a set
13183 * that lives in the domain space of "pma".
13185 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
13186 __isl_take isl_pw_multi_aff *pma)
13188 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
13191 /* Compute the preimage of the domain of "map" under the function
13192 * represented by "pma".
13193 * In other words, plug in "pma" in the domain of "map".
13194 * The result is a map that lives in the same space as "map",
13195 * except that domain space has been replaced by the domain space of "pma".
13197 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
13198 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13200 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
13203 /* Compute the preimage of the range of "map" under the function
13204 * represented by "pma".
13205 * In other words, plug in "pma" in the range of "map".
13206 * The result is a map that lives in the same space as "map",
13207 * except that range space has been replaced by the domain space of "pma".
13209 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
13210 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13212 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
13215 /* Compute the preimage of "map" under the function represented by "mpa".
13216 * In other words, plug in "mpa" in the domain or range of "map".
13217 * The result is a map that lives in the same space as "map",
13218 * except that the space of type "type" has been replaced by
13219 * the domain space of "mpa".
13221 * If the map does not involve any constraints that refer to the
13222 * dimensions of the substituted space, then the only possible
13223 * effect of "mpa" on the map is to map the space to a different space.
13224 * We create a separate isl_multi_aff to effectuate this change
13225 * in order to avoid spurious splitting of the map along the pieces
13226 * of "mpa".
13227 * If "mpa" has a non-trivial explicit domain, however,
13228 * then the full substitution should be performed.
13230 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
13231 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
13233 int n;
13234 isl_bool full;
13235 isl_pw_multi_aff *pma;
13237 if (!map || !mpa)
13238 goto error;
13240 n = isl_map_dim(map, type);
13241 full = isl_map_involves_dims(map, type, 0, n);
13242 if (full >= 0 && !full)
13243 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
13244 if (full < 0)
13245 goto error;
13246 if (!full) {
13247 isl_space *space;
13248 isl_multi_aff *ma;
13250 space = isl_multi_pw_aff_get_space(mpa);
13251 isl_multi_pw_aff_free(mpa);
13252 ma = isl_multi_aff_zero(space);
13253 return isl_map_preimage_multi_aff(map, type, ma);
13256 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
13257 return isl_map_preimage_pw_multi_aff(map, type, pma);
13258 error:
13259 isl_map_free(map);
13260 isl_multi_pw_aff_free(mpa);
13261 return NULL;
13264 /* Compute the preimage of "map" under the function represented by "mpa".
13265 * In other words, plug in "mpa" in the domain "map".
13266 * The result is a map that lives in the same space as "map",
13267 * except that domain space has been replaced by the domain space of "mpa".
13269 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
13270 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
13272 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
13275 /* Compute the preimage of "set" by the function represented by "mpa".
13276 * In other words, plug in "mpa" in "set".
13278 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
13279 __isl_take isl_multi_pw_aff *mpa)
13281 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
13284 /* Return a copy of the equality constraints of "bset" as a matrix.
13286 __isl_give isl_mat *isl_basic_set_extract_equalities(
13287 __isl_keep isl_basic_set *bset)
13289 isl_ctx *ctx;
13290 unsigned total;
13292 if (!bset)
13293 return NULL;
13295 ctx = isl_basic_set_get_ctx(bset);
13296 total = 1 + isl_basic_set_dim(bset, isl_dim_all);
13297 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
13300 /* Are the "n" "coefficients" starting at "first" of the integer division
13301 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
13302 * to each other?
13303 * The "coefficient" at position 0 is the denominator.
13304 * The "coefficient" at position 1 is the constant term.
13306 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
13307 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
13308 unsigned first, unsigned n)
13310 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
13311 return isl_bool_error;
13312 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
13313 return isl_bool_error;
13314 return isl_seq_eq(bmap1->div[pos1] + first,
13315 bmap2->div[pos2] + first, n);
13318 /* Are the integer division expressions at position "pos1" in "bmap1" and
13319 * "pos2" in "bmap2" equal to each other, except that the constant terms
13320 * are different?
13322 isl_bool isl_basic_map_equal_div_expr_except_constant(
13323 __isl_keep isl_basic_map *bmap1, int pos1,
13324 __isl_keep isl_basic_map *bmap2, int pos2)
13326 isl_bool equal;
13327 unsigned total;
13329 if (!bmap1 || !bmap2)
13330 return isl_bool_error;
13331 total = isl_basic_map_total_dim(bmap1);
13332 if (total != isl_basic_map_total_dim(bmap2))
13333 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
13334 "incomparable div expressions", return isl_bool_error);
13335 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13336 0, 1);
13337 if (equal < 0 || !equal)
13338 return equal;
13339 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13340 1, 1);
13341 if (equal < 0 || equal)
13342 return isl_bool_not(equal);
13343 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13344 2, total);
13347 /* Replace the numerator of the constant term of the integer division
13348 * expression at position "div" in "bmap" by "value".
13349 * The caller guarantees that this does not change the meaning
13350 * of the input.
13352 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
13353 __isl_take isl_basic_map *bmap, int div, int value)
13355 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
13356 return isl_basic_map_free(bmap);
13358 isl_int_set_si(bmap->div[div][1], value);
13360 return bmap;
13363 /* Is the point "inner" internal to inequality constraint "ineq"
13364 * of "bset"?
13365 * The point is considered to be internal to the inequality constraint,
13366 * if it strictly lies on the positive side of the inequality constraint,
13367 * or if it lies on the constraint and the constraint is lexico-positive.
13369 static isl_bool is_internal(__isl_keep isl_vec *inner,
13370 __isl_keep isl_basic_set *bset, int ineq)
13372 isl_ctx *ctx;
13373 int pos;
13374 unsigned total;
13376 if (!inner || !bset)
13377 return isl_bool_error;
13379 ctx = isl_basic_set_get_ctx(bset);
13380 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13381 &ctx->normalize_gcd);
13382 if (!isl_int_is_zero(ctx->normalize_gcd))
13383 return isl_int_is_nonneg(ctx->normalize_gcd);
13385 total = isl_basic_set_dim(bset, isl_dim_all);
13386 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13387 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13390 /* Tighten the inequality constraints of "bset" that are outward with respect
13391 * to the point "vec".
13392 * That is, tighten the constraints that are not satisfied by "vec".
13394 * "vec" is a point internal to some superset S of "bset" that is used
13395 * to make the subsets of S disjoint, by tightening one half of the constraints
13396 * that separate two subsets. In particular, the constraints of S
13397 * are all satisfied by "vec" and should not be tightened.
13398 * Of the internal constraints, those that have "vec" on the outside
13399 * are tightened. The shared facet is included in the adjacent subset
13400 * with the opposite constraint.
13401 * For constraints that saturate "vec", this criterion cannot be used
13402 * to determine which of the two sides should be tightened.
13403 * Instead, the sign of the first non-zero coefficient is used
13404 * to make this choice. Note that this second criterion is never used
13405 * on the constraints of S since "vec" is interior to "S".
13407 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13408 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13410 int j;
13412 bset = isl_basic_set_cow(bset);
13413 if (!bset)
13414 return NULL;
13415 for (j = 0; j < bset->n_ineq; ++j) {
13416 isl_bool internal;
13418 internal = is_internal(vec, bset, j);
13419 if (internal < 0)
13420 return isl_basic_set_free(bset);
13421 if (internal)
13422 continue;
13423 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13426 return bset;
13429 /* Replace the variables x of type "type" starting at "first" in "bmap"
13430 * by x' with x = M x' with M the matrix trans.
13431 * That is, replace the corresponding coefficients c by c M.
13433 * The transformation matrix should be a square matrix.
13435 __isl_give isl_basic_map *isl_basic_map_transform_dims(
13436 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
13437 __isl_take isl_mat *trans)
13439 unsigned pos;
13441 bmap = isl_basic_map_cow(bmap);
13442 if (!bmap || !trans)
13443 goto error;
13445 if (trans->n_row != trans->n_col)
13446 isl_die(trans->ctx, isl_error_invalid,
13447 "expecting square transformation matrix", goto error);
13448 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
13449 goto error;
13451 pos = isl_basic_map_offset(bmap, type) + first;
13453 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
13454 isl_mat_copy(trans)) < 0)
13455 goto error;
13456 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
13457 isl_mat_copy(trans)) < 0)
13458 goto error;
13459 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
13460 isl_mat_copy(trans)) < 0)
13461 goto error;
13463 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
13464 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
13466 isl_mat_free(trans);
13467 return bmap;
13468 error:
13469 isl_mat_free(trans);
13470 isl_basic_map_free(bmap);
13471 return NULL;
13474 /* Replace the variables x of type "type" starting at "first" in "bset"
13475 * by x' with x = M x' with M the matrix trans.
13476 * That is, replace the corresponding coefficients c by c M.
13478 * The transformation matrix should be a square matrix.
13480 __isl_give isl_basic_set *isl_basic_set_transform_dims(
13481 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
13482 __isl_take isl_mat *trans)
13484 return isl_basic_map_transform_dims(bset, type, first, trans);