isl_basic_map_swap_div: use isl_basic_map_var_offset
[isl.git] / isl_map.c
blob725992d2038387fe80b1d2306f51fdae3e74d1ec
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>
47 #include <isl_printer_private.h>
49 #include <bset_to_bmap.c>
50 #include <bset_from_bmap.c>
51 #include <set_to_map.c>
52 #include <set_from_map.c>
54 /* Treat "bset" as a basic map.
55 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
56 * this function performs a redundant cast.
58 static __isl_keep const isl_basic_map *const_bset_to_bmap(
59 __isl_keep const isl_basic_set *bset)
61 return (const isl_basic_map *) bset;
64 static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
66 switch (type) {
67 case isl_dim_param: return dim->nparam;
68 case isl_dim_in: return dim->n_in;
69 case isl_dim_out: return dim->n_out;
70 case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
71 default: return 0;
75 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
77 switch (type) {
78 case isl_dim_param: return 1;
79 case isl_dim_in: return 1 + dim->nparam;
80 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
81 default: return 0;
85 unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
86 enum isl_dim_type type)
88 if (!bmap)
89 return 0;
90 switch (type) {
91 case isl_dim_cst: return 1;
92 case isl_dim_param:
93 case isl_dim_in:
94 case isl_dim_out: return isl_space_dim(bmap->dim, type);
95 case isl_dim_div: return bmap->n_div;
96 case isl_dim_all: return isl_basic_map_total_dim(bmap);
97 default: return 0;
101 /* Return the space of "map".
103 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
105 return map ? map->dim : NULL;
108 /* Return the space of "set".
110 __isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
112 return isl_map_peek_space(set_to_map(set));
115 unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
117 return map ? n(map->dim, type) : 0;
120 unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
122 return set ? n(set->dim, type) : 0;
125 /* Return the position of the variables of the given type
126 * within the sequence of variables of "bmap".
128 int isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
129 enum isl_dim_type type)
131 isl_space *space;
133 space = isl_basic_map_peek_space(bmap);
134 if (!space)
135 return -1;
137 switch (type) {
138 case isl_dim_param:
139 case isl_dim_in:
140 case isl_dim_out: return isl_space_offset(space, type);
141 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
142 case isl_dim_cst:
143 default:
144 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
145 "invalid dimension type", return -1);
149 /* Return the position of the coefficients of the variables of the given type
150 * within the sequence of coefficients of "bmap".
152 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
153 enum isl_dim_type type)
155 switch (type) {
156 case isl_dim_cst: return 0;
157 case isl_dim_param:
158 case isl_dim_in:
159 case isl_dim_out:
160 case isl_dim_div: return 1 + isl_basic_map_var_offset(bmap, type);
161 default: return 0;
165 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
166 enum isl_dim_type type)
168 return isl_basic_map_offset(bset, type);
171 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
173 return pos(map->dim, type);
176 unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
177 enum isl_dim_type type)
179 return isl_basic_map_dim(bset, type);
182 unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
184 return isl_basic_set_dim(bset, isl_dim_set);
187 unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
189 return isl_basic_set_dim(bset, isl_dim_param);
192 unsigned isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
194 return isl_basic_map_total_dim(const_bset_to_bmap(bset));
197 unsigned isl_set_n_dim(__isl_keep isl_set *set)
199 return isl_set_dim(set, isl_dim_set);
202 unsigned isl_set_n_param(__isl_keep isl_set *set)
204 return isl_set_dim(set, isl_dim_param);
207 unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap)
209 return bmap ? bmap->dim->n_in : 0;
212 unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap)
214 return bmap ? bmap->dim->n_out : 0;
217 unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap)
219 return bmap ? bmap->dim->nparam : 0;
222 unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap)
224 return bmap ? bmap->n_div : 0;
227 unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
229 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
232 unsigned isl_map_n_in(__isl_keep const isl_map *map)
234 return map ? map->dim->n_in : 0;
237 unsigned isl_map_n_out(__isl_keep const isl_map *map)
239 return map ? map->dim->n_out : 0;
242 unsigned isl_map_n_param(__isl_keep const isl_map *map)
244 return map ? map->dim->nparam : 0;
247 /* Return the number of equality constraints in the description of "bmap".
248 * Return -1 on error.
250 int isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
252 if (!bmap)
253 return -1;
254 return bmap->n_eq;
257 /* Return the number of equality constraints in the description of "bset".
258 * Return -1 on error.
260 int isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
262 return isl_basic_map_n_equality(bset_to_bmap(bset));
265 /* Return the number of inequality constraints in the description of "bmap".
266 * Return -1 on error.
268 int isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
270 if (!bmap)
271 return -1;
272 return bmap->n_ineq;
275 /* Return the number of inequality constraints in the description of "bset".
276 * Return -1 on error.
278 int isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
280 return isl_basic_map_n_inequality(bset_to_bmap(bset));
283 /* Do "bmap1" and "bmap2" have the same parameters?
285 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
286 __isl_keep isl_basic_map *bmap2)
288 isl_space *space1, *space2;
290 space1 = isl_basic_map_peek_space(bmap1);
291 space2 = isl_basic_map_peek_space(bmap2);
292 return isl_space_has_equal_params(space1, space2);
295 /* Do "map1" and "map2" have the same parameters?
297 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
298 __isl_keep isl_map *map2)
300 isl_space *space1, *space2;
302 space1 = isl_map_peek_space(map1);
303 space2 = isl_map_peek_space(map2);
304 return isl_space_has_equal_params(space1, space2);
307 /* Do "map" and "set" have the same parameters?
309 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
310 __isl_keep isl_set *set)
312 return isl_map_has_equal_params(map, set_to_map(set));
315 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
316 __isl_keep isl_set *set)
318 isl_bool m;
319 if (!map || !set)
320 return isl_bool_error;
321 m = isl_map_has_equal_params(map, set_to_map(set));
322 if (m < 0 || !m)
323 return m;
324 return isl_space_tuple_is_equal(map->dim, isl_dim_in,
325 set->dim, isl_dim_set);
328 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
329 __isl_keep isl_basic_set *bset)
331 isl_bool m;
332 if (!bmap || !bset)
333 return isl_bool_error;
334 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
335 if (m < 0 || !m)
336 return m;
337 return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
338 bset->dim, isl_dim_set);
341 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
342 __isl_keep isl_set *set)
344 isl_bool m;
345 if (!map || !set)
346 return isl_bool_error;
347 m = isl_map_has_equal_params(map, set_to_map(set));
348 if (m < 0 || !m)
349 return m;
350 return isl_space_tuple_is_equal(map->dim, isl_dim_out,
351 set->dim, isl_dim_set);
354 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
355 __isl_keep isl_basic_set *bset)
357 isl_bool m;
358 if (!bmap || !bset)
359 return isl_bool_error;
360 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
361 if (m < 0 || !m)
362 return m;
363 return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
364 bset->dim, isl_dim_set);
367 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
369 return bmap ? bmap->ctx : NULL;
372 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
374 return bset ? bset->ctx : NULL;
377 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
379 return map ? map->ctx : NULL;
382 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
384 return set ? set->ctx : NULL;
387 /* Return the space of "bmap".
389 __isl_keep isl_space *isl_basic_map_peek_space(
390 __isl_keep const isl_basic_map *bmap)
392 return bmap ? bmap->dim : NULL;
395 /* Return the space of "bset".
397 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
399 return isl_basic_map_peek_space(bset_to_bmap(bset));
402 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
404 return isl_space_copy(isl_basic_map_peek_space(bmap));
407 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
409 return isl_basic_map_get_space(bset_to_bmap(bset));
412 /* Extract the divs in "bmap" as a matrix.
414 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
416 int i;
417 isl_ctx *ctx;
418 isl_mat *div;
419 int v_div;
420 unsigned cols;
422 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
423 if (v_div < 0)
424 return NULL;
426 ctx = isl_basic_map_get_ctx(bmap);
427 cols = 1 + 1 + v_div + bmap->n_div;
428 div = isl_mat_alloc(ctx, bmap->n_div, cols);
429 if (!div)
430 return NULL;
432 for (i = 0; i < bmap->n_div; ++i)
433 isl_seq_cpy(div->row[i], bmap->div[i], cols);
435 return div;
438 /* Extract the divs in "bset" as a matrix.
440 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
442 return isl_basic_map_get_divs(bset);
445 __isl_give isl_local_space *isl_basic_map_get_local_space(
446 __isl_keep isl_basic_map *bmap)
448 isl_mat *div;
450 if (!bmap)
451 return NULL;
453 div = isl_basic_map_get_divs(bmap);
454 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
457 __isl_give isl_local_space *isl_basic_set_get_local_space(
458 __isl_keep isl_basic_set *bset)
460 return isl_basic_map_get_local_space(bset);
463 /* For each known div d = floor(f/m), add the constraints
465 * f - m d >= 0
466 * -(f-(m-1)) + m d >= 0
468 * Do not finalize the result.
470 static __isl_give isl_basic_map *add_known_div_constraints(
471 __isl_take isl_basic_map *bmap)
473 int i;
474 unsigned n_div;
476 if (!bmap)
477 return NULL;
478 n_div = isl_basic_map_dim(bmap, isl_dim_div);
479 if (n_div == 0)
480 return bmap;
481 bmap = isl_basic_map_cow(bmap);
482 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
483 if (!bmap)
484 return NULL;
485 for (i = 0; i < n_div; ++i) {
486 if (isl_int_is_zero(bmap->div[i][0]))
487 continue;
488 bmap = isl_basic_map_add_div_constraints(bmap, i);
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 isl_space *space = isl_basic_map_peek_space(bmap);
1148 unsigned n_var = isl_space_dim(space, isl_dim_all);
1149 size_t row_size = 1 + n_var + extra;
1151 bmap->ctx = ctx;
1152 isl_ctx_ref(ctx);
1154 if (!space)
1155 return isl_basic_map_free(bmap);
1157 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1158 if (isl_blk_is_error(bmap->block))
1159 goto error;
1161 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1162 if ((n_ineq + n_eq) && !bmap->ineq)
1163 goto error;
1165 if (extra == 0) {
1166 bmap->block2 = isl_blk_empty();
1167 bmap->div = NULL;
1168 } else {
1169 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1170 if (isl_blk_is_error(bmap->block2))
1171 goto error;
1173 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1174 if (!bmap->div)
1175 goto error;
1178 for (i = 0; i < n_ineq + n_eq; ++i)
1179 bmap->ineq[i] = bmap->block.data + i * row_size;
1181 for (i = 0; i < extra; ++i)
1182 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1184 bmap->ref = 1;
1185 bmap->flags = 0;
1186 bmap->c_size = n_eq + n_ineq;
1187 bmap->eq = bmap->ineq + n_ineq;
1188 bmap->extra = extra;
1189 bmap->n_eq = 0;
1190 bmap->n_ineq = 0;
1191 bmap->n_div = 0;
1192 bmap->sample = NULL;
1194 return bmap;
1195 error:
1196 isl_basic_map_free(bmap);
1197 return NULL;
1200 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1201 unsigned nparam, unsigned dim, unsigned extra,
1202 unsigned n_eq, unsigned n_ineq)
1204 struct isl_basic_map *bmap;
1205 isl_space *space;
1207 space = isl_space_set_alloc(ctx, nparam, dim);
1208 if (!space)
1209 return NULL;
1211 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1212 return bset_from_bmap(bmap);
1215 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1216 unsigned extra, unsigned n_eq, unsigned n_ineq)
1218 struct isl_basic_map *bmap;
1219 if (!dim)
1220 return NULL;
1221 isl_assert(dim->ctx, dim->n_in == 0, goto error);
1222 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1223 return bset_from_bmap(bmap);
1224 error:
1225 isl_space_free(dim);
1226 return NULL;
1229 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1230 unsigned extra, unsigned n_eq, unsigned n_ineq)
1232 struct isl_basic_map *bmap;
1234 if (!space)
1235 return NULL;
1236 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1237 if (!bmap)
1238 goto error;
1239 bmap->dim = space;
1241 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1242 error:
1243 isl_space_free(space);
1244 return NULL;
1247 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1248 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1249 unsigned n_eq, unsigned n_ineq)
1251 struct isl_basic_map *bmap;
1252 isl_space *dim;
1254 dim = isl_space_alloc(ctx, nparam, in, out);
1255 if (!dim)
1256 return NULL;
1258 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1259 return bmap;
1262 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1263 __isl_keep isl_basic_map *src)
1265 int i;
1266 unsigned total = isl_basic_map_total_dim(src);
1268 if (!dst)
1269 return NULL;
1271 for (i = 0; i < src->n_eq; ++i) {
1272 int j = isl_basic_map_alloc_equality(dst);
1273 if (j < 0)
1274 return isl_basic_map_free(dst);
1275 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1278 for (i = 0; i < src->n_ineq; ++i) {
1279 int j = isl_basic_map_alloc_inequality(dst);
1280 if (j < 0)
1281 return isl_basic_map_free(dst);
1282 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1285 for (i = 0; i < src->n_div; ++i) {
1286 int j = isl_basic_map_alloc_div(dst);
1287 if (j < 0)
1288 return isl_basic_map_free(dst);
1289 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1291 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1292 return dst;
1295 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1297 struct isl_basic_map *dup;
1299 if (!bmap)
1300 return NULL;
1301 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1302 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1303 dup = dup_constraints(dup, bmap);
1304 if (!dup)
1305 return NULL;
1306 dup->flags = bmap->flags;
1307 dup->sample = isl_vec_copy(bmap->sample);
1308 return dup;
1311 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1313 struct isl_basic_map *dup;
1315 dup = isl_basic_map_dup(bset_to_bmap(bset));
1316 return bset_from_bmap(dup);
1319 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1321 if (!bset)
1322 return NULL;
1324 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1325 bset->ref++;
1326 return bset;
1328 return isl_basic_set_dup(bset);
1331 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1333 if (!set)
1334 return NULL;
1336 set->ref++;
1337 return set;
1340 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1342 if (!bmap)
1343 return NULL;
1345 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1346 bmap->ref++;
1347 return bmap;
1349 bmap = isl_basic_map_dup(bmap);
1350 if (bmap)
1351 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1352 return bmap;
1355 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1357 if (!map)
1358 return NULL;
1360 map->ref++;
1361 return map;
1364 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1366 if (!bmap)
1367 return NULL;
1369 if (--bmap->ref > 0)
1370 return NULL;
1372 isl_ctx_deref(bmap->ctx);
1373 free(bmap->div);
1374 isl_blk_free(bmap->ctx, bmap->block2);
1375 free(bmap->ineq);
1376 isl_blk_free(bmap->ctx, bmap->block);
1377 isl_vec_free(bmap->sample);
1378 isl_space_free(bmap->dim);
1379 free(bmap);
1381 return NULL;
1384 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1386 return isl_basic_map_free(bset_to_bmap(bset));
1389 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1391 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1394 /* Check that "bset" does not involve any parameters.
1396 isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1398 if (!bset)
1399 return isl_stat_error;
1400 if (isl_basic_set_dim(bset, isl_dim_param) != 0)
1401 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1402 "basic set should not have any parameters",
1403 return isl_stat_error);
1404 return isl_stat_ok;
1407 /* Check that "bset" does not involve any local variables.
1409 isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1411 if (!bset)
1412 return isl_stat_error;
1413 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
1414 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1415 "basic set should not have any local variables",
1416 return isl_stat_error);
1417 return isl_stat_ok;
1420 /* Check that "map" has only named parameters, reporting an error
1421 * if it does not.
1423 isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1425 return isl_space_check_named_params(isl_map_peek_space(map));
1428 /* Check that "bmap" has only named parameters, reporting an error
1429 * if it does not.
1431 static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
1433 return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
1436 /* Check that "bmap1" and "bmap2" have the same parameters,
1437 * reporting an error if they do not.
1439 static isl_stat isl_basic_map_check_equal_params(
1440 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1442 isl_bool match;
1444 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1445 if (match < 0)
1446 return isl_stat_error;
1447 if (!match)
1448 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1449 "parameters don't match", return isl_stat_error);
1450 return isl_stat_ok;
1453 __isl_give isl_map *isl_map_align_params_map_map_and(
1454 __isl_take isl_map *map1, __isl_take isl_map *map2,
1455 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1456 __isl_take isl_map *map2))
1458 if (!map1 || !map2)
1459 goto error;
1460 if (isl_map_has_equal_params(map1, map2))
1461 return fn(map1, map2);
1462 if (isl_map_check_named_params(map1) < 0)
1463 goto error;
1464 if (isl_map_check_named_params(map2) < 0)
1465 goto error;
1466 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1467 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1468 return fn(map1, map2);
1469 error:
1470 isl_map_free(map1);
1471 isl_map_free(map2);
1472 return NULL;
1475 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1476 __isl_keep isl_map *map2,
1477 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1479 isl_bool r;
1481 if (!map1 || !map2)
1482 return isl_bool_error;
1483 if (isl_map_has_equal_params(map1, map2))
1484 return fn(map1, map2);
1485 if (isl_map_check_named_params(map1) < 0)
1486 return isl_bool_error;
1487 if (isl_map_check_named_params(map2) < 0)
1488 return isl_bool_error;
1489 map1 = isl_map_copy(map1);
1490 map2 = isl_map_copy(map2);
1491 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1492 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1493 r = fn(map1, map2);
1494 isl_map_free(map1);
1495 isl_map_free(map2);
1496 return r;
1499 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1501 struct isl_ctx *ctx;
1502 if (!bmap)
1503 return -1;
1504 ctx = bmap->ctx;
1505 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1506 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1507 return -1);
1508 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1509 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1510 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1511 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1512 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1513 isl_int *t;
1514 int j = isl_basic_map_alloc_inequality(bmap);
1515 if (j < 0)
1516 return -1;
1517 t = bmap->ineq[j];
1518 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1519 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1520 bmap->eq[-1] = t;
1521 bmap->n_eq++;
1522 bmap->n_ineq--;
1523 bmap->eq--;
1524 return 0;
1526 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1527 bmap->extra - bmap->n_div);
1528 return bmap->n_eq++;
1531 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1533 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1536 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1538 if (!bmap)
1539 return -1;
1540 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1541 bmap->n_eq -= n;
1542 return 0;
1545 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1547 return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1550 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1552 isl_int *t;
1553 if (!bmap)
1554 return -1;
1555 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1557 if (pos != bmap->n_eq - 1) {
1558 t = bmap->eq[pos];
1559 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1560 bmap->eq[bmap->n_eq - 1] = t;
1562 bmap->n_eq--;
1563 return 0;
1566 /* Turn inequality "pos" of "bmap" into an equality.
1568 * In particular, we move the inequality in front of the equalities
1569 * and move the last inequality in the position of the moved inequality.
1570 * Note that isl_tab_make_equalities_explicit depends on this particular
1571 * change in the ordering of the constraints.
1573 void isl_basic_map_inequality_to_equality(
1574 struct isl_basic_map *bmap, unsigned pos)
1576 isl_int *t;
1578 t = bmap->ineq[pos];
1579 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1580 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1581 bmap->eq[-1] = t;
1582 bmap->n_eq++;
1583 bmap->n_ineq--;
1584 bmap->eq--;
1585 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1586 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1587 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1588 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1591 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1593 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1596 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1598 struct isl_ctx *ctx;
1599 if (!bmap)
1600 return -1;
1601 ctx = bmap->ctx;
1602 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1603 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1604 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1605 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1606 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1607 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1608 1 + isl_basic_map_total_dim(bmap),
1609 bmap->extra - bmap->n_div);
1610 return bmap->n_ineq++;
1613 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1615 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1618 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1620 if (!bmap)
1621 return -1;
1622 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1623 bmap->n_ineq -= n;
1624 return 0;
1627 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1629 return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1632 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1634 isl_int *t;
1635 if (!bmap)
1636 return -1;
1637 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1639 if (pos != bmap->n_ineq - 1) {
1640 t = bmap->ineq[pos];
1641 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1642 bmap->ineq[bmap->n_ineq - 1] = t;
1643 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1645 bmap->n_ineq--;
1646 return 0;
1649 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1651 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1654 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1655 isl_int *eq)
1657 isl_bool empty;
1658 int k;
1660 empty = isl_basic_map_plain_is_empty(bmap);
1661 if (empty < 0)
1662 return isl_basic_map_free(bmap);
1663 if (empty)
1664 return bmap;
1666 bmap = isl_basic_map_cow(bmap);
1667 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1668 if (!bmap)
1669 return NULL;
1670 k = isl_basic_map_alloc_equality(bmap);
1671 if (k < 0)
1672 goto error;
1673 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1674 return bmap;
1675 error:
1676 isl_basic_map_free(bmap);
1677 return NULL;
1680 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1681 isl_int *eq)
1683 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1686 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1687 isl_int *ineq)
1689 int k;
1691 bmap = isl_basic_map_cow(bmap);
1692 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1693 if (!bmap)
1694 return NULL;
1695 k = isl_basic_map_alloc_inequality(bmap);
1696 if (k < 0)
1697 goto error;
1698 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1699 return bmap;
1700 error:
1701 isl_basic_map_free(bmap);
1702 return NULL;
1705 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1706 isl_int *ineq)
1708 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1711 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1713 if (!bmap)
1714 return -1;
1715 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1716 isl_seq_clr(bmap->div[bmap->n_div] +
1717 1 + 1 + isl_basic_map_total_dim(bmap),
1718 bmap->extra - bmap->n_div);
1719 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1720 return bmap->n_div++;
1723 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1725 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1728 #undef TYPE
1729 #define TYPE isl_basic_map
1730 #include "check_type_range_templ.c"
1732 /* Check that there are "n" dimensions of type "type" starting at "first"
1733 * in "bset".
1735 isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1736 enum isl_dim_type type, unsigned first, unsigned n)
1738 return isl_basic_map_check_range(bset_to_bmap(bset),
1739 type, first, n);
1742 /* Insert an extra integer division, prescribed by "div", to "bmap"
1743 * at (integer division) position "pos".
1745 * The integer division is first added at the end and then moved
1746 * into the right position.
1748 __isl_give isl_basic_map *isl_basic_map_insert_div(
1749 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1751 int i, k;
1753 bmap = isl_basic_map_cow(bmap);
1754 if (!bmap || !div)
1755 return isl_basic_map_free(bmap);
1757 if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1758 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1759 "unexpected size", return isl_basic_map_free(bmap));
1760 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1761 return isl_basic_map_free(bmap);
1763 bmap = isl_basic_map_extend_space(bmap,
1764 isl_basic_map_get_space(bmap), 1, 0, 2);
1765 k = isl_basic_map_alloc_div(bmap);
1766 if (k < 0)
1767 return isl_basic_map_free(bmap);
1768 isl_seq_cpy(bmap->div[k], div->el, div->size);
1769 isl_int_set_si(bmap->div[k][div->size], 0);
1771 for (i = k; i > pos; --i)
1772 bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1774 return bmap;
1777 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1779 if (!bmap)
1780 return isl_stat_error;
1781 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1782 bmap->n_div -= n;
1783 return isl_stat_ok;
1786 static __isl_give isl_basic_map *add_constraints(
1787 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1788 unsigned i_pos, unsigned o_pos)
1790 unsigned total, n_param, n_in, o_in, n_out, o_out, n_div;
1791 isl_ctx *ctx;
1792 isl_space *space;
1793 struct isl_dim_map *dim_map;
1795 space = isl_basic_map_peek_space(bmap2);
1796 if (!bmap1 || !space)
1797 goto error;
1799 total = isl_basic_map_dim(bmap1, isl_dim_all);
1800 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1801 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1802 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1803 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1804 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1805 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1806 ctx = isl_basic_map_get_ctx(bmap1);
1807 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1808 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1809 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1810 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1811 isl_dim_map_div(dim_map, bmap2, total);
1813 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1814 error:
1815 isl_basic_map_free(bmap1);
1816 isl_basic_map_free(bmap2);
1817 return NULL;
1820 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1821 struct isl_basic_set *bset2, unsigned pos)
1823 return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1824 bset_to_bmap(bset2), 0, pos));
1827 __isl_give isl_basic_map *isl_basic_map_extend_space(
1828 __isl_take isl_basic_map *base, __isl_take isl_space *space,
1829 unsigned extra, unsigned n_eq, unsigned n_ineq)
1831 struct isl_basic_map *ext;
1832 unsigned flags;
1833 int dims_ok;
1835 if (!space)
1836 goto error;
1838 if (!base)
1839 goto error;
1841 dims_ok = isl_space_is_equal(base->dim, space) &&
1842 base->extra >= base->n_div + extra;
1844 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1845 room_for_ineq(base, n_ineq)) {
1846 isl_space_free(space);
1847 return base;
1850 isl_assert(base->ctx, base->dim->nparam <= space->nparam, goto error);
1851 isl_assert(base->ctx, base->dim->n_in <= space->n_in, goto error);
1852 isl_assert(base->ctx, base->dim->n_out <= space->n_out, goto error);
1853 extra += base->extra;
1854 n_eq += base->n_eq;
1855 n_ineq += base->n_ineq;
1857 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1858 space = NULL;
1859 if (!ext)
1860 goto error;
1862 if (dims_ok)
1863 ext->sample = isl_vec_copy(base->sample);
1864 flags = base->flags;
1865 ext = add_constraints(ext, base, 0, 0);
1866 if (ext) {
1867 ext->flags = flags;
1868 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1871 return ext;
1873 error:
1874 isl_space_free(space);
1875 isl_basic_map_free(base);
1876 return NULL;
1879 __isl_give isl_basic_set *isl_basic_set_extend_space(
1880 __isl_take isl_basic_set *base,
1881 __isl_take isl_space *dim, unsigned extra,
1882 unsigned n_eq, unsigned n_ineq)
1884 return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1885 dim, extra, n_eq, n_ineq));
1888 struct isl_basic_map *isl_basic_map_extend_constraints(
1889 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1891 if (!base)
1892 return NULL;
1893 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1894 0, n_eq, n_ineq);
1897 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1898 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1899 unsigned n_eq, unsigned n_ineq)
1901 struct isl_basic_map *bmap;
1902 isl_space *dim;
1904 if (!base)
1905 return NULL;
1906 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1907 if (!dim)
1908 goto error;
1910 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1911 return bmap;
1912 error:
1913 isl_basic_map_free(base);
1914 return NULL;
1917 struct isl_basic_set *isl_basic_set_extend_constraints(
1918 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1920 isl_basic_map *bmap = bset_to_bmap(base);
1921 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1922 return bset_from_bmap(bmap);
1925 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1927 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1930 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1932 if (!bmap)
1933 return NULL;
1935 if (bmap->ref > 1) {
1936 bmap->ref--;
1937 bmap = isl_basic_map_dup(bmap);
1939 if (bmap) {
1940 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1941 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1943 return bmap;
1946 /* Clear all cached information in "map", either because it is about
1947 * to be modified or because it is being freed.
1948 * Always return the same pointer that is passed in.
1949 * This is needed for the use in isl_map_free.
1951 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1953 isl_basic_map_free(map->cached_simple_hull[0]);
1954 isl_basic_map_free(map->cached_simple_hull[1]);
1955 map->cached_simple_hull[0] = NULL;
1956 map->cached_simple_hull[1] = NULL;
1957 return map;
1960 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
1962 return isl_map_cow(set);
1965 /* Return an isl_map that is equal to "map" and that has only
1966 * a single reference.
1968 * If the original input already has only one reference, then
1969 * simply return it, but clear all cached information, since
1970 * it may be rendered invalid by the operations that will be
1971 * performed on the result.
1973 * Otherwise, create a duplicate (without any cached information).
1975 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
1977 if (!map)
1978 return NULL;
1980 if (map->ref == 1)
1981 return clear_caches(map);
1982 map->ref--;
1983 return isl_map_dup(map);
1986 static void swap_vars(struct isl_blk blk, isl_int *a,
1987 unsigned a_len, unsigned b_len)
1989 isl_seq_cpy(blk.data, a+a_len, b_len);
1990 isl_seq_cpy(blk.data+b_len, a, a_len);
1991 isl_seq_cpy(a, blk.data, b_len+a_len);
1994 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1995 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1997 int i;
1998 struct isl_blk blk;
2000 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
2001 goto error;
2003 if (n1 == 0 || n2 == 0)
2004 return bmap;
2006 bmap = isl_basic_map_cow(bmap);
2007 if (!bmap)
2008 return NULL;
2010 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2011 if (isl_blk_is_error(blk))
2012 goto error;
2014 for (i = 0; i < bmap->n_eq; ++i)
2015 swap_vars(blk,
2016 bmap->eq[i] + pos, n1, n2);
2018 for (i = 0; i < bmap->n_ineq; ++i)
2019 swap_vars(blk,
2020 bmap->ineq[i] + pos, n1, n2);
2022 for (i = 0; i < bmap->n_div; ++i)
2023 swap_vars(blk,
2024 bmap->div[i]+1 + pos, n1, n2);
2026 isl_blk_free(bmap->ctx, blk);
2028 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2029 bmap = isl_basic_map_gauss(bmap, NULL);
2030 return isl_basic_map_finalize(bmap);
2031 error:
2032 isl_basic_map_free(bmap);
2033 return NULL;
2036 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2037 __isl_take isl_basic_map *bmap)
2039 int i = 0;
2040 unsigned total;
2041 if (!bmap)
2042 goto error;
2043 total = isl_basic_map_total_dim(bmap);
2044 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2045 return isl_basic_map_free(bmap);
2046 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2047 if (bmap->n_eq > 0)
2048 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
2049 else {
2050 i = isl_basic_map_alloc_equality(bmap);
2051 if (i < 0)
2052 goto error;
2054 isl_int_set_si(bmap->eq[i][0], 1);
2055 isl_seq_clr(bmap->eq[i]+1, total);
2056 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2057 isl_vec_free(bmap->sample);
2058 bmap->sample = NULL;
2059 return isl_basic_map_finalize(bmap);
2060 error:
2061 isl_basic_map_free(bmap);
2062 return NULL;
2065 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2066 __isl_take isl_basic_set *bset)
2068 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2071 __isl_give isl_basic_map *isl_basic_map_set_rational(
2072 __isl_take isl_basic_map *bmap)
2074 if (!bmap)
2075 return NULL;
2077 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2078 return bmap;
2080 bmap = isl_basic_map_cow(bmap);
2081 if (!bmap)
2082 return NULL;
2084 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2086 return isl_basic_map_finalize(bmap);
2089 __isl_give isl_basic_set *isl_basic_set_set_rational(
2090 __isl_take isl_basic_set *bset)
2092 return isl_basic_map_set_rational(bset);
2095 __isl_give isl_basic_set *isl_basic_set_set_integral(
2096 __isl_take isl_basic_set *bset)
2098 if (!bset)
2099 return NULL;
2101 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2102 return bset;
2104 bset = isl_basic_set_cow(bset);
2105 if (!bset)
2106 return NULL;
2108 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2110 return isl_basic_set_finalize(bset);
2113 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2115 int i;
2117 map = isl_map_cow(map);
2118 if (!map)
2119 return NULL;
2120 for (i = 0; i < map->n; ++i) {
2121 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2122 if (!map->p[i])
2123 goto error;
2125 return map;
2126 error:
2127 isl_map_free(map);
2128 return NULL;
2131 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2133 return isl_map_set_rational(set);
2136 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2137 * of "bmap").
2139 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2141 isl_int *t = bmap->div[a];
2142 bmap->div[a] = bmap->div[b];
2143 bmap->div[b] = t;
2146 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2147 * div definitions accordingly.
2149 __isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2150 int a, int b)
2152 int i;
2153 int off;
2155 off = isl_basic_map_var_offset(bmap, isl_dim_div);
2156 if (off < 0)
2157 return isl_basic_map_free(bmap);
2159 swap_div(bmap, a, b);
2161 for (i = 0; i < bmap->n_eq; ++i)
2162 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2164 for (i = 0; i < bmap->n_ineq; ++i)
2165 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2167 for (i = 0; i < bmap->n_div; ++i)
2168 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2169 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2171 return bmap;
2174 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2176 isl_seq_cpy(c, c + n, rem);
2177 isl_seq_clr(c + rem, n);
2180 /* Drop n dimensions starting at first.
2182 * In principle, this frees up some extra variables as the number
2183 * of columns remains constant, but we would have to extend
2184 * the div array too as the number of rows in this array is assumed
2185 * to be equal to extra.
2187 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2188 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2190 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2193 /* Move "n" divs starting at "first" to the end of the list of divs.
2195 static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
2196 unsigned first, unsigned n)
2198 isl_int **div;
2199 int i;
2201 if (first + n == bmap->n_div)
2202 return bmap;
2204 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2205 if (!div)
2206 goto error;
2207 for (i = 0; i < n; ++i)
2208 div[i] = bmap->div[first + i];
2209 for (i = 0; i < bmap->n_div - first - n; ++i)
2210 bmap->div[first + i] = bmap->div[first + n + i];
2211 for (i = 0; i < n; ++i)
2212 bmap->div[bmap->n_div - n + i] = div[i];
2213 free(div);
2214 return bmap;
2215 error:
2216 isl_basic_map_free(bmap);
2217 return NULL;
2220 #undef TYPE
2221 #define TYPE isl_map
2222 static
2223 #include "check_type_range_templ.c"
2225 /* Check that there are "n" dimensions of type "type" starting at "first"
2226 * in "set".
2228 static isl_stat isl_set_check_range(__isl_keep isl_set *set,
2229 enum isl_dim_type type, unsigned first, unsigned n)
2231 return isl_map_check_range(set_to_map(set), type, first, n);
2234 /* Drop "n" dimensions of type "type" starting at "first".
2235 * Perform the core computation, without cowing or
2236 * simplifying and finalizing the result.
2238 * In principle, this frees up some extra variables as the number
2239 * of columns remains constant, but we would have to extend
2240 * the div array too as the number of rows in this array is assumed
2241 * to be equal to extra.
2243 __isl_give isl_basic_map *isl_basic_map_drop_core(
2244 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2245 unsigned first, unsigned n)
2247 int i;
2248 unsigned offset;
2249 unsigned left;
2251 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2252 return isl_basic_map_free(bmap);
2254 offset = isl_basic_map_offset(bmap, type) + first;
2255 left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
2256 for (i = 0; i < bmap->n_eq; ++i)
2257 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2259 for (i = 0; i < bmap->n_ineq; ++i)
2260 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2262 for (i = 0; i < bmap->n_div; ++i)
2263 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2265 if (type == isl_dim_div) {
2266 bmap = move_divs_last(bmap, first, n);
2267 if (!bmap)
2268 return NULL;
2269 if (isl_basic_map_free_div(bmap, n) < 0)
2270 return isl_basic_map_free(bmap);
2271 } else
2272 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2273 if (!bmap->dim)
2274 return isl_basic_map_free(bmap);
2276 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2277 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2278 return bmap;
2281 /* Drop "n" dimensions of type "type" starting at "first".
2283 * In principle, this frees up some extra variables as the number
2284 * of columns remains constant, but we would have to extend
2285 * the div array too as the number of rows in this array is assumed
2286 * to be equal to extra.
2288 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2289 enum isl_dim_type type, unsigned first, unsigned n)
2291 if (!bmap)
2292 return NULL;
2293 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2294 return bmap;
2296 bmap = isl_basic_map_cow(bmap);
2297 if (!bmap)
2298 return NULL;
2300 bmap = isl_basic_map_drop_core(bmap, type, first, n);
2302 bmap = isl_basic_map_simplify(bmap);
2303 return isl_basic_map_finalize(bmap);
2306 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2307 enum isl_dim_type type, unsigned first, unsigned n)
2309 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2310 type, first, n));
2313 /* No longer consider "map" to be normalized.
2315 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2317 if (!map)
2318 return NULL;
2319 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2320 return map;
2323 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2324 enum isl_dim_type type, unsigned first, unsigned n)
2326 int i;
2328 if (isl_map_check_range(map, type, first, n) < 0)
2329 return isl_map_free(map);
2331 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2332 return map;
2333 map = isl_map_cow(map);
2334 if (!map)
2335 goto error;
2336 map->dim = isl_space_drop_dims(map->dim, type, first, n);
2337 if (!map->dim)
2338 goto error;
2340 for (i = 0; i < map->n; ++i) {
2341 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2342 if (!map->p[i])
2343 goto error;
2345 map = isl_map_unmark_normalized(map);
2347 return map;
2348 error:
2349 isl_map_free(map);
2350 return NULL;
2353 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2354 enum isl_dim_type type, unsigned first, unsigned n)
2356 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2359 /* Drop the integer division at position "div", which is assumed
2360 * not to appear in any of the constraints or
2361 * in any of the other integer divisions.
2363 * Since the integer division is redundant, there is no need to cow.
2365 __isl_give isl_basic_map *isl_basic_map_drop_div(
2366 __isl_take isl_basic_map *bmap, unsigned div)
2368 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2371 /* Eliminate the specified n dimensions starting at first from the
2372 * constraints, without removing the dimensions from the space.
2373 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2375 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2376 enum isl_dim_type type, unsigned first, unsigned n)
2378 int i;
2380 if (n == 0)
2381 return map;
2383 if (isl_map_check_range(map, type, first, n) < 0)
2384 return isl_map_free(map);
2386 map = isl_map_cow(map);
2387 if (!map)
2388 return NULL;
2390 for (i = 0; i < map->n; ++i) {
2391 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2392 if (!map->p[i])
2393 goto error;
2395 return map;
2396 error:
2397 isl_map_free(map);
2398 return NULL;
2401 /* Eliminate the specified n dimensions starting at first from the
2402 * constraints, without removing the dimensions from the space.
2403 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2405 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2406 enum isl_dim_type type, unsigned first, unsigned n)
2408 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2411 /* Eliminate the specified n dimensions starting at first from the
2412 * constraints, without removing the dimensions from the space.
2413 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2415 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2416 unsigned first, unsigned n)
2418 return isl_set_eliminate(set, isl_dim_set, first, n);
2421 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2422 __isl_take isl_basic_map *bmap)
2424 if (!bmap)
2425 return NULL;
2426 bmap = isl_basic_map_eliminate_vars(bmap,
2427 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
2428 if (!bmap)
2429 return NULL;
2430 bmap->n_div = 0;
2431 return isl_basic_map_finalize(bmap);
2434 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2435 __isl_take isl_basic_set *bset)
2437 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2440 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2442 int i;
2444 if (!map)
2445 return NULL;
2446 if (map->n == 0)
2447 return map;
2449 map = isl_map_cow(map);
2450 if (!map)
2451 return NULL;
2453 for (i = 0; i < map->n; ++i) {
2454 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2455 if (!map->p[i])
2456 goto error;
2458 return map;
2459 error:
2460 isl_map_free(map);
2461 return NULL;
2464 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2466 return isl_map_remove_divs(set);
2469 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2470 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2471 unsigned first, unsigned n)
2473 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2474 return isl_basic_map_free(bmap);
2475 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2476 return bmap;
2477 bmap = isl_basic_map_eliminate_vars(bmap,
2478 isl_basic_map_offset(bmap, type) - 1 + first, n);
2479 if (!bmap)
2480 return bmap;
2481 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2482 return bmap;
2483 bmap = isl_basic_map_drop(bmap, type, first, n);
2484 return bmap;
2487 /* Return true if the definition of the given div (recursively) involves
2488 * any of the given variables.
2490 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2491 unsigned first, unsigned n)
2493 int i;
2494 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2496 if (isl_int_is_zero(bmap->div[div][0]))
2497 return isl_bool_false;
2498 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2499 return isl_bool_true;
2501 for (i = bmap->n_div - 1; i >= 0; --i) {
2502 isl_bool involves;
2504 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2505 continue;
2506 involves = div_involves_vars(bmap, i, first, n);
2507 if (involves < 0 || involves)
2508 return involves;
2511 return isl_bool_false;
2514 /* Try and add a lower and/or upper bound on "div" to "bmap"
2515 * based on inequality "i".
2516 * "total" is the total number of variables (excluding the divs).
2517 * "v" is a temporary object that can be used during the calculations.
2518 * If "lb" is set, then a lower bound should be constructed.
2519 * If "ub" is set, then an upper bound should be constructed.
2521 * The calling function has already checked that the inequality does not
2522 * reference "div", but we still need to check that the inequality is
2523 * of the right form. We'll consider the case where we want to construct
2524 * a lower bound. The construction of upper bounds is similar.
2526 * Let "div" be of the form
2528 * q = floor((a + f(x))/d)
2530 * We essentially check if constraint "i" is of the form
2532 * b + f(x) >= 0
2534 * so that we can use it to derive a lower bound on "div".
2535 * However, we allow a slightly more general form
2537 * b + g(x) >= 0
2539 * with the condition that the coefficients of g(x) - f(x) are all
2540 * divisible by d.
2541 * Rewriting this constraint as
2543 * 0 >= -b - g(x)
2545 * adding a + f(x) to both sides and dividing by d, we obtain
2547 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2549 * Taking the floor on both sides, we obtain
2551 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2553 * or
2555 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2557 * In the case of an upper bound, we construct the constraint
2559 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2562 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2563 __isl_take isl_basic_map *bmap, int div, int i,
2564 unsigned total, isl_int v, int lb, int ub)
2566 int j;
2568 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2569 if (lb) {
2570 isl_int_sub(v, bmap->ineq[i][1 + j],
2571 bmap->div[div][1 + 1 + j]);
2572 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2574 if (ub) {
2575 isl_int_add(v, bmap->ineq[i][1 + j],
2576 bmap->div[div][1 + 1 + j]);
2577 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2580 if (!lb && !ub)
2581 return bmap;
2583 bmap = isl_basic_map_cow(bmap);
2584 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2585 if (lb) {
2586 int k = isl_basic_map_alloc_inequality(bmap);
2587 if (k < 0)
2588 goto error;
2589 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2590 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2591 bmap->div[div][1 + j]);
2592 isl_int_cdiv_q(bmap->ineq[k][j],
2593 bmap->ineq[k][j], bmap->div[div][0]);
2595 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2597 if (ub) {
2598 int k = isl_basic_map_alloc_inequality(bmap);
2599 if (k < 0)
2600 goto error;
2601 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2602 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2603 bmap->div[div][1 + j]);
2604 isl_int_fdiv_q(bmap->ineq[k][j],
2605 bmap->ineq[k][j], bmap->div[div][0]);
2607 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2610 return bmap;
2611 error:
2612 isl_basic_map_free(bmap);
2613 return NULL;
2616 /* This function is called right before "div" is eliminated from "bmap"
2617 * using Fourier-Motzkin.
2618 * Look through the constraints of "bmap" for constraints on the argument
2619 * of the integer division and use them to construct constraints on the
2620 * integer division itself. These constraints can then be combined
2621 * during the Fourier-Motzkin elimination.
2622 * Note that it is only useful to introduce lower bounds on "div"
2623 * if "bmap" already contains upper bounds on "div" as the newly
2624 * introduce lower bounds can then be combined with the pre-existing
2625 * upper bounds. Similarly for upper bounds.
2626 * We therefore first check if "bmap" contains any lower and/or upper bounds
2627 * on "div".
2629 * It is interesting to note that the introduction of these constraints
2630 * can indeed lead to more accurate results, even when compared to
2631 * deriving constraints on the argument of "div" from constraints on "div".
2632 * Consider, for example, the set
2634 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2636 * The second constraint can be rewritten as
2638 * 2 * [(-i-2j+3)/4] + k >= 0
2640 * from which we can derive
2642 * -i - 2j + 3 >= -2k
2644 * or
2646 * i + 2j <= 3 + 2k
2648 * Combined with the first constraint, we obtain
2650 * -3 <= 3 + 2k or k >= -3
2652 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2653 * the first constraint, we obtain
2655 * [(i + 2j)/4] >= [-3/4] = -1
2657 * Combining this constraint with the second constraint, we obtain
2659 * k >= -2
2661 static __isl_give isl_basic_map *insert_bounds_on_div(
2662 __isl_take isl_basic_map *bmap, int div)
2664 int i;
2665 int check_lb, check_ub;
2666 isl_int v;
2667 unsigned total;
2669 if (!bmap)
2670 return NULL;
2672 if (isl_int_is_zero(bmap->div[div][0]))
2673 return bmap;
2675 total = isl_space_dim(bmap->dim, isl_dim_all);
2677 check_lb = 0;
2678 check_ub = 0;
2679 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2680 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2681 if (s > 0)
2682 check_ub = 1;
2683 if (s < 0)
2684 check_lb = 1;
2687 if (!check_lb && !check_ub)
2688 return bmap;
2690 isl_int_init(v);
2692 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2693 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2694 continue;
2696 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2697 check_lb, check_ub);
2700 isl_int_clear(v);
2702 return bmap;
2705 /* Remove all divs (recursively) involving any of the given dimensions
2706 * in their definitions.
2708 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2709 __isl_take isl_basic_map *bmap,
2710 enum isl_dim_type type, unsigned first, unsigned n)
2712 int i;
2714 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2715 return isl_basic_map_free(bmap);
2716 first += isl_basic_map_offset(bmap, type);
2718 for (i = bmap->n_div - 1; i >= 0; --i) {
2719 isl_bool involves;
2721 involves = div_involves_vars(bmap, i, first, n);
2722 if (involves < 0)
2723 return isl_basic_map_free(bmap);
2724 if (!involves)
2725 continue;
2726 bmap = insert_bounds_on_div(bmap, i);
2727 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2728 if (!bmap)
2729 return NULL;
2730 i = bmap->n_div;
2733 return bmap;
2736 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2737 __isl_take isl_basic_set *bset,
2738 enum isl_dim_type type, unsigned first, unsigned n)
2740 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2743 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2744 enum isl_dim_type type, unsigned first, unsigned n)
2746 int i;
2748 if (!map)
2749 return NULL;
2750 if (map->n == 0)
2751 return map;
2753 map = isl_map_cow(map);
2754 if (!map)
2755 return NULL;
2757 for (i = 0; i < map->n; ++i) {
2758 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2759 type, first, n);
2760 if (!map->p[i])
2761 goto error;
2763 return map;
2764 error:
2765 isl_map_free(map);
2766 return NULL;
2769 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2770 enum isl_dim_type type, unsigned first, unsigned n)
2772 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2773 type, first, n));
2776 /* Does the description of "bmap" depend on the specified dimensions?
2777 * We also check whether the dimensions appear in any of the div definitions.
2778 * In principle there is no need for this check. If the dimensions appear
2779 * in a div definition, they also appear in the defining constraints of that
2780 * div.
2782 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2783 enum isl_dim_type type, unsigned first, unsigned n)
2785 int i;
2787 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2788 return isl_bool_error;
2790 first += isl_basic_map_offset(bmap, type);
2791 for (i = 0; i < bmap->n_eq; ++i)
2792 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2793 return isl_bool_true;
2794 for (i = 0; i < bmap->n_ineq; ++i)
2795 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2796 return isl_bool_true;
2797 for (i = 0; i < bmap->n_div; ++i) {
2798 if (isl_int_is_zero(bmap->div[i][0]))
2799 continue;
2800 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2801 return isl_bool_true;
2804 return isl_bool_false;
2807 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2808 enum isl_dim_type type, unsigned first, unsigned n)
2810 int i;
2812 if (isl_map_check_range(map, type, first, n) < 0)
2813 return isl_bool_error;
2815 for (i = 0; i < map->n; ++i) {
2816 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2817 type, first, n);
2818 if (involves < 0 || involves)
2819 return involves;
2822 return isl_bool_false;
2825 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2826 enum isl_dim_type type, unsigned first, unsigned n)
2828 return isl_basic_map_involves_dims(bset, type, first, n);
2831 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2832 enum isl_dim_type type, unsigned first, unsigned n)
2834 return isl_map_involves_dims(set, type, first, n);
2837 /* Drop all constraints in bmap that involve any of the dimensions
2838 * first to first+n-1.
2839 * This function only performs the actual removal of constraints.
2841 * This function should not call finalize since it is used by
2842 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
2844 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2845 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2847 int i;
2849 if (n == 0)
2850 return bmap;
2852 bmap = isl_basic_map_cow(bmap);
2854 if (!bmap)
2855 return NULL;
2857 for (i = bmap->n_eq - 1; i >= 0; --i) {
2858 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2859 continue;
2860 isl_basic_map_drop_equality(bmap, i);
2863 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2864 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2865 continue;
2866 isl_basic_map_drop_inequality(bmap, i);
2869 return bmap;
2872 /* Drop all constraints in bset that involve any of the dimensions
2873 * first to first+n-1.
2874 * This function only performs the actual removal of constraints.
2876 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2877 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2879 return isl_basic_map_drop_constraints_involving(bset, first, n);
2882 /* Drop all constraints in bmap that do not involve any of the dimensions
2883 * first to first + n - 1 of the given type.
2885 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2886 __isl_take isl_basic_map *bmap,
2887 enum isl_dim_type type, unsigned first, unsigned n)
2889 int i;
2891 if (n == 0) {
2892 isl_space *space = isl_basic_map_get_space(bmap);
2893 isl_basic_map_free(bmap);
2894 return isl_basic_map_universe(space);
2896 bmap = isl_basic_map_cow(bmap);
2897 if (!bmap)
2898 return NULL;
2900 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2901 return isl_basic_map_free(bmap);
2903 first += isl_basic_map_offset(bmap, type) - 1;
2905 for (i = bmap->n_eq - 1; i >= 0; --i) {
2906 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2907 continue;
2908 isl_basic_map_drop_equality(bmap, i);
2911 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2912 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2913 continue;
2914 isl_basic_map_drop_inequality(bmap, i);
2917 bmap = isl_basic_map_add_known_div_constraints(bmap);
2918 return bmap;
2921 /* Drop all constraints in bset that do not involve any of the dimensions
2922 * first to first + n - 1 of the given type.
2924 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2925 __isl_take isl_basic_set *bset,
2926 enum isl_dim_type type, unsigned first, unsigned n)
2928 return isl_basic_map_drop_constraints_not_involving_dims(bset,
2929 type, first, n);
2932 /* Drop all constraints in bmap that involve any of the dimensions
2933 * first to first + n - 1 of the given type.
2935 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2936 __isl_take isl_basic_map *bmap,
2937 enum isl_dim_type type, unsigned first, unsigned n)
2939 if (!bmap)
2940 return NULL;
2941 if (n == 0)
2942 return bmap;
2944 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2945 return isl_basic_map_free(bmap);
2947 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2948 first += isl_basic_map_offset(bmap, type) - 1;
2949 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
2950 bmap = isl_basic_map_add_known_div_constraints(bmap);
2951 return bmap;
2954 /* Drop all constraints in bset that involve any of the dimensions
2955 * first to first + n - 1 of the given type.
2957 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2958 __isl_take isl_basic_set *bset,
2959 enum isl_dim_type type, unsigned first, unsigned n)
2961 return isl_basic_map_drop_constraints_involving_dims(bset,
2962 type, first, n);
2965 /* Drop constraints from "map" by applying "drop" to each basic map.
2967 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2968 enum isl_dim_type type, unsigned first, unsigned n,
2969 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2970 enum isl_dim_type type, unsigned first, unsigned n))
2972 int i;
2974 if (isl_map_check_range(map, type, first, n) < 0)
2975 return isl_map_free(map);
2977 map = isl_map_cow(map);
2978 if (!map)
2979 return NULL;
2981 for (i = 0; i < map->n; ++i) {
2982 map->p[i] = drop(map->p[i], type, first, n);
2983 if (!map->p[i])
2984 return isl_map_free(map);
2987 if (map->n > 1)
2988 ISL_F_CLR(map, ISL_MAP_DISJOINT);
2990 return map;
2993 /* Drop all constraints in map that involve any of the dimensions
2994 * first to first + n - 1 of the given type.
2996 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
2997 __isl_take isl_map *map,
2998 enum isl_dim_type type, unsigned first, unsigned n)
3000 if (n == 0)
3001 return map;
3002 return drop_constraints(map, type, first, n,
3003 &isl_basic_map_drop_constraints_involving_dims);
3006 /* Drop all constraints in "map" that do not involve any of the dimensions
3007 * first to first + n - 1 of the given type.
3009 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3010 __isl_take isl_map *map,
3011 enum isl_dim_type type, unsigned first, unsigned n)
3013 if (n == 0) {
3014 isl_space *space = isl_map_get_space(map);
3015 isl_map_free(map);
3016 return isl_map_universe(space);
3018 return drop_constraints(map, type, first, n,
3019 &isl_basic_map_drop_constraints_not_involving_dims);
3022 /* Drop all constraints in set that involve any of the dimensions
3023 * first to first + n - 1 of the given type.
3025 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3026 __isl_take isl_set *set,
3027 enum isl_dim_type type, unsigned first, unsigned n)
3029 return isl_map_drop_constraints_involving_dims(set, type, first, n);
3032 /* Drop all constraints in "set" that do not involve any of the dimensions
3033 * first to first + n - 1 of the given type.
3035 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3036 __isl_take isl_set *set,
3037 enum isl_dim_type type, unsigned first, unsigned n)
3039 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3042 /* Does local variable "div" of "bmap" have a complete explicit representation?
3043 * Having a complete explicit representation requires not only
3044 * an explicit representation, but also that all local variables
3045 * that appear in this explicit representation in turn have
3046 * a complete explicit representation.
3048 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3050 int i;
3051 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3052 isl_bool marked;
3054 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3055 if (marked < 0 || marked)
3056 return isl_bool_not(marked);
3058 for (i = bmap->n_div - 1; i >= 0; --i) {
3059 isl_bool known;
3061 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3062 continue;
3063 known = isl_basic_map_div_is_known(bmap, i);
3064 if (known < 0 || !known)
3065 return known;
3068 return isl_bool_true;
3071 /* Remove all divs that are unknown or defined in terms of unknown divs.
3073 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3074 __isl_take isl_basic_map *bmap)
3076 int i;
3078 if (!bmap)
3079 return NULL;
3081 for (i = bmap->n_div - 1; i >= 0; --i) {
3082 if (isl_basic_map_div_is_known(bmap, i))
3083 continue;
3084 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3085 if (!bmap)
3086 return NULL;
3087 i = bmap->n_div;
3090 return bmap;
3093 /* Remove all divs that are unknown or defined in terms of unknown divs.
3095 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3096 __isl_take isl_basic_set *bset)
3098 return isl_basic_map_remove_unknown_divs(bset);
3101 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3103 int i;
3105 if (!map)
3106 return NULL;
3107 if (map->n == 0)
3108 return map;
3110 map = isl_map_cow(map);
3111 if (!map)
3112 return NULL;
3114 for (i = 0; i < map->n; ++i) {
3115 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3116 if (!map->p[i])
3117 goto error;
3119 return map;
3120 error:
3121 isl_map_free(map);
3122 return NULL;
3125 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3127 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3130 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3131 __isl_take isl_basic_set *bset,
3132 enum isl_dim_type type, unsigned first, unsigned n)
3134 isl_basic_map *bmap = bset_to_bmap(bset);
3135 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3136 return bset_from_bmap(bmap);
3139 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3140 enum isl_dim_type type, unsigned first, unsigned n)
3142 int i;
3144 if (n == 0)
3145 return map;
3147 map = isl_map_cow(map);
3148 if (isl_map_check_range(map, type, first, n) < 0)
3149 return isl_map_free(map);
3151 for (i = 0; i < map->n; ++i) {
3152 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3153 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3154 if (!map->p[i])
3155 goto error;
3157 map = isl_map_drop(map, type, first, n);
3158 return map;
3159 error:
3160 isl_map_free(map);
3161 return NULL;
3164 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3165 enum isl_dim_type type, unsigned first, unsigned n)
3167 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3168 type, first, n));
3171 /* Project out n inputs starting at first using Fourier-Motzkin */
3172 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
3173 unsigned first, unsigned n)
3175 return isl_map_remove_dims(map, isl_dim_in, first, n);
3178 void isl_basic_set_print_internal(struct isl_basic_set *bset,
3179 FILE *out, int indent)
3181 isl_printer *p;
3183 if (!bset) {
3184 fprintf(out, "null basic set\n");
3185 return;
3188 fprintf(out, "%*s", indent, "");
3189 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3190 bset->ref, bset->dim->nparam, bset->dim->n_out,
3191 bset->extra, bset->flags);
3193 p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
3194 p = isl_printer_set_dump(p, 1);
3195 p = isl_printer_set_indent(p, indent);
3196 p = isl_printer_start_line(p);
3197 p = isl_printer_print_basic_set(p, bset);
3198 p = isl_printer_end_line(p);
3199 isl_printer_free(p);
3202 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
3203 FILE *out, int indent)
3205 isl_printer *p;
3207 if (!bmap) {
3208 fprintf(out, "null basic map\n");
3209 return;
3212 fprintf(out, "%*s", indent, "");
3213 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3214 "flags: %x, n_name: %d\n",
3215 bmap->ref,
3216 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3217 bmap->extra, bmap->flags, bmap->dim->n_id);
3219 p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
3220 p = isl_printer_set_dump(p, 1);
3221 p = isl_printer_set_indent(p, indent);
3222 p = isl_printer_start_line(p);
3223 p = isl_printer_print_basic_map(p, bmap);
3224 p = isl_printer_end_line(p);
3225 isl_printer_free(p);
3228 __isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3229 unsigned pos)
3231 unsigned total;
3233 if (!bmap)
3234 return NULL;
3235 total = isl_basic_map_total_dim(bmap);
3236 if (pos >= bmap->n_ineq)
3237 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3238 "invalid position", return isl_basic_map_free(bmap));
3239 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3240 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3241 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3242 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3243 return bmap;
3246 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3247 unsigned flags)
3249 if (isl_space_check_is_set(space) < 0)
3250 goto error;
3251 return isl_map_alloc_space(space, n, flags);
3252 error:
3253 isl_space_free(space);
3254 return NULL;
3257 /* Make sure "map" has room for at least "n" more basic maps.
3259 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3261 int i;
3262 struct isl_map *grown = NULL;
3264 if (!map)
3265 return NULL;
3266 isl_assert(map->ctx, n >= 0, goto error);
3267 if (map->n + n <= map->size)
3268 return map;
3269 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3270 if (!grown)
3271 goto error;
3272 for (i = 0; i < map->n; ++i) {
3273 grown->p[i] = isl_basic_map_copy(map->p[i]);
3274 if (!grown->p[i])
3275 goto error;
3276 grown->n++;
3278 isl_map_free(map);
3279 return grown;
3280 error:
3281 isl_map_free(grown);
3282 isl_map_free(map);
3283 return NULL;
3286 /* Make sure "set" has room for at least "n" more basic sets.
3288 struct isl_set *isl_set_grow(struct isl_set *set, int n)
3290 return set_from_map(isl_map_grow(set_to_map(set), n));
3293 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3295 return isl_map_from_basic_map(bset);
3298 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3300 struct isl_map *map;
3302 if (!bmap)
3303 return NULL;
3305 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3306 return isl_map_add_basic_map(map, bmap);
3309 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3310 __isl_take isl_basic_set *bset)
3312 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3313 bset_to_bmap(bset)));
3316 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3318 return isl_map_free(set);
3321 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3323 int i;
3325 if (!set) {
3326 fprintf(out, "null set\n");
3327 return;
3330 fprintf(out, "%*s", indent, "");
3331 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3332 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3333 set->flags);
3334 for (i = 0; i < set->n; ++i) {
3335 fprintf(out, "%*s", indent, "");
3336 fprintf(out, "basic set %d:\n", i);
3337 isl_basic_set_print_internal(set->p[i], out, indent+4);
3341 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3343 int i;
3345 if (!map) {
3346 fprintf(out, "null map\n");
3347 return;
3350 fprintf(out, "%*s", indent, "");
3351 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3352 "flags: %x, n_name: %d\n",
3353 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3354 map->dim->n_out, map->flags, map->dim->n_id);
3355 for (i = 0; i < map->n; ++i) {
3356 fprintf(out, "%*s", indent, "");
3357 fprintf(out, "basic map %d:\n", i);
3358 isl_basic_map_print_internal(map->p[i], out, indent+4);
3362 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3363 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3365 struct isl_basic_map *bmap_domain;
3367 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3368 goto error;
3370 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
3371 isl_assert(bset->ctx,
3372 isl_basic_map_compatible_domain(bmap, bset), goto error);
3374 bmap = isl_basic_map_cow(bmap);
3375 if (!bmap)
3376 goto error;
3377 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3378 bset->n_div, bset->n_eq, bset->n_ineq);
3379 bmap_domain = isl_basic_map_from_domain(bset);
3380 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3382 bmap = isl_basic_map_simplify(bmap);
3383 return isl_basic_map_finalize(bmap);
3384 error:
3385 isl_basic_map_free(bmap);
3386 isl_basic_set_free(bset);
3387 return NULL;
3390 /* Check that the space of "bset" is the same as that of the range of "bmap".
3392 static isl_stat isl_basic_map_check_compatible_range(
3393 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3395 isl_bool ok;
3397 ok = isl_basic_map_compatible_range(bmap, bset);
3398 if (ok < 0)
3399 return isl_stat_error;
3400 if (!ok)
3401 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3402 "incompatible spaces", return isl_stat_error);
3404 return isl_stat_ok;
3407 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3408 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3410 struct isl_basic_map *bmap_range;
3412 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3413 goto error;
3415 if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
3416 isl_basic_map_check_compatible_range(bmap, bset) < 0)
3417 goto error;
3419 if (isl_basic_set_plain_is_universe(bset)) {
3420 isl_basic_set_free(bset);
3421 return bmap;
3424 bmap = isl_basic_map_cow(bmap);
3425 if (!bmap)
3426 goto error;
3427 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3428 bset->n_div, bset->n_eq, bset->n_ineq);
3429 bmap_range = bset_to_bmap(bset);
3430 bmap = add_constraints(bmap, bmap_range, 0, 0);
3432 bmap = isl_basic_map_simplify(bmap);
3433 return isl_basic_map_finalize(bmap);
3434 error:
3435 isl_basic_map_free(bmap);
3436 isl_basic_set_free(bset);
3437 return NULL;
3440 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3441 __isl_keep isl_vec *vec)
3443 int i;
3444 unsigned total;
3445 isl_int s;
3447 if (!bmap || !vec)
3448 return isl_bool_error;
3450 total = 1 + isl_basic_map_total_dim(bmap);
3451 if (total != vec->size)
3452 return isl_bool_false;
3454 isl_int_init(s);
3456 for (i = 0; i < bmap->n_eq; ++i) {
3457 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3458 if (!isl_int_is_zero(s)) {
3459 isl_int_clear(s);
3460 return isl_bool_false;
3464 for (i = 0; i < bmap->n_ineq; ++i) {
3465 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3466 if (isl_int_is_neg(s)) {
3467 isl_int_clear(s);
3468 return isl_bool_false;
3472 isl_int_clear(s);
3474 return isl_bool_true;
3477 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3478 __isl_keep isl_vec *vec)
3480 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3483 __isl_give isl_basic_map *isl_basic_map_intersect(
3484 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3486 struct isl_vec *sample = NULL;
3488 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3489 goto error;
3490 if (isl_space_dim(bmap1->dim, isl_dim_all) ==
3491 isl_space_dim(bmap1->dim, isl_dim_param) &&
3492 isl_space_dim(bmap2->dim, isl_dim_all) !=
3493 isl_space_dim(bmap2->dim, isl_dim_param))
3494 return isl_basic_map_intersect(bmap2, bmap1);
3496 if (isl_space_dim(bmap2->dim, isl_dim_all) !=
3497 isl_space_dim(bmap2->dim, isl_dim_param))
3498 isl_assert(bmap1->ctx,
3499 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3501 if (isl_basic_map_plain_is_empty(bmap1)) {
3502 isl_basic_map_free(bmap2);
3503 return bmap1;
3505 if (isl_basic_map_plain_is_empty(bmap2)) {
3506 isl_basic_map_free(bmap1);
3507 return bmap2;
3510 if (bmap1->sample &&
3511 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3512 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3513 sample = isl_vec_copy(bmap1->sample);
3514 else if (bmap2->sample &&
3515 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3516 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3517 sample = isl_vec_copy(bmap2->sample);
3519 bmap1 = isl_basic_map_cow(bmap1);
3520 if (!bmap1)
3521 goto error;
3522 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3523 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3524 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3526 if (!bmap1)
3527 isl_vec_free(sample);
3528 else if (sample) {
3529 isl_vec_free(bmap1->sample);
3530 bmap1->sample = sample;
3533 bmap1 = isl_basic_map_simplify(bmap1);
3534 return isl_basic_map_finalize(bmap1);
3535 error:
3536 if (sample)
3537 isl_vec_free(sample);
3538 isl_basic_map_free(bmap1);
3539 isl_basic_map_free(bmap2);
3540 return NULL;
3543 struct isl_basic_set *isl_basic_set_intersect(
3544 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3546 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3547 bset_to_bmap(bset2)));
3550 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3551 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3553 return isl_basic_set_intersect(bset1, bset2);
3556 /* Special case of isl_map_intersect, where both map1 and map2
3557 * are convex, without any divs and such that either map1 or map2
3558 * contains a single constraint. This constraint is then simply
3559 * added to the other map.
3561 static __isl_give isl_map *map_intersect_add_constraint(
3562 __isl_take isl_map *map1, __isl_take isl_map *map2)
3564 isl_assert(map1->ctx, map1->n == 1, goto error);
3565 isl_assert(map2->ctx, map1->n == 1, goto error);
3566 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3567 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3569 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3570 return isl_map_intersect(map2, map1);
3572 map1 = isl_map_cow(map1);
3573 if (!map1)
3574 goto error;
3575 if (isl_map_plain_is_empty(map1)) {
3576 isl_map_free(map2);
3577 return map1;
3579 if (map2->p[0]->n_eq == 1)
3580 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3581 else
3582 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3583 map2->p[0]->ineq[0]);
3585 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3586 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3587 if (!map1->p[0])
3588 goto error;
3590 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3591 isl_basic_map_free(map1->p[0]);
3592 map1->n = 0;
3595 isl_map_free(map2);
3597 map1 = isl_map_unmark_normalized(map1);
3598 return map1;
3599 error:
3600 isl_map_free(map1);
3601 isl_map_free(map2);
3602 return NULL;
3605 /* map2 may be either a parameter domain or a map living in the same
3606 * space as map1.
3608 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3609 __isl_take isl_map *map2)
3611 unsigned flags = 0;
3612 isl_bool equal;
3613 isl_map *result;
3614 int i, j;
3616 if (!map1 || !map2)
3617 goto error;
3619 if ((isl_map_plain_is_empty(map1) ||
3620 isl_map_plain_is_universe(map2)) &&
3621 isl_space_is_equal(map1->dim, map2->dim)) {
3622 isl_map_free(map2);
3623 return map1;
3625 if ((isl_map_plain_is_empty(map2) ||
3626 isl_map_plain_is_universe(map1)) &&
3627 isl_space_is_equal(map1->dim, map2->dim)) {
3628 isl_map_free(map1);
3629 return map2;
3632 if (map1->n == 1 && map2->n == 1 &&
3633 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3634 isl_space_is_equal(map1->dim, map2->dim) &&
3635 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3636 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3637 return map_intersect_add_constraint(map1, map2);
3639 equal = isl_map_plain_is_equal(map1, map2);
3640 if (equal < 0)
3641 goto error;
3642 if (equal) {
3643 isl_map_free(map2);
3644 return map1;
3647 if (isl_space_dim(map2->dim, isl_dim_all) !=
3648 isl_space_dim(map2->dim, isl_dim_param))
3649 isl_assert(map1->ctx,
3650 isl_space_is_equal(map1->dim, map2->dim), goto error);
3652 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3653 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3654 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3656 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3657 map1->n * map2->n, flags);
3658 if (!result)
3659 goto error;
3660 for (i = 0; i < map1->n; ++i)
3661 for (j = 0; j < map2->n; ++j) {
3662 struct isl_basic_map *part;
3663 part = isl_basic_map_intersect(
3664 isl_basic_map_copy(map1->p[i]),
3665 isl_basic_map_copy(map2->p[j]));
3666 if (isl_basic_map_is_empty(part) < 0)
3667 part = isl_basic_map_free(part);
3668 result = isl_map_add_basic_map(result, part);
3669 if (!result)
3670 goto error;
3672 isl_map_free(map1);
3673 isl_map_free(map2);
3674 return result;
3675 error:
3676 isl_map_free(map1);
3677 isl_map_free(map2);
3678 return NULL;
3681 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3682 __isl_take isl_map *map2)
3684 if (!map1 || !map2)
3685 goto error;
3686 if (!isl_space_is_equal(map1->dim, map2->dim))
3687 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3688 "spaces don't match", goto error);
3689 return map_intersect_internal(map1, map2);
3690 error:
3691 isl_map_free(map1);
3692 isl_map_free(map2);
3693 return NULL;
3696 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3697 __isl_take isl_map *map2)
3699 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3702 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3704 return set_from_map(isl_map_intersect(set_to_map(set1),
3705 set_to_map(set2)));
3708 /* map_intersect_internal accepts intersections
3709 * with parameter domains, so we can just call that function.
3711 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3712 __isl_take isl_set *params)
3714 return map_intersect_internal(map, params);
3717 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3718 __isl_take isl_map *map2)
3720 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3723 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3724 __isl_take isl_set *params)
3726 return isl_map_intersect_params(set, params);
3729 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3731 isl_space *space;
3732 unsigned pos, n1, n2;
3734 if (!bmap)
3735 return NULL;
3736 bmap = isl_basic_map_cow(bmap);
3737 if (!bmap)
3738 return NULL;
3739 space = isl_space_reverse(isl_space_copy(bmap->dim));
3740 pos = isl_basic_map_offset(bmap, isl_dim_in);
3741 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3742 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3743 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3744 return isl_basic_map_reset_space(bmap, space);
3747 static __isl_give isl_basic_map *basic_map_space_reset(
3748 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3750 isl_space *space;
3752 if (!bmap)
3753 return NULL;
3754 if (!isl_space_is_named_or_nested(bmap->dim, type))
3755 return bmap;
3757 space = isl_basic_map_get_space(bmap);
3758 space = isl_space_reset(space, type);
3759 bmap = isl_basic_map_reset_space(bmap, space);
3760 return bmap;
3763 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3764 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3765 unsigned pos, unsigned n)
3767 isl_bool rational, is_empty;
3768 isl_space *res_space;
3769 struct isl_basic_map *res;
3770 struct isl_dim_map *dim_map;
3771 unsigned total, off;
3772 enum isl_dim_type t;
3774 if (n == 0)
3775 return basic_map_space_reset(bmap, type);
3777 is_empty = isl_basic_map_plain_is_empty(bmap);
3778 if (is_empty < 0)
3779 return isl_basic_map_free(bmap);
3780 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3781 type, pos, n);
3782 if (!res_space)
3783 return isl_basic_map_free(bmap);
3784 if (is_empty) {
3785 isl_basic_map_free(bmap);
3786 return isl_basic_map_empty(res_space);
3789 total = isl_basic_map_total_dim(bmap) + n;
3790 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3791 off = 0;
3792 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3793 if (t != type) {
3794 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3795 } else {
3796 unsigned size = isl_basic_map_dim(bmap, t);
3797 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3798 0, pos, off);
3799 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3800 pos, size - pos, off + pos + n);
3802 off += isl_space_dim(res_space, t);
3804 isl_dim_map_div(dim_map, bmap, off);
3806 res = isl_basic_map_alloc_space(res_space,
3807 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3808 rational = isl_basic_map_is_rational(bmap);
3809 if (rational < 0)
3810 res = isl_basic_map_free(res);
3811 if (rational)
3812 res = isl_basic_map_set_rational(res);
3813 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3814 return isl_basic_map_finalize(res);
3817 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3818 __isl_take isl_basic_set *bset,
3819 enum isl_dim_type type, unsigned pos, unsigned n)
3821 return isl_basic_map_insert_dims(bset, type, pos, n);
3824 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3825 enum isl_dim_type type, unsigned n)
3827 if (!bmap)
3828 return NULL;
3829 return isl_basic_map_insert_dims(bmap, type,
3830 isl_basic_map_dim(bmap, type), n);
3833 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3834 enum isl_dim_type type, unsigned n)
3836 if (!bset)
3837 return NULL;
3838 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3839 return isl_basic_map_add_dims(bset, type, n);
3840 error:
3841 isl_basic_set_free(bset);
3842 return NULL;
3845 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3846 enum isl_dim_type type)
3848 isl_space *space;
3850 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3851 return map;
3853 space = isl_map_get_space(map);
3854 space = isl_space_reset(space, type);
3855 map = isl_map_reset_space(map, space);
3856 return map;
3859 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3860 enum isl_dim_type type, unsigned pos, unsigned n)
3862 int i;
3864 if (n == 0)
3865 return map_space_reset(map, type);
3867 map = isl_map_cow(map);
3868 if (!map)
3869 return NULL;
3871 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3872 if (!map->dim)
3873 goto error;
3875 for (i = 0; i < map->n; ++i) {
3876 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3877 if (!map->p[i])
3878 goto error;
3881 return map;
3882 error:
3883 isl_map_free(map);
3884 return NULL;
3887 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3888 enum isl_dim_type type, unsigned pos, unsigned n)
3890 return isl_map_insert_dims(set, type, pos, n);
3893 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3894 enum isl_dim_type type, unsigned n)
3896 if (!map)
3897 return NULL;
3898 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3901 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3902 enum isl_dim_type type, unsigned n)
3904 if (!set)
3905 return NULL;
3906 isl_assert(set->ctx, type != isl_dim_in, goto error);
3907 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
3908 error:
3909 isl_set_free(set);
3910 return NULL;
3913 __isl_give isl_basic_map *isl_basic_map_move_dims(
3914 __isl_take isl_basic_map *bmap,
3915 enum isl_dim_type dst_type, unsigned dst_pos,
3916 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3918 struct isl_dim_map *dim_map;
3919 struct isl_basic_map *res;
3920 enum isl_dim_type t;
3921 unsigned total, off;
3923 if (!bmap)
3924 return NULL;
3925 if (n == 0) {
3926 bmap = isl_basic_map_reset(bmap, src_type);
3927 bmap = isl_basic_map_reset(bmap, dst_type);
3928 return bmap;
3931 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
3932 return isl_basic_map_free(bmap);
3934 if (dst_type == src_type && dst_pos == src_pos)
3935 return bmap;
3937 isl_assert(bmap->ctx, dst_type != src_type, goto error);
3939 if (pos(bmap->dim, dst_type) + dst_pos ==
3940 pos(bmap->dim, src_type) + src_pos +
3941 ((src_type < dst_type) ? n : 0)) {
3942 bmap = isl_basic_map_cow(bmap);
3943 if (!bmap)
3944 return NULL;
3946 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3947 src_type, src_pos, n);
3948 if (!bmap->dim)
3949 goto error;
3951 bmap = isl_basic_map_finalize(bmap);
3953 return bmap;
3956 total = isl_basic_map_total_dim(bmap);
3957 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3959 off = 0;
3960 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3961 unsigned size = isl_space_dim(bmap->dim, t);
3962 if (t == dst_type) {
3963 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3964 0, dst_pos, off);
3965 off += dst_pos;
3966 isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
3967 src_pos, n, off);
3968 off += n;
3969 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3970 dst_pos, size - dst_pos, off);
3971 off += size - dst_pos;
3972 } else if (t == src_type) {
3973 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3974 0, src_pos, off);
3975 off += src_pos;
3976 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3977 src_pos + n, size - src_pos - n, off);
3978 off += size - src_pos - n;
3979 } else {
3980 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3981 off += size;
3984 isl_dim_map_div(dim_map, bmap, off);
3986 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3987 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3988 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3989 if (!bmap)
3990 goto error;
3992 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3993 src_type, src_pos, n);
3994 if (!bmap->dim)
3995 goto error;
3997 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3998 bmap = isl_basic_map_gauss(bmap, NULL);
3999 bmap = isl_basic_map_finalize(bmap);
4001 return bmap;
4002 error:
4003 isl_basic_map_free(bmap);
4004 return NULL;
4007 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4008 enum isl_dim_type dst_type, unsigned dst_pos,
4009 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4011 isl_basic_map *bmap = bset_to_bmap(bset);
4012 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4013 src_type, src_pos, n);
4014 return bset_from_bmap(bmap);
4017 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4018 enum isl_dim_type dst_type, unsigned dst_pos,
4019 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4021 if (!set)
4022 return NULL;
4023 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4024 return set_from_map(isl_map_move_dims(set_to_map(set),
4025 dst_type, dst_pos, src_type, src_pos, n));
4026 error:
4027 isl_set_free(set);
4028 return NULL;
4031 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4032 enum isl_dim_type dst_type, unsigned dst_pos,
4033 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4035 int i;
4037 if (n == 0) {
4038 map = isl_map_reset(map, src_type);
4039 map = isl_map_reset(map, dst_type);
4040 return map;
4043 if (isl_map_check_range(map, src_type, src_pos, n))
4044 return isl_map_free(map);
4046 if (dst_type == src_type && dst_pos == src_pos)
4047 return map;
4049 isl_assert(map->ctx, dst_type != src_type, goto error);
4051 map = isl_map_cow(map);
4052 if (!map)
4053 return NULL;
4055 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
4056 if (!map->dim)
4057 goto error;
4059 for (i = 0; i < map->n; ++i) {
4060 map->p[i] = isl_basic_map_move_dims(map->p[i],
4061 dst_type, dst_pos,
4062 src_type, src_pos, n);
4063 if (!map->p[i])
4064 goto error;
4067 return map;
4068 error:
4069 isl_map_free(map);
4070 return NULL;
4073 /* Move the specified dimensions to the last columns right before
4074 * the divs. Don't change the dimension specification of bmap.
4075 * That's the responsibility of the caller.
4077 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4078 enum isl_dim_type type, unsigned first, unsigned n)
4080 struct isl_dim_map *dim_map;
4081 struct isl_basic_map *res;
4082 enum isl_dim_type t;
4083 unsigned total, off;
4085 if (!bmap)
4086 return NULL;
4087 if (pos(bmap->dim, type) + first + n ==
4088 1 + isl_space_dim(bmap->dim, isl_dim_all))
4089 return bmap;
4091 total = isl_basic_map_total_dim(bmap);
4092 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4094 off = 0;
4095 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4096 unsigned size = isl_space_dim(bmap->dim, t);
4097 if (t == type) {
4098 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4099 0, first, off);
4100 off += first;
4101 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4102 first, n, total - bmap->n_div - n);
4103 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4104 first + n, size - (first + n), off);
4105 off += size - (first + n);
4106 } else {
4107 isl_dim_map_dim(dim_map, bmap->dim, t, off);
4108 off += size;
4111 isl_dim_map_div(dim_map, bmap, off + n);
4113 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4114 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4115 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4116 return res;
4119 /* Insert "n" rows in the divs of "bmap".
4121 * The number of columns is not changed, which means that the last
4122 * dimensions of "bmap" are being reintepreted as the new divs.
4123 * The space of "bmap" is not adjusted, however, which means
4124 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4125 * from the space of "bmap" is the responsibility of the caller.
4127 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4128 int n)
4130 int i;
4131 size_t row_size;
4132 isl_int **new_div;
4133 isl_int *old;
4135 bmap = isl_basic_map_cow(bmap);
4136 if (!bmap)
4137 return NULL;
4139 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
4140 old = bmap->block2.data;
4141 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4142 (bmap->extra + n) * (1 + row_size));
4143 if (!bmap->block2.data)
4144 return isl_basic_map_free(bmap);
4145 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4146 if (!new_div)
4147 return isl_basic_map_free(bmap);
4148 for (i = 0; i < n; ++i) {
4149 new_div[i] = bmap->block2.data +
4150 (bmap->extra + i) * (1 + row_size);
4151 isl_seq_clr(new_div[i], 1 + row_size);
4153 for (i = 0; i < bmap->extra; ++i)
4154 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4155 free(bmap->div);
4156 bmap->div = new_div;
4157 bmap->n_div += n;
4158 bmap->extra += n;
4160 return bmap;
4163 /* Drop constraints from "bmap" that only involve the variables
4164 * of "type" in the range [first, first + n] that are not related
4165 * to any of the variables outside that interval.
4166 * These constraints cannot influence the values for the variables
4167 * outside the interval, except in case they cause "bmap" to be empty.
4168 * Only drop the constraints if "bmap" is known to be non-empty.
4170 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4171 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4172 unsigned first, unsigned n)
4174 int i;
4175 int *groups;
4176 unsigned dim, n_div;
4177 isl_bool non_empty;
4179 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4180 if (non_empty < 0)
4181 return isl_basic_map_free(bmap);
4182 if (!non_empty)
4183 return bmap;
4185 dim = isl_basic_map_dim(bmap, isl_dim_all);
4186 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4187 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4188 if (!groups)
4189 return isl_basic_map_free(bmap);
4190 first += isl_basic_map_offset(bmap, type) - 1;
4191 for (i = 0; i < first; ++i)
4192 groups[i] = -1;
4193 for (i = first + n; i < dim - n_div; ++i)
4194 groups[i] = -1;
4196 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4198 return bmap;
4201 /* Turn the n dimensions of type type, starting at first
4202 * into existentially quantified variables.
4204 * If a subset of the projected out variables are unrelated
4205 * to any of the variables that remain, then the constraints
4206 * involving this subset are simply dropped first.
4208 __isl_give isl_basic_map *isl_basic_map_project_out(
4209 __isl_take isl_basic_map *bmap,
4210 enum isl_dim_type type, unsigned first, unsigned n)
4212 isl_bool empty;
4214 if (n == 0)
4215 return basic_map_space_reset(bmap, type);
4216 if (type == isl_dim_div)
4217 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4218 "cannot project out existentially quantified variables",
4219 return isl_basic_map_free(bmap));
4221 empty = isl_basic_map_plain_is_empty(bmap);
4222 if (empty < 0)
4223 return isl_basic_map_free(bmap);
4224 if (empty)
4225 bmap = isl_basic_map_set_to_empty(bmap);
4227 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4228 if (!bmap)
4229 return NULL;
4231 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4232 return isl_basic_map_remove_dims(bmap, type, first, n);
4234 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4235 return isl_basic_map_free(bmap);
4237 bmap = move_last(bmap, type, first, n);
4238 bmap = isl_basic_map_cow(bmap);
4239 bmap = insert_div_rows(bmap, n);
4240 if (!bmap)
4241 return NULL;
4243 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
4244 if (!bmap->dim)
4245 goto error;
4246 bmap = isl_basic_map_simplify(bmap);
4247 bmap = isl_basic_map_drop_redundant_divs(bmap);
4248 return isl_basic_map_finalize(bmap);
4249 error:
4250 isl_basic_map_free(bmap);
4251 return NULL;
4254 /* Turn the n dimensions of type type, starting at first
4255 * into existentially quantified variables.
4257 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
4258 enum isl_dim_type type, unsigned first, unsigned n)
4260 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4261 type, first, n));
4264 /* Turn the n dimensions of type type, starting at first
4265 * into existentially quantified variables.
4267 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4268 enum isl_dim_type type, unsigned first, unsigned n)
4270 int i;
4272 if (n == 0)
4273 return map_space_reset(map, type);
4275 if (isl_map_check_range(map, type, first, n) < 0)
4276 return isl_map_free(map);
4278 map = isl_map_cow(map);
4279 if (!map)
4280 return NULL;
4282 map->dim = isl_space_drop_dims(map->dim, type, first, n);
4283 if (!map->dim)
4284 goto error;
4286 for (i = 0; i < map->n; ++i) {
4287 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4288 if (!map->p[i])
4289 goto error;
4292 return map;
4293 error:
4294 isl_map_free(map);
4295 return NULL;
4298 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4299 * into existentially quantified variables.
4301 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4302 enum isl_dim_type type, unsigned first, unsigned n)
4304 unsigned dim;
4306 if (isl_map_check_range(map, type, first, n) < 0)
4307 return isl_map_free(map);
4308 dim = isl_map_dim(map, type);
4309 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4310 map = isl_map_project_out(map, type, 0, first);
4311 return map;
4314 /* Turn the n dimensions of type type, starting at first
4315 * into existentially quantified variables.
4317 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4318 enum isl_dim_type type, unsigned first, unsigned n)
4320 return set_from_map(isl_map_project_out(set_to_map(set),
4321 type, first, n));
4324 /* Return a map that projects the elements in "set" onto their
4325 * "n" set dimensions starting at "first".
4326 * "type" should be equal to isl_dim_set.
4328 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4329 enum isl_dim_type type, unsigned first, unsigned n)
4331 int i;
4332 isl_map *map;
4334 if (type != isl_dim_set)
4335 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4336 "only set dimensions can be projected out", goto error);
4337 if (isl_set_check_range(set, type, first, n) < 0)
4338 return isl_set_free(set);
4340 map = isl_map_from_domain(set);
4341 map = isl_map_add_dims(map, isl_dim_out, n);
4342 for (i = 0; i < n; ++i)
4343 map = isl_map_equate(map, isl_dim_in, first + i,
4344 isl_dim_out, i);
4345 return map;
4346 error:
4347 isl_set_free(set);
4348 return NULL;
4351 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4352 unsigned n)
4354 int i, j;
4356 for (i = 0; i < n; ++i) {
4357 j = isl_basic_map_alloc_div(bmap);
4358 if (j < 0)
4359 goto error;
4360 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4362 return bmap;
4363 error:
4364 isl_basic_map_free(bmap);
4365 return NULL;
4368 struct isl_basic_map *isl_basic_map_apply_range(
4369 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4371 isl_space *space_result = NULL;
4372 struct isl_basic_map *bmap;
4373 unsigned n_in, n_out, n, nparam, total, pos;
4374 struct isl_dim_map *dim_map1, *dim_map2;
4376 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4377 goto error;
4378 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4379 bmap2->dim, isl_dim_in))
4380 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4381 "spaces don't match", goto error);
4383 space_result = isl_space_join(isl_space_copy(bmap1->dim),
4384 isl_space_copy(bmap2->dim));
4386 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4387 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4388 n = isl_basic_map_dim(bmap1, isl_dim_out);
4389 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4391 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4392 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4393 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4394 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4395 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4396 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4397 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4398 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4399 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4400 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4401 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4403 bmap = isl_basic_map_alloc_space(space_result,
4404 bmap1->n_div + bmap2->n_div + n,
4405 bmap1->n_eq + bmap2->n_eq,
4406 bmap1->n_ineq + bmap2->n_ineq);
4407 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4408 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4409 bmap = add_divs(bmap, n);
4410 bmap = isl_basic_map_simplify(bmap);
4411 bmap = isl_basic_map_drop_redundant_divs(bmap);
4412 return isl_basic_map_finalize(bmap);
4413 error:
4414 isl_basic_map_free(bmap1);
4415 isl_basic_map_free(bmap2);
4416 return NULL;
4419 struct isl_basic_set *isl_basic_set_apply(
4420 struct isl_basic_set *bset, struct isl_basic_map *bmap)
4422 if (!bset || !bmap)
4423 goto error;
4425 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4426 goto error);
4428 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4429 bmap));
4430 error:
4431 isl_basic_set_free(bset);
4432 isl_basic_map_free(bmap);
4433 return NULL;
4436 struct isl_basic_map *isl_basic_map_apply_domain(
4437 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4439 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4440 goto error;
4441 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4442 bmap2->dim, isl_dim_in))
4443 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4444 "spaces don't match", goto error);
4446 bmap1 = isl_basic_map_reverse(bmap1);
4447 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4448 return isl_basic_map_reverse(bmap1);
4449 error:
4450 isl_basic_map_free(bmap1);
4451 isl_basic_map_free(bmap2);
4452 return NULL;
4455 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4456 * A \cap B -> f(A) + f(B)
4458 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4459 __isl_take isl_basic_map *bmap2)
4461 unsigned n_in, n_out, nparam, total, pos;
4462 struct isl_basic_map *bmap = NULL;
4463 struct isl_dim_map *dim_map1, *dim_map2;
4464 int i;
4466 if (!bmap1 || !bmap2)
4467 goto error;
4469 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4470 goto error);
4472 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4473 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4474 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4476 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4477 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4478 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4479 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4480 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4481 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4482 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4483 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4484 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4485 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4486 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4488 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4489 bmap1->n_div + bmap2->n_div + 2 * n_out,
4490 bmap1->n_eq + bmap2->n_eq + n_out,
4491 bmap1->n_ineq + bmap2->n_ineq);
4492 for (i = 0; i < n_out; ++i) {
4493 int j = isl_basic_map_alloc_equality(bmap);
4494 if (j < 0)
4495 goto error;
4496 isl_seq_clr(bmap->eq[j], 1+total);
4497 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4498 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4499 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4501 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4502 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4503 bmap = add_divs(bmap, 2 * n_out);
4505 bmap = isl_basic_map_simplify(bmap);
4506 return isl_basic_map_finalize(bmap);
4507 error:
4508 isl_basic_map_free(bmap);
4509 isl_basic_map_free(bmap1);
4510 isl_basic_map_free(bmap2);
4511 return NULL;
4514 /* Given two maps A -> f(A) and B -> g(B), construct a map
4515 * A \cap B -> f(A) + f(B)
4517 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4518 __isl_take isl_map *map2)
4520 struct isl_map *result;
4521 int i, j;
4523 if (!map1 || !map2)
4524 goto error;
4526 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4528 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4529 map1->n * map2->n, 0);
4530 if (!result)
4531 goto error;
4532 for (i = 0; i < map1->n; ++i)
4533 for (j = 0; j < map2->n; ++j) {
4534 struct isl_basic_map *part;
4535 part = isl_basic_map_sum(
4536 isl_basic_map_copy(map1->p[i]),
4537 isl_basic_map_copy(map2->p[j]));
4538 if (isl_basic_map_is_empty(part))
4539 isl_basic_map_free(part);
4540 else
4541 result = isl_map_add_basic_map(result, part);
4542 if (!result)
4543 goto error;
4545 isl_map_free(map1);
4546 isl_map_free(map2);
4547 return result;
4548 error:
4549 isl_map_free(map1);
4550 isl_map_free(map2);
4551 return NULL;
4554 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4555 __isl_take isl_set *set2)
4557 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4560 /* Given a basic map A -> f(A), construct A -> -f(A).
4562 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4564 int i, j;
4565 unsigned off, n;
4567 bmap = isl_basic_map_cow(bmap);
4568 if (!bmap)
4569 return NULL;
4571 n = isl_basic_map_dim(bmap, isl_dim_out);
4572 off = isl_basic_map_offset(bmap, isl_dim_out);
4573 for (i = 0; i < bmap->n_eq; ++i)
4574 for (j = 0; j < n; ++j)
4575 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4576 for (i = 0; i < bmap->n_ineq; ++i)
4577 for (j = 0; j < n; ++j)
4578 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4579 for (i = 0; i < bmap->n_div; ++i)
4580 for (j = 0; j < n; ++j)
4581 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4582 bmap = isl_basic_map_gauss(bmap, NULL);
4583 return isl_basic_map_finalize(bmap);
4586 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4588 return isl_basic_map_neg(bset);
4591 /* Given a map A -> f(A), construct A -> -f(A).
4593 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4595 int i;
4597 map = isl_map_cow(map);
4598 if (!map)
4599 return NULL;
4601 for (i = 0; i < map->n; ++i) {
4602 map->p[i] = isl_basic_map_neg(map->p[i]);
4603 if (!map->p[i])
4604 goto error;
4607 return map;
4608 error:
4609 isl_map_free(map);
4610 return NULL;
4613 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4615 return set_from_map(isl_map_neg(set_to_map(set)));
4618 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4619 * A -> floor(f(A)/d).
4621 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4622 isl_int d)
4624 unsigned n_in, n_out, nparam, total, pos;
4625 struct isl_basic_map *result = NULL;
4626 struct isl_dim_map *dim_map;
4627 int i;
4629 if (!bmap)
4630 return NULL;
4632 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4633 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4634 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4636 total = nparam + n_in + n_out + bmap->n_div + n_out;
4637 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4638 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4639 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4640 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4641 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4643 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4644 bmap->n_div + n_out,
4645 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4646 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4647 result = add_divs(result, n_out);
4648 for (i = 0; i < n_out; ++i) {
4649 int j;
4650 j = isl_basic_map_alloc_inequality(result);
4651 if (j < 0)
4652 goto error;
4653 isl_seq_clr(result->ineq[j], 1+total);
4654 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4655 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4656 j = isl_basic_map_alloc_inequality(result);
4657 if (j < 0)
4658 goto error;
4659 isl_seq_clr(result->ineq[j], 1+total);
4660 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4661 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4662 isl_int_sub_ui(result->ineq[j][0], d, 1);
4665 result = isl_basic_map_simplify(result);
4666 return isl_basic_map_finalize(result);
4667 error:
4668 isl_basic_map_free(result);
4669 return NULL;
4672 /* Given a map A -> f(A) and an integer d, construct a map
4673 * A -> floor(f(A)/d).
4675 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4677 int i;
4679 map = isl_map_cow(map);
4680 if (!map)
4681 return NULL;
4683 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4684 for (i = 0; i < map->n; ++i) {
4685 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4686 if (!map->p[i])
4687 goto error;
4689 map = isl_map_unmark_normalized(map);
4691 return map;
4692 error:
4693 isl_map_free(map);
4694 return NULL;
4697 /* Given a map A -> f(A) and an integer d, construct a map
4698 * A -> floor(f(A)/d).
4700 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4701 __isl_take isl_val *d)
4703 if (!map || !d)
4704 goto error;
4705 if (!isl_val_is_int(d))
4706 isl_die(isl_val_get_ctx(d), isl_error_invalid,
4707 "expecting integer denominator", goto error);
4708 map = isl_map_floordiv(map, d->n);
4709 isl_val_free(d);
4710 return map;
4711 error:
4712 isl_map_free(map);
4713 isl_val_free(d);
4714 return NULL;
4717 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
4718 unsigned pos)
4720 int i;
4721 unsigned nparam;
4722 unsigned n_in;
4724 i = isl_basic_map_alloc_equality(bmap);
4725 if (i < 0)
4726 goto error;
4727 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4728 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4729 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4730 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4731 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4732 return isl_basic_map_finalize(bmap);
4733 error:
4734 isl_basic_map_free(bmap);
4735 return NULL;
4738 /* Add a constraint to "bmap" expressing i_pos < o_pos
4740 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
4741 unsigned pos)
4743 int i;
4744 unsigned nparam;
4745 unsigned n_in;
4747 i = isl_basic_map_alloc_inequality(bmap);
4748 if (i < 0)
4749 goto error;
4750 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4751 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4752 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4753 isl_int_set_si(bmap->ineq[i][0], -1);
4754 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4755 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4756 return isl_basic_map_finalize(bmap);
4757 error:
4758 isl_basic_map_free(bmap);
4759 return NULL;
4762 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4764 static __isl_give isl_basic_map *var_less_or_equal(
4765 __isl_take isl_basic_map *bmap, unsigned pos)
4767 int i;
4768 unsigned nparam;
4769 unsigned n_in;
4771 i = isl_basic_map_alloc_inequality(bmap);
4772 if (i < 0)
4773 goto error;
4774 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4775 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4776 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4777 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4778 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4779 return isl_basic_map_finalize(bmap);
4780 error:
4781 isl_basic_map_free(bmap);
4782 return NULL;
4785 /* Add a constraint to "bmap" expressing i_pos > o_pos
4787 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
4788 unsigned pos)
4790 int i;
4791 unsigned nparam;
4792 unsigned n_in;
4794 i = isl_basic_map_alloc_inequality(bmap);
4795 if (i < 0)
4796 goto error;
4797 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4798 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4799 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4800 isl_int_set_si(bmap->ineq[i][0], -1);
4801 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4802 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4803 return isl_basic_map_finalize(bmap);
4804 error:
4805 isl_basic_map_free(bmap);
4806 return NULL;
4809 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4811 static __isl_give isl_basic_map *var_more_or_equal(
4812 __isl_take isl_basic_map *bmap, unsigned pos)
4814 int i;
4815 unsigned nparam;
4816 unsigned n_in;
4818 i = isl_basic_map_alloc_inequality(bmap);
4819 if (i < 0)
4820 goto error;
4821 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4822 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4823 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4824 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4825 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4826 return isl_basic_map_finalize(bmap);
4827 error:
4828 isl_basic_map_free(bmap);
4829 return NULL;
4832 __isl_give isl_basic_map *isl_basic_map_equal(
4833 __isl_take isl_space *space, unsigned n_equal)
4835 int i;
4836 struct isl_basic_map *bmap;
4837 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
4838 if (!bmap)
4839 return NULL;
4840 for (i = 0; i < n_equal && bmap; ++i)
4841 bmap = var_equal(bmap, i);
4842 return isl_basic_map_finalize(bmap);
4845 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
4847 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
4848 unsigned pos)
4850 int i;
4851 struct isl_basic_map *bmap;
4852 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4853 if (!bmap)
4854 return NULL;
4855 for (i = 0; i < pos && bmap; ++i)
4856 bmap = var_equal(bmap, i);
4857 if (bmap)
4858 bmap = var_less(bmap, pos);
4859 return isl_basic_map_finalize(bmap);
4862 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
4864 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4865 __isl_take isl_space *space, unsigned pos)
4867 int i;
4868 isl_basic_map *bmap;
4870 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4871 for (i = 0; i < pos; ++i)
4872 bmap = var_equal(bmap, i);
4873 bmap = var_less_or_equal(bmap, pos);
4874 return isl_basic_map_finalize(bmap);
4877 /* Return a relation on "space" expressing i_pos > o_pos
4879 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
4880 unsigned pos)
4882 int i;
4883 struct isl_basic_map *bmap;
4884 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4885 if (!bmap)
4886 return NULL;
4887 for (i = 0; i < pos && bmap; ++i)
4888 bmap = var_equal(bmap, i);
4889 if (bmap)
4890 bmap = var_more(bmap, pos);
4891 return isl_basic_map_finalize(bmap);
4894 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
4896 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4897 __isl_take isl_space *space, unsigned pos)
4899 int i;
4900 isl_basic_map *bmap;
4902 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4903 for (i = 0; i < pos; ++i)
4904 bmap = var_equal(bmap, i);
4905 bmap = var_more_or_equal(bmap, pos);
4906 return isl_basic_map_finalize(bmap);
4909 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
4910 unsigned n, int equal)
4912 struct isl_map *map;
4913 int i;
4915 if (n == 0 && equal)
4916 return isl_map_universe(space);
4918 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
4920 for (i = 0; i + 1 < n; ++i)
4921 map = isl_map_add_basic_map(map,
4922 isl_basic_map_less_at(isl_space_copy(space), i));
4923 if (n > 0) {
4924 if (equal)
4925 map = isl_map_add_basic_map(map,
4926 isl_basic_map_less_or_equal_at(space, n - 1));
4927 else
4928 map = isl_map_add_basic_map(map,
4929 isl_basic_map_less_at(space, n - 1));
4930 } else
4931 isl_space_free(space);
4933 return map;
4936 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
4938 if (!space)
4939 return NULL;
4940 return map_lex_lte_first(space, space->n_out, equal);
4943 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
4945 return map_lex_lte_first(dim, n, 0);
4948 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
4950 return map_lex_lte_first(dim, n, 1);
4953 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
4955 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
4958 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
4960 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
4963 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
4964 unsigned n, int equal)
4966 struct isl_map *map;
4967 int i;
4969 if (n == 0 && equal)
4970 return isl_map_universe(space);
4972 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
4974 for (i = 0; i + 1 < n; ++i)
4975 map = isl_map_add_basic_map(map,
4976 isl_basic_map_more_at(isl_space_copy(space), i));
4977 if (n > 0) {
4978 if (equal)
4979 map = isl_map_add_basic_map(map,
4980 isl_basic_map_more_or_equal_at(space, n - 1));
4981 else
4982 map = isl_map_add_basic_map(map,
4983 isl_basic_map_more_at(space, n - 1));
4984 } else
4985 isl_space_free(space);
4987 return map;
4990 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
4992 if (!space)
4993 return NULL;
4994 return map_lex_gte_first(space, space->n_out, equal);
4997 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
4999 return map_lex_gte_first(dim, n, 0);
5002 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
5004 return map_lex_gte_first(dim, n, 1);
5007 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
5009 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
5012 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
5014 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
5017 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5018 __isl_take isl_set *set2)
5020 isl_map *map;
5021 map = isl_map_lex_le(isl_set_get_space(set1));
5022 map = isl_map_intersect_domain(map, set1);
5023 map = isl_map_intersect_range(map, set2);
5024 return map;
5027 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5028 __isl_take isl_set *set2)
5030 isl_map *map;
5031 map = isl_map_lex_lt(isl_set_get_space(set1));
5032 map = isl_map_intersect_domain(map, set1);
5033 map = isl_map_intersect_range(map, set2);
5034 return map;
5037 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5038 __isl_take isl_set *set2)
5040 isl_map *map;
5041 map = isl_map_lex_ge(isl_set_get_space(set1));
5042 map = isl_map_intersect_domain(map, set1);
5043 map = isl_map_intersect_range(map, set2);
5044 return map;
5047 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5048 __isl_take isl_set *set2)
5050 isl_map *map;
5051 map = isl_map_lex_gt(isl_set_get_space(set1));
5052 map = isl_map_intersect_domain(map, set1);
5053 map = isl_map_intersect_range(map, set2);
5054 return map;
5057 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5058 __isl_take isl_map *map2)
5060 isl_map *map;
5061 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5062 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5063 map = isl_map_apply_range(map, isl_map_reverse(map2));
5064 return map;
5067 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5068 __isl_take isl_map *map2)
5070 isl_map *map;
5071 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5072 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5073 map = isl_map_apply_range(map, isl_map_reverse(map2));
5074 return map;
5077 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5078 __isl_take isl_map *map2)
5080 isl_map *map;
5081 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5082 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5083 map = isl_map_apply_range(map, isl_map_reverse(map2));
5084 return map;
5087 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5088 __isl_take isl_map *map2)
5090 isl_map *map;
5091 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5092 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5093 map = isl_map_apply_range(map, isl_map_reverse(map2));
5094 return map;
5097 /* For the div d = floor(f/m) at position "div", add the constraint
5099 * f - m d >= 0
5101 static __isl_give isl_basic_map *add_upper_div_constraint(
5102 __isl_take isl_basic_map *bmap, unsigned div)
5104 int i;
5105 int v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5106 unsigned n_div, pos;
5108 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5109 if (v_div < 0)
5110 return isl_basic_map_free(bmap);
5111 pos = v_div + div;
5112 i = isl_basic_map_alloc_inequality(bmap);
5113 if (i < 0)
5114 return isl_basic_map_free(bmap);
5115 isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5116 isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5118 return bmap;
5121 /* For the div d = floor(f/m) at position "div", add the constraint
5123 * -(f-(m-1)) + m d >= 0
5125 static __isl_give isl_basic_map *add_lower_div_constraint(
5126 __isl_take isl_basic_map *bmap, unsigned div)
5128 int i;
5129 int v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5130 unsigned n_div, pos;
5132 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5133 if (v_div < 0)
5134 return isl_basic_map_free(bmap);
5135 pos = v_div + div;
5136 i = isl_basic_map_alloc_inequality(bmap);
5137 if (i < 0)
5138 return isl_basic_map_free(bmap);
5139 isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5140 isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5141 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5142 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5144 return bmap;
5147 /* For the div d = floor(f/m) at position "pos", add the constraints
5149 * f - m d >= 0
5150 * -(f-(m-1)) + m d >= 0
5152 * Note that the second constraint is the negation of
5154 * f - m d >= m
5156 __isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5157 __isl_take isl_basic_map *bmap, unsigned pos)
5159 bmap = add_upper_div_constraint(bmap, pos);
5160 bmap = add_lower_div_constraint(bmap, pos);
5161 return bmap;
5164 /* For each known div d = floor(f/m), add the constraints
5166 * f - m d >= 0
5167 * -(f-(m-1)) + m d >= 0
5169 * Remove duplicate constraints in case of some these div constraints
5170 * already appear in "bmap".
5172 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5173 __isl_take isl_basic_map *bmap)
5175 unsigned n_div;
5177 if (!bmap)
5178 return NULL;
5179 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5180 if (n_div == 0)
5181 return bmap;
5183 bmap = add_known_div_constraints(bmap);
5184 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5185 bmap = isl_basic_map_finalize(bmap);
5186 return bmap;
5189 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5191 * In particular, if this div is of the form d = floor(f/m),
5192 * then add the constraint
5194 * f - m d >= 0
5196 * if sign < 0 or the constraint
5198 * -(f-(m-1)) + m d >= 0
5200 * if sign > 0.
5202 __isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5203 __isl_take isl_basic_map *bmap, unsigned div, int sign)
5205 if (sign < 0)
5206 return add_upper_div_constraint(bmap, div);
5207 else
5208 return add_lower_div_constraint(bmap, div);
5211 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5212 __isl_take isl_basic_map *bmap)
5214 if (!bmap)
5215 goto error;
5216 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5217 bmap->n_div == 0 &&
5218 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5219 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5220 return bset_from_bmap(bmap);
5221 bmap = isl_basic_map_cow(bmap);
5222 if (!bmap)
5223 goto error;
5224 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
5225 if (!bmap->dim)
5226 goto error;
5227 bmap->extra -= bmap->n_div;
5228 bmap->n_div = 0;
5229 bmap = isl_basic_map_finalize(bmap);
5230 return bset_from_bmap(bmap);
5231 error:
5232 isl_basic_map_free(bmap);
5233 return NULL;
5236 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5237 __isl_take isl_basic_set *bset)
5239 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5242 /* Replace each element in "list" by the result of applying
5243 * isl_basic_map_underlying_set to the element.
5245 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5246 __isl_take isl_basic_map_list *list)
5248 int i, n;
5250 if (!list)
5251 return NULL;
5253 n = isl_basic_map_list_n_basic_map(list);
5254 for (i = 0; i < n; ++i) {
5255 isl_basic_map *bmap;
5256 isl_basic_set *bset;
5258 bmap = isl_basic_map_list_get_basic_map(list, i);
5259 bset = isl_basic_set_underlying_set(bmap);
5260 list = isl_basic_set_list_set_basic_set(list, i, bset);
5263 return list;
5266 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5267 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5269 struct isl_basic_map *bmap;
5270 struct isl_ctx *ctx;
5271 unsigned total;
5272 int i;
5274 if (!bset || !like)
5275 goto error;
5276 ctx = bset->ctx;
5277 if (isl_basic_set_check_no_params(bset) < 0 ||
5278 isl_basic_set_check_no_locals(bset) < 0)
5279 goto error;
5280 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
5281 goto error);
5282 if (like->n_div == 0) {
5283 isl_space *space = isl_basic_map_get_space(like);
5284 isl_basic_map_free(like);
5285 return isl_basic_map_reset_space(bset, space);
5287 bset = isl_basic_set_cow(bset);
5288 if (!bset)
5289 goto error;
5290 total = bset->dim->n_out + bset->extra;
5291 bmap = bset_to_bmap(bset);
5292 isl_space_free(bmap->dim);
5293 bmap->dim = isl_space_copy(like->dim);
5294 if (!bmap->dim)
5295 goto error;
5296 bmap->n_div = like->n_div;
5297 bmap->extra += like->n_div;
5298 if (bmap->extra) {
5299 unsigned ltotal;
5300 isl_int **div;
5301 ltotal = total - bmap->extra + like->extra;
5302 if (ltotal > total)
5303 ltotal = total;
5304 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5305 bmap->extra * (1 + 1 + total));
5306 if (isl_blk_is_error(bmap->block2))
5307 goto error;
5308 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5309 if (!div)
5310 goto error;
5311 bmap->div = div;
5312 for (i = 0; i < bmap->extra; ++i)
5313 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5314 for (i = 0; i < like->n_div; ++i) {
5315 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5316 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5318 bmap = isl_basic_map_add_known_div_constraints(bmap);
5320 isl_basic_map_free(like);
5321 bmap = isl_basic_map_simplify(bmap);
5322 bmap = isl_basic_map_finalize(bmap);
5323 return bmap;
5324 error:
5325 isl_basic_map_free(like);
5326 isl_basic_set_free(bset);
5327 return NULL;
5330 struct isl_basic_set *isl_basic_set_from_underlying_set(
5331 struct isl_basic_set *bset, struct isl_basic_set *like)
5333 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5334 bset_to_bmap(like)));
5337 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5339 int i;
5341 map = isl_map_cow(map);
5342 if (!map)
5343 return NULL;
5344 map->dim = isl_space_cow(map->dim);
5345 if (!map->dim)
5346 goto error;
5348 for (i = 1; i < map->n; ++i)
5349 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5350 goto error);
5351 for (i = 0; i < map->n; ++i) {
5352 map->p[i] = bset_to_bmap(
5353 isl_basic_map_underlying_set(map->p[i]));
5354 if (!map->p[i])
5355 goto error;
5357 if (map->n == 0)
5358 map->dim = isl_space_underlying(map->dim, 0);
5359 else {
5360 isl_space_free(map->dim);
5361 map->dim = isl_space_copy(map->p[0]->dim);
5363 if (!map->dim)
5364 goto error;
5365 return set_from_map(map);
5366 error:
5367 isl_map_free(map);
5368 return NULL;
5371 /* Replace the space of "bmap" by "space".
5373 * If the space of "bmap" is identical to "space" (including the identifiers
5374 * of the input and output dimensions), then simply return the original input.
5376 __isl_give isl_basic_map *isl_basic_map_reset_space(
5377 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5379 isl_bool equal;
5380 isl_space *bmap_space;
5382 bmap_space = isl_basic_map_peek_space(bmap);
5383 equal = isl_space_is_equal(bmap_space, space);
5384 if (equal >= 0 && equal)
5385 equal = isl_space_has_equal_ids(bmap_space, space);
5386 if (equal < 0)
5387 goto error;
5388 if (equal) {
5389 isl_space_free(space);
5390 return bmap;
5392 bmap = isl_basic_map_cow(bmap);
5393 if (!bmap || !space)
5394 goto error;
5396 isl_space_free(bmap->dim);
5397 bmap->dim = space;
5399 bmap = isl_basic_map_finalize(bmap);
5401 return bmap;
5402 error:
5403 isl_basic_map_free(bmap);
5404 isl_space_free(space);
5405 return NULL;
5408 __isl_give isl_basic_set *isl_basic_set_reset_space(
5409 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5411 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5412 dim));
5415 /* Check that the total dimensions of "map" and "space" are the same.
5417 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5418 __isl_keep isl_space *space)
5420 unsigned dim1, dim2;
5422 if (!map || !space)
5423 return isl_stat_error;
5424 dim1 = isl_map_dim(map, isl_dim_all);
5425 dim2 = isl_space_dim(space, isl_dim_all);
5426 if (dim1 == dim2)
5427 return isl_stat_ok;
5428 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5429 "total dimensions do not match", return isl_stat_error);
5432 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5433 __isl_take isl_space *space)
5435 int i;
5437 map = isl_map_cow(map);
5438 if (!map || !space)
5439 goto error;
5441 for (i = 0; i < map->n; ++i) {
5442 map->p[i] = isl_basic_map_reset_space(map->p[i],
5443 isl_space_copy(space));
5444 if (!map->p[i])
5445 goto error;
5447 isl_space_free(map->dim);
5448 map->dim = space;
5450 return map;
5451 error:
5452 isl_map_free(map);
5453 isl_space_free(space);
5454 return NULL;
5457 /* Replace the space of "map" by "space", without modifying
5458 * the dimension of "map".
5460 * If the space of "map" is identical to "space" (including the identifiers
5461 * of the input and output dimensions), then simply return the original input.
5463 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5464 __isl_take isl_space *space)
5466 isl_bool equal;
5467 isl_space *map_space;
5469 map_space = isl_map_peek_space(map);
5470 equal = isl_space_is_equal(map_space, space);
5471 if (equal >= 0 && equal)
5472 equal = isl_space_has_equal_ids(map_space, space);
5473 if (equal < 0)
5474 goto error;
5475 if (equal) {
5476 isl_space_free(space);
5477 return map;
5479 if (check_map_space_equal_total_dim(map, space) < 0)
5480 goto error;
5481 return isl_map_reset_space(map, space);
5482 error:
5483 isl_map_free(map);
5484 isl_space_free(space);
5485 return NULL;
5488 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5489 __isl_take isl_space *dim)
5491 return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5494 /* Compute the parameter domain of the given basic set.
5496 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5498 isl_bool is_params;
5499 isl_space *space;
5500 unsigned n;
5502 is_params = isl_basic_set_is_params(bset);
5503 if (is_params < 0)
5504 return isl_basic_set_free(bset);
5505 if (is_params)
5506 return bset;
5508 n = isl_basic_set_dim(bset, isl_dim_set);
5509 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5510 space = isl_basic_set_get_space(bset);
5511 space = isl_space_params(space);
5512 bset = isl_basic_set_reset_space(bset, space);
5513 return bset;
5516 /* Construct a zero-dimensional basic set with the given parameter domain.
5518 __isl_give isl_basic_set *isl_basic_set_from_params(
5519 __isl_take isl_basic_set *bset)
5521 isl_space *space;
5522 space = isl_basic_set_get_space(bset);
5523 space = isl_space_set_from_params(space);
5524 bset = isl_basic_set_reset_space(bset, space);
5525 return bset;
5528 /* Compute the parameter domain of the given set.
5530 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5532 isl_space *space;
5533 unsigned n;
5535 if (isl_set_is_params(set))
5536 return set;
5538 n = isl_set_dim(set, isl_dim_set);
5539 set = isl_set_project_out(set, isl_dim_set, 0, n);
5540 space = isl_set_get_space(set);
5541 space = isl_space_params(space);
5542 set = isl_set_reset_space(set, space);
5543 return set;
5546 /* Construct a zero-dimensional set with the given parameter domain.
5548 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5550 isl_space *space;
5551 space = isl_set_get_space(set);
5552 space = isl_space_set_from_params(space);
5553 set = isl_set_reset_space(set, space);
5554 return set;
5557 /* Compute the parameter domain of the given map.
5559 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5561 isl_space *space;
5562 unsigned n;
5564 n = isl_map_dim(map, isl_dim_in);
5565 map = isl_map_project_out(map, isl_dim_in, 0, n);
5566 n = isl_map_dim(map, isl_dim_out);
5567 map = isl_map_project_out(map, isl_dim_out, 0, n);
5568 space = isl_map_get_space(map);
5569 space = isl_space_params(space);
5570 map = isl_map_reset_space(map, space);
5571 return map;
5574 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5576 isl_space *space;
5577 unsigned n_out;
5579 if (!bmap)
5580 return NULL;
5581 space = isl_space_domain(isl_basic_map_get_space(bmap));
5583 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5584 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5586 return isl_basic_map_reset_space(bmap, space);
5589 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5591 if (!bmap)
5592 return isl_bool_error;
5593 return isl_space_may_be_set(bmap->dim);
5596 /* Is this basic map actually a set?
5597 * Users should never call this function. Outside of isl,
5598 * the type should indicate whether something is a set or a map.
5600 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5602 if (!bmap)
5603 return isl_bool_error;
5604 return isl_space_is_set(bmap->dim);
5607 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5609 isl_bool is_set;
5611 is_set = isl_basic_map_is_set(bmap);
5612 if (is_set < 0)
5613 goto error;
5614 if (is_set)
5615 return bmap;
5616 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5617 error:
5618 isl_basic_map_free(bmap);
5619 return NULL;
5622 __isl_give isl_basic_map *isl_basic_map_domain_map(
5623 __isl_take isl_basic_map *bmap)
5625 int i;
5626 isl_space *space;
5627 isl_basic_map *domain;
5628 int nparam, n_in, n_out;
5630 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5631 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5632 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5634 space = isl_basic_map_get_space(bmap);
5635 space = isl_space_from_range(isl_space_domain(space));
5636 domain = isl_basic_map_universe(space);
5638 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5639 bmap = isl_basic_map_apply_range(bmap, domain);
5640 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5642 for (i = 0; i < n_in; ++i)
5643 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5644 isl_dim_out, i);
5646 bmap = isl_basic_map_gauss(bmap, NULL);
5647 return isl_basic_map_finalize(bmap);
5650 __isl_give isl_basic_map *isl_basic_map_range_map(
5651 __isl_take isl_basic_map *bmap)
5653 int i;
5654 isl_space *space;
5655 isl_basic_map *range;
5656 int nparam, n_in, n_out;
5658 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5659 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5660 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5662 space = isl_basic_map_get_space(bmap);
5663 space = isl_space_from_range(isl_space_range(space));
5664 range = isl_basic_map_universe(space);
5666 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5667 bmap = isl_basic_map_apply_range(bmap, range);
5668 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5670 for (i = 0; i < n_out; ++i)
5671 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5672 isl_dim_out, i);
5674 bmap = isl_basic_map_gauss(bmap, NULL);
5675 return isl_basic_map_finalize(bmap);
5678 int isl_map_may_be_set(__isl_keep isl_map *map)
5680 if (!map)
5681 return -1;
5682 return isl_space_may_be_set(map->dim);
5685 /* Is this map actually a set?
5686 * Users should never call this function. Outside of isl,
5687 * the type should indicate whether something is a set or a map.
5689 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5691 if (!map)
5692 return isl_bool_error;
5693 return isl_space_is_set(map->dim);
5696 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
5698 int i;
5699 isl_bool is_set;
5700 struct isl_set *set;
5702 is_set = isl_map_is_set(map);
5703 if (is_set < 0)
5704 goto error;
5705 if (is_set)
5706 return set_from_map(map);
5708 map = isl_map_cow(map);
5709 if (!map)
5710 goto error;
5712 set = set_from_map(map);
5713 set->dim = isl_space_range(set->dim);
5714 if (!set->dim)
5715 goto error;
5716 for (i = 0; i < map->n; ++i) {
5717 set->p[i] = isl_basic_map_range(map->p[i]);
5718 if (!set->p[i])
5719 goto error;
5721 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5722 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5723 return set;
5724 error:
5725 isl_map_free(map);
5726 return NULL;
5729 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5731 int i;
5733 map = isl_map_cow(map);
5734 if (!map)
5735 return NULL;
5737 map->dim = isl_space_domain_map(map->dim);
5738 if (!map->dim)
5739 goto error;
5740 for (i = 0; i < map->n; ++i) {
5741 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5742 if (!map->p[i])
5743 goto error;
5745 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5746 map = isl_map_unmark_normalized(map);
5747 return map;
5748 error:
5749 isl_map_free(map);
5750 return NULL;
5753 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5755 int i;
5756 isl_space *range_dim;
5758 map = isl_map_cow(map);
5759 if (!map)
5760 return NULL;
5762 range_dim = isl_space_range(isl_map_get_space(map));
5763 range_dim = isl_space_from_range(range_dim);
5764 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5765 map->dim = isl_space_join(map->dim, range_dim);
5766 if (!map->dim)
5767 goto error;
5768 for (i = 0; i < map->n; ++i) {
5769 map->p[i] = isl_basic_map_range_map(map->p[i]);
5770 if (!map->p[i])
5771 goto error;
5773 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5774 map = isl_map_unmark_normalized(map);
5775 return map;
5776 error:
5777 isl_map_free(map);
5778 return NULL;
5781 /* Given a wrapped map of the form A[B -> C],
5782 * return the map A[B -> C] -> B.
5784 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5786 isl_id *id;
5787 isl_map *map;
5789 if (!set)
5790 return NULL;
5791 if (!isl_set_has_tuple_id(set))
5792 return isl_map_domain_map(isl_set_unwrap(set));
5794 id = isl_set_get_tuple_id(set);
5795 map = isl_map_domain_map(isl_set_unwrap(set));
5796 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5798 return map;
5801 __isl_give isl_basic_map *isl_basic_map_from_domain(
5802 __isl_take isl_basic_set *bset)
5804 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5807 __isl_give isl_basic_map *isl_basic_map_from_range(
5808 __isl_take isl_basic_set *bset)
5810 isl_space *space;
5811 space = isl_basic_set_get_space(bset);
5812 space = isl_space_from_range(space);
5813 bset = isl_basic_set_reset_space(bset, space);
5814 return bset_to_bmap(bset);
5817 /* Create a relation with the given set as range.
5818 * The domain of the created relation is a zero-dimensional
5819 * flat anonymous space.
5821 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5823 isl_space *space;
5824 space = isl_set_get_space(set);
5825 space = isl_space_from_range(space);
5826 set = isl_set_reset_space(set, space);
5827 return set_to_map(set);
5830 /* Create a relation with the given set as domain.
5831 * The range of the created relation is a zero-dimensional
5832 * flat anonymous space.
5834 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5836 return isl_map_reverse(isl_map_from_range(set));
5839 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5840 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5842 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5845 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5846 __isl_take isl_set *range)
5848 return isl_map_apply_range(isl_map_reverse(domain), range);
5851 /* Return a newly allocated isl_map with given space and flags and
5852 * room for "n" basic maps.
5853 * Make sure that all cached information is cleared.
5855 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5856 unsigned flags)
5858 struct isl_map *map;
5860 if (!space)
5861 return NULL;
5862 if (n < 0)
5863 isl_die(space->ctx, isl_error_internal,
5864 "negative number of basic maps", goto error);
5865 map = isl_calloc(space->ctx, struct isl_map,
5866 sizeof(struct isl_map) +
5867 (n - 1) * sizeof(struct isl_basic_map *));
5868 if (!map)
5869 goto error;
5871 map->ctx = space->ctx;
5872 isl_ctx_ref(map->ctx);
5873 map->ref = 1;
5874 map->size = n;
5875 map->n = 0;
5876 map->dim = space;
5877 map->flags = flags;
5878 return map;
5879 error:
5880 isl_space_free(space);
5881 return NULL;
5884 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
5886 struct isl_basic_map *bmap;
5887 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
5888 bmap = isl_basic_map_set_to_empty(bmap);
5889 return bmap;
5892 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
5894 struct isl_basic_set *bset;
5895 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
5896 bset = isl_basic_set_set_to_empty(bset);
5897 return bset;
5900 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
5902 struct isl_basic_map *bmap;
5903 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
5904 bmap = isl_basic_map_finalize(bmap);
5905 return bmap;
5908 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
5910 struct isl_basic_set *bset;
5911 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
5912 bset = isl_basic_set_finalize(bset);
5913 return bset;
5916 __isl_give isl_basic_map *isl_basic_map_nat_universe(
5917 __isl_take isl_space *space)
5919 int i;
5920 unsigned total = isl_space_dim(space, isl_dim_all);
5921 isl_basic_map *bmap;
5923 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
5924 for (i = 0; i < total; ++i) {
5925 int k = isl_basic_map_alloc_inequality(bmap);
5926 if (k < 0)
5927 goto error;
5928 isl_seq_clr(bmap->ineq[k], 1 + total);
5929 isl_int_set_si(bmap->ineq[k][1 + i], 1);
5931 return bmap;
5932 error:
5933 isl_basic_map_free(bmap);
5934 return NULL;
5937 __isl_give isl_basic_set *isl_basic_set_nat_universe(
5938 __isl_take isl_space *space)
5940 return isl_basic_map_nat_universe(space);
5943 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
5945 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
5948 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
5950 return isl_map_nat_universe(dim);
5953 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
5955 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
5958 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
5960 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
5963 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
5965 struct isl_map *map;
5966 if (!space)
5967 return NULL;
5968 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
5969 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
5970 return map;
5973 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
5975 struct isl_set *set;
5976 if (!space)
5977 return NULL;
5978 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
5979 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
5980 return set;
5983 struct isl_map *isl_map_dup(struct isl_map *map)
5985 int i;
5986 struct isl_map *dup;
5988 if (!map)
5989 return NULL;
5990 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
5991 for (i = 0; i < map->n; ++i)
5992 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
5993 return dup;
5996 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
5997 __isl_take isl_basic_map *bmap)
5999 if (!bmap || !map)
6000 goto error;
6001 if (isl_basic_map_plain_is_empty(bmap)) {
6002 isl_basic_map_free(bmap);
6003 return map;
6005 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
6006 isl_assert(map->ctx, map->n < map->size, goto error);
6007 map->p[map->n] = bmap;
6008 map->n++;
6009 map = isl_map_unmark_normalized(map);
6010 return map;
6011 error:
6012 if (map)
6013 isl_map_free(map);
6014 if (bmap)
6015 isl_basic_map_free(bmap);
6016 return NULL;
6019 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6021 int i;
6023 if (!map)
6024 return NULL;
6026 if (--map->ref > 0)
6027 return NULL;
6029 clear_caches(map);
6030 isl_ctx_deref(map->ctx);
6031 for (i = 0; i < map->n; ++i)
6032 isl_basic_map_free(map->p[i]);
6033 isl_space_free(map->dim);
6034 free(map);
6036 return NULL;
6039 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6040 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6042 int j;
6044 bmap = isl_basic_map_cow(bmap);
6045 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6046 j = isl_basic_map_alloc_equality(bmap);
6047 if (j < 0)
6048 goto error;
6049 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6050 isl_int_set_si(bmap->eq[j][pos], -1);
6051 isl_int_set_si(bmap->eq[j][0], value);
6052 bmap = isl_basic_map_simplify(bmap);
6053 return isl_basic_map_finalize(bmap);
6054 error:
6055 isl_basic_map_free(bmap);
6056 return NULL;
6059 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6060 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6062 int j;
6064 bmap = isl_basic_map_cow(bmap);
6065 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6066 j = isl_basic_map_alloc_equality(bmap);
6067 if (j < 0)
6068 goto error;
6069 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6070 isl_int_set_si(bmap->eq[j][pos], -1);
6071 isl_int_set(bmap->eq[j][0], value);
6072 bmap = isl_basic_map_simplify(bmap);
6073 return isl_basic_map_finalize(bmap);
6074 error:
6075 isl_basic_map_free(bmap);
6076 return NULL;
6079 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6080 enum isl_dim_type type, unsigned pos, int value)
6082 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6083 return isl_basic_map_free(bmap);
6084 return isl_basic_map_fix_pos_si(bmap,
6085 isl_basic_map_offset(bmap, type) + pos, value);
6088 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6089 enum isl_dim_type type, unsigned pos, isl_int value)
6091 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6092 return isl_basic_map_free(bmap);
6093 return isl_basic_map_fix_pos(bmap,
6094 isl_basic_map_offset(bmap, type) + pos, value);
6097 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6098 * to be equal to "v".
6100 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6101 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6103 if (!bmap || !v)
6104 goto error;
6105 if (!isl_val_is_int(v))
6106 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6107 "expecting integer value", goto error);
6108 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6109 goto error;
6110 pos += isl_basic_map_offset(bmap, type);
6111 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6112 isl_val_free(v);
6113 return bmap;
6114 error:
6115 isl_basic_map_free(bmap);
6116 isl_val_free(v);
6117 return NULL;
6120 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6121 * to be equal to "v".
6123 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6124 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6126 return isl_basic_map_fix_val(bset, type, pos, v);
6129 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
6130 enum isl_dim_type type, unsigned pos, int value)
6132 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6133 type, pos, value));
6136 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6137 enum isl_dim_type type, unsigned pos, isl_int value)
6139 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6140 type, pos, value));
6143 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
6144 unsigned input, int value)
6146 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
6149 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
6150 unsigned dim, int value)
6152 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6153 isl_dim_set, dim, value));
6156 /* Remove the basic map at position "i" from "map" if this basic map
6157 * is (obviously) empty.
6159 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6161 isl_bool empty;
6163 if (!map)
6164 return NULL;
6166 empty = isl_basic_map_plain_is_empty(map->p[i]);
6167 if (empty < 0)
6168 return isl_map_free(map);
6169 if (!empty)
6170 return map;
6172 isl_basic_map_free(map->p[i]);
6173 map->n--;
6174 if (i != map->n) {
6175 map->p[i] = map->p[map->n];
6176 map = isl_map_unmark_normalized(map);
6180 return map;
6183 /* Perform "fn" on each basic map of "map", where we may not be holding
6184 * the only reference to "map".
6185 * In particular, "fn" should be a semantics preserving operation
6186 * that we want to apply to all copies of "map". We therefore need
6187 * to be careful not to modify "map" in a way that breaks "map"
6188 * in case anything goes wrong.
6190 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6191 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6193 struct isl_basic_map *bmap;
6194 int i;
6196 if (!map)
6197 return NULL;
6199 for (i = map->n - 1; i >= 0; --i) {
6200 bmap = isl_basic_map_copy(map->p[i]);
6201 bmap = fn(bmap);
6202 if (!bmap)
6203 goto error;
6204 isl_basic_map_free(map->p[i]);
6205 map->p[i] = bmap;
6206 map = remove_if_empty(map, i);
6207 if (!map)
6208 return NULL;
6211 return map;
6212 error:
6213 isl_map_free(map);
6214 return NULL;
6217 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6218 enum isl_dim_type type, unsigned pos, int value)
6220 int i;
6222 map = isl_map_cow(map);
6223 if (isl_map_check_range(map, type, pos, 1) < 0)
6224 return isl_map_free(map);
6225 for (i = map->n - 1; i >= 0; --i) {
6226 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6227 map = remove_if_empty(map, i);
6228 if (!map)
6229 return NULL;
6231 map = isl_map_unmark_normalized(map);
6232 return map;
6235 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6236 enum isl_dim_type type, unsigned pos, int value)
6238 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6241 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6242 enum isl_dim_type type, unsigned pos, isl_int value)
6244 int i;
6246 map = isl_map_cow(map);
6247 if (isl_map_check_range(map, type, pos, 1) < 0)
6248 return isl_map_free(map);
6249 for (i = 0; i < map->n; ++i) {
6250 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6251 if (!map->p[i])
6252 goto error;
6254 map = isl_map_unmark_normalized(map);
6255 return map;
6256 error:
6257 isl_map_free(map);
6258 return NULL;
6261 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6262 enum isl_dim_type type, unsigned pos, isl_int value)
6264 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6267 /* Fix the value of the variable at position "pos" of type "type" of "map"
6268 * to be equal to "v".
6270 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6271 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6273 int i;
6275 map = isl_map_cow(map);
6276 if (!map || !v)
6277 goto error;
6279 if (!isl_val_is_int(v))
6280 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6281 "expecting integer value", goto error);
6282 if (isl_map_check_range(map, type, pos, 1) < 0)
6283 goto error;
6284 for (i = map->n - 1; i >= 0; --i) {
6285 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6286 isl_val_copy(v));
6287 map = remove_if_empty(map, i);
6288 if (!map)
6289 goto error;
6291 map = isl_map_unmark_normalized(map);
6292 isl_val_free(v);
6293 return map;
6294 error:
6295 isl_map_free(map);
6296 isl_val_free(v);
6297 return NULL;
6300 /* Fix the value of the variable at position "pos" of type "type" of "set"
6301 * to be equal to "v".
6303 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6304 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6306 return isl_map_fix_val(set, type, pos, v);
6309 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
6310 unsigned input, int value)
6312 return isl_map_fix_si(map, isl_dim_in, input, value);
6315 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
6317 return set_from_map(isl_map_fix_si(set_to_map(set),
6318 isl_dim_set, dim, value));
6321 static __isl_give isl_basic_map *basic_map_bound_si(
6322 __isl_take isl_basic_map *bmap,
6323 enum isl_dim_type type, unsigned pos, int value, int upper)
6325 int j;
6327 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6328 return isl_basic_map_free(bmap);
6329 pos += isl_basic_map_offset(bmap, type);
6330 bmap = isl_basic_map_cow(bmap);
6331 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6332 j = isl_basic_map_alloc_inequality(bmap);
6333 if (j < 0)
6334 goto error;
6335 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6336 if (upper) {
6337 isl_int_set_si(bmap->ineq[j][pos], -1);
6338 isl_int_set_si(bmap->ineq[j][0], value);
6339 } else {
6340 isl_int_set_si(bmap->ineq[j][pos], 1);
6341 isl_int_set_si(bmap->ineq[j][0], -value);
6343 bmap = isl_basic_map_simplify(bmap);
6344 return isl_basic_map_finalize(bmap);
6345 error:
6346 isl_basic_map_free(bmap);
6347 return NULL;
6350 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6351 __isl_take isl_basic_map *bmap,
6352 enum isl_dim_type type, unsigned pos, int value)
6354 return basic_map_bound_si(bmap, type, pos, value, 0);
6357 /* Constrain the values of the given dimension to be no greater than "value".
6359 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6360 __isl_take isl_basic_map *bmap,
6361 enum isl_dim_type type, unsigned pos, int value)
6363 return basic_map_bound_si(bmap, type, pos, value, 1);
6366 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6367 enum isl_dim_type type, unsigned pos, int value, int upper)
6369 int i;
6371 map = isl_map_cow(map);
6372 if (isl_map_check_range(map, type, pos, 1) < 0)
6373 return isl_map_free(map);
6374 for (i = 0; i < map->n; ++i) {
6375 map->p[i] = basic_map_bound_si(map->p[i],
6376 type, pos, value, upper);
6377 if (!map->p[i])
6378 goto error;
6380 map = isl_map_unmark_normalized(map);
6381 return map;
6382 error:
6383 isl_map_free(map);
6384 return NULL;
6387 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6388 enum isl_dim_type type, unsigned pos, int value)
6390 return map_bound_si(map, type, pos, value, 0);
6393 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6394 enum isl_dim_type type, unsigned pos, int value)
6396 return map_bound_si(map, type, pos, value, 1);
6399 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6400 enum isl_dim_type type, unsigned pos, int value)
6402 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6403 type, pos, value));
6406 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6407 enum isl_dim_type type, unsigned pos, int value)
6409 return isl_map_upper_bound_si(set, type, pos, value);
6412 /* Bound the given variable of "bmap" from below (or above is "upper"
6413 * is set) to "value".
6415 static __isl_give isl_basic_map *basic_map_bound(
6416 __isl_take isl_basic_map *bmap,
6417 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6419 int j;
6421 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6422 return isl_basic_map_free(bmap);
6423 pos += isl_basic_map_offset(bmap, type);
6424 bmap = isl_basic_map_cow(bmap);
6425 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6426 j = isl_basic_map_alloc_inequality(bmap);
6427 if (j < 0)
6428 goto error;
6429 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6430 if (upper) {
6431 isl_int_set_si(bmap->ineq[j][pos], -1);
6432 isl_int_set(bmap->ineq[j][0], value);
6433 } else {
6434 isl_int_set_si(bmap->ineq[j][pos], 1);
6435 isl_int_neg(bmap->ineq[j][0], value);
6437 bmap = isl_basic_map_simplify(bmap);
6438 return isl_basic_map_finalize(bmap);
6439 error:
6440 isl_basic_map_free(bmap);
6441 return NULL;
6444 /* Bound the given variable of "map" from below (or above is "upper"
6445 * is set) to "value".
6447 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6448 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6450 int i;
6452 map = isl_map_cow(map);
6453 if (isl_map_check_range(map, type, pos, 1) < 0)
6454 return isl_map_free(map);
6455 for (i = map->n - 1; i >= 0; --i) {
6456 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6457 map = remove_if_empty(map, i);
6458 if (!map)
6459 return NULL;
6461 map = isl_map_unmark_normalized(map);
6462 return map;
6465 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6466 enum isl_dim_type type, unsigned pos, isl_int value)
6468 return map_bound(map, type, pos, value, 0);
6471 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6472 enum isl_dim_type type, unsigned pos, isl_int value)
6474 return map_bound(map, type, pos, value, 1);
6477 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6478 enum isl_dim_type type, unsigned pos, isl_int value)
6480 return isl_map_lower_bound(set, type, pos, value);
6483 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6484 enum isl_dim_type type, unsigned pos, isl_int value)
6486 return isl_map_upper_bound(set, type, pos, value);
6489 /* Force the values of the variable at position "pos" of type "type" of "set"
6490 * to be no smaller than "value".
6492 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6493 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6495 if (!value)
6496 goto error;
6497 if (!isl_val_is_int(value))
6498 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6499 "expecting integer value", goto error);
6500 set = isl_set_lower_bound(set, type, pos, value->n);
6501 isl_val_free(value);
6502 return set;
6503 error:
6504 isl_val_free(value);
6505 isl_set_free(set);
6506 return NULL;
6509 /* Force the values of the variable at position "pos" of type "type" of "set"
6510 * to be no greater than "value".
6512 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6513 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6515 if (!value)
6516 goto error;
6517 if (!isl_val_is_int(value))
6518 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6519 "expecting integer value", goto error);
6520 set = isl_set_upper_bound(set, type, pos, value->n);
6521 isl_val_free(value);
6522 return set;
6523 error:
6524 isl_val_free(value);
6525 isl_set_free(set);
6526 return NULL;
6529 /* Bound the given variable of "bset" from below (or above is "upper"
6530 * is set) to "value".
6532 static __isl_give isl_basic_set *isl_basic_set_bound(
6533 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6534 isl_int value, int upper)
6536 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
6537 type, pos, value, upper));
6540 /* Bound the given variable of "bset" from below (or above is "upper"
6541 * is set) to "value".
6543 static __isl_give isl_basic_set *isl_basic_set_bound_val(
6544 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6545 __isl_take isl_val *value, int upper)
6547 if (!value)
6548 goto error;
6549 if (!isl_val_is_int(value))
6550 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
6551 "expecting integer value", goto error);
6552 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
6553 isl_val_free(value);
6554 return bset;
6555 error:
6556 isl_val_free(value);
6557 isl_basic_set_free(bset);
6558 return NULL;
6561 /* Bound the given variable of "bset" from below to "value".
6563 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
6564 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6565 __isl_take isl_val *value)
6567 return isl_basic_set_bound_val(bset, type, pos, value, 0);
6570 /* Bound the given variable of "bset" from above to "value".
6572 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
6573 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6574 __isl_take isl_val *value)
6576 return isl_basic_set_bound_val(bset, type, pos, value, 1);
6579 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
6581 int i;
6583 map = isl_map_cow(map);
6584 if (!map)
6585 return NULL;
6587 map->dim = isl_space_reverse(map->dim);
6588 if (!map->dim)
6589 goto error;
6590 for (i = 0; i < map->n; ++i) {
6591 map->p[i] = isl_basic_map_reverse(map->p[i]);
6592 if (!map->p[i])
6593 goto error;
6595 map = isl_map_unmark_normalized(map);
6596 return map;
6597 error:
6598 isl_map_free(map);
6599 return NULL;
6602 #undef TYPE
6603 #define TYPE isl_pw_multi_aff
6604 #undef SUFFIX
6605 #define SUFFIX _pw_multi_aff
6606 #undef EMPTY
6607 #define EMPTY isl_pw_multi_aff_empty
6608 #undef ADD
6609 #define ADD isl_pw_multi_aff_union_add
6610 #include "isl_map_lexopt_templ.c"
6612 /* Given a map "map", compute the lexicographically minimal
6613 * (or maximal) image element for each domain element in dom,
6614 * in the form of an isl_pw_multi_aff.
6615 * If "empty" is not NULL, then set *empty to those elements in dom that
6616 * do not have an image element.
6617 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6618 * should be computed over the domain of "map". "empty" is also NULL
6619 * in this case.
6621 * We first compute the lexicographically minimal or maximal element
6622 * in the first basic map. This results in a partial solution "res"
6623 * and a subset "todo" of dom that still need to be handled.
6624 * We then consider each of the remaining maps in "map" and successively
6625 * update both "res" and "todo".
6626 * If "empty" is NULL, then the todo sets are not needed and therefore
6627 * also not computed.
6629 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6630 __isl_take isl_map *map, __isl_take isl_set *dom,
6631 __isl_give isl_set **empty, unsigned flags)
6633 int i;
6634 int full;
6635 isl_pw_multi_aff *res;
6636 isl_set *todo;
6638 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6639 if (!map || (!full && !dom))
6640 goto error;
6642 if (isl_map_plain_is_empty(map)) {
6643 if (empty)
6644 *empty = dom;
6645 else
6646 isl_set_free(dom);
6647 return isl_pw_multi_aff_from_map(map);
6650 res = basic_map_partial_lexopt_pw_multi_aff(
6651 isl_basic_map_copy(map->p[0]),
6652 isl_set_copy(dom), empty, flags);
6654 if (empty)
6655 todo = *empty;
6656 for (i = 1; i < map->n; ++i) {
6657 isl_pw_multi_aff *res_i;
6659 res_i = basic_map_partial_lexopt_pw_multi_aff(
6660 isl_basic_map_copy(map->p[i]),
6661 isl_set_copy(dom), empty, flags);
6663 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6664 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6665 else
6666 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6668 if (empty)
6669 todo = isl_set_intersect(todo, *empty);
6672 isl_set_free(dom);
6673 isl_map_free(map);
6675 if (empty)
6676 *empty = todo;
6678 return res;
6679 error:
6680 if (empty)
6681 *empty = NULL;
6682 isl_set_free(dom);
6683 isl_map_free(map);
6684 return NULL;
6687 #undef TYPE
6688 #define TYPE isl_map
6689 #undef SUFFIX
6690 #define SUFFIX
6691 #undef EMPTY
6692 #define EMPTY isl_map_empty
6693 #undef ADD
6694 #define ADD isl_map_union_disjoint
6695 #include "isl_map_lexopt_templ.c"
6697 /* Given a map "map", compute the lexicographically minimal
6698 * (or maximal) image element for each domain element in "dom",
6699 * in the form of an isl_map.
6700 * If "empty" is not NULL, then set *empty to those elements in "dom" that
6701 * do not have an image element.
6702 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6703 * should be computed over the domain of "map". "empty" is also NULL
6704 * in this case.
6706 * If the input consists of more than one disjunct, then first
6707 * compute the desired result in the form of an isl_pw_multi_aff and
6708 * then convert that into an isl_map.
6710 * This function used to have an explicit implementation in terms
6711 * of isl_maps, but it would continually intersect the domains of
6712 * partial results with the complement of the domain of the next
6713 * partial solution, potentially leading to an explosion in the number
6714 * of disjuncts if there are several disjuncts in the input.
6715 * An even earlier implementation of this function would look for
6716 * better results in the domain of the partial result and for extra
6717 * results in the complement of this domain, which would lead to
6718 * even more splintering.
6720 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6721 __isl_take isl_map *map, __isl_take isl_set *dom,
6722 __isl_give isl_set **empty, unsigned flags)
6724 int full;
6725 struct isl_map *res;
6726 isl_pw_multi_aff *pma;
6728 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6729 if (!map || (!full && !dom))
6730 goto error;
6732 if (isl_map_plain_is_empty(map)) {
6733 if (empty)
6734 *empty = dom;
6735 else
6736 isl_set_free(dom);
6737 return map;
6740 if (map->n == 1) {
6741 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6742 dom, empty, flags);
6743 isl_map_free(map);
6744 return res;
6747 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6748 flags);
6749 return isl_map_from_pw_multi_aff(pma);
6750 error:
6751 if (empty)
6752 *empty = NULL;
6753 isl_set_free(dom);
6754 isl_map_free(map);
6755 return NULL;
6758 __isl_give isl_map *isl_map_partial_lexmax(
6759 __isl_take isl_map *map, __isl_take isl_set *dom,
6760 __isl_give isl_set **empty)
6762 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6765 __isl_give isl_map *isl_map_partial_lexmin(
6766 __isl_take isl_map *map, __isl_take isl_set *dom,
6767 __isl_give isl_set **empty)
6769 return isl_map_partial_lexopt(map, dom, empty, 0);
6772 __isl_give isl_set *isl_set_partial_lexmin(
6773 __isl_take isl_set *set, __isl_take isl_set *dom,
6774 __isl_give isl_set **empty)
6776 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6777 dom, empty));
6780 __isl_give isl_set *isl_set_partial_lexmax(
6781 __isl_take isl_set *set, __isl_take isl_set *dom,
6782 __isl_give isl_set **empty)
6784 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6785 dom, empty));
6788 /* Compute the lexicographic minimum (or maximum if "flags" includes
6789 * ISL_OPT_MAX) of "bset" over its parametric domain.
6791 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6792 unsigned flags)
6794 return isl_basic_map_lexopt(bset, flags);
6797 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6799 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6802 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6804 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6807 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6809 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6812 /* Compute the lexicographic minimum of "bset" over its parametric domain
6813 * for the purpose of quantifier elimination.
6814 * That is, find an explicit representation for all the existentially
6815 * quantified variables in "bset" by computing their lexicographic
6816 * minimum.
6818 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6819 __isl_take isl_basic_set *bset)
6821 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6824 /* Given a basic map with one output dimension, compute the minimum or
6825 * maximum of that dimension as an isl_pw_aff.
6827 * Compute the optimum as a lexicographic optimum over the single
6828 * output dimension and extract the single isl_pw_aff from the result.
6830 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6831 int max)
6833 isl_pw_multi_aff *pma;
6834 isl_pw_aff *pwaff;
6836 bmap = isl_basic_map_copy(bmap);
6837 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
6838 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
6839 isl_pw_multi_aff_free(pma);
6841 return pwaff;
6844 /* Compute the minimum or maximum of the given output dimension
6845 * as a function of the parameters and the input dimensions,
6846 * but independently of the other output dimensions.
6848 * We first project out the other output dimension and then compute
6849 * the "lexicographic" maximum in each basic map, combining the results
6850 * using isl_pw_aff_union_max.
6852 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6853 int max)
6855 int i;
6856 isl_pw_aff *pwaff;
6857 unsigned n_out;
6859 n_out = isl_map_dim(map, isl_dim_out);
6860 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6861 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6862 if (!map)
6863 return NULL;
6865 if (map->n == 0) {
6866 isl_space *space = isl_map_get_space(map);
6867 isl_map_free(map);
6868 return isl_pw_aff_empty(space);
6871 pwaff = basic_map_dim_opt(map->p[0], max);
6872 for (i = 1; i < map->n; ++i) {
6873 isl_pw_aff *pwaff_i;
6875 pwaff_i = basic_map_dim_opt(map->p[i], max);
6876 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6879 isl_map_free(map);
6881 return pwaff;
6884 /* Compute the minimum of the given output dimension as a function of the
6885 * parameters and input dimensions, but independently of
6886 * the other output dimensions.
6888 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
6890 return map_dim_opt(map, pos, 0);
6893 /* Compute the maximum of the given output dimension as a function of the
6894 * parameters and input dimensions, but independently of
6895 * the other output dimensions.
6897 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6899 return map_dim_opt(map, pos, 1);
6902 /* Compute the minimum or maximum of the given set dimension
6903 * as a function of the parameters,
6904 * but independently of the other set dimensions.
6906 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
6907 int max)
6909 return map_dim_opt(set, pos, max);
6912 /* Compute the maximum of the given set dimension as a function of the
6913 * parameters, but independently of the other set dimensions.
6915 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
6917 return set_dim_opt(set, pos, 1);
6920 /* Compute the minimum of the given set dimension as a function of the
6921 * parameters, but independently of the other set dimensions.
6923 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
6925 return set_dim_opt(set, pos, 0);
6928 /* Apply a preimage specified by "mat" on the parameters of "bset".
6929 * bset is assumed to have only parameters and divs.
6931 static __isl_give isl_basic_set *basic_set_parameter_preimage(
6932 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
6934 unsigned nparam;
6936 if (!bset || !mat)
6937 goto error;
6939 bset->dim = isl_space_cow(bset->dim);
6940 if (!bset->dim)
6941 goto error;
6943 nparam = isl_basic_set_dim(bset, isl_dim_param);
6945 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
6947 bset->dim->nparam = 0;
6948 bset->dim->n_out = nparam;
6949 bset = isl_basic_set_preimage(bset, mat);
6950 if (bset) {
6951 bset->dim->nparam = bset->dim->n_out;
6952 bset->dim->n_out = 0;
6954 return bset;
6955 error:
6956 isl_mat_free(mat);
6957 isl_basic_set_free(bset);
6958 return NULL;
6961 /* Apply a preimage specified by "mat" on the parameters of "set".
6962 * set is assumed to have only parameters and divs.
6964 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
6965 __isl_take isl_mat *mat)
6967 isl_space *space;
6968 unsigned nparam;
6970 if (!set || !mat)
6971 goto error;
6973 nparam = isl_set_dim(set, isl_dim_param);
6975 if (mat->n_row != 1 + nparam)
6976 isl_die(isl_set_get_ctx(set), isl_error_internal,
6977 "unexpected number of rows", goto error);
6979 space = isl_set_get_space(set);
6980 space = isl_space_move_dims(space, isl_dim_set, 0,
6981 isl_dim_param, 0, nparam);
6982 set = isl_set_reset_space(set, space);
6983 set = isl_set_preimage(set, mat);
6984 nparam = isl_set_dim(set, isl_dim_out);
6985 space = isl_set_get_space(set);
6986 space = isl_space_move_dims(space, isl_dim_param, 0,
6987 isl_dim_out, 0, nparam);
6988 set = isl_set_reset_space(set, space);
6989 return set;
6990 error:
6991 isl_mat_free(mat);
6992 isl_set_free(set);
6993 return NULL;
6996 /* Intersect the basic set "bset" with the affine space specified by the
6997 * equalities in "eq".
6999 static __isl_give isl_basic_set *basic_set_append_equalities(
7000 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7002 int i, k;
7003 unsigned len;
7005 if (!bset || !eq)
7006 goto error;
7008 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
7009 eq->n_row, 0);
7010 if (!bset)
7011 goto error;
7013 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
7014 for (i = 0; i < eq->n_row; ++i) {
7015 k = isl_basic_set_alloc_equality(bset);
7016 if (k < 0)
7017 goto error;
7018 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7019 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7021 isl_mat_free(eq);
7023 bset = isl_basic_set_gauss(bset, NULL);
7024 bset = isl_basic_set_finalize(bset);
7026 return bset;
7027 error:
7028 isl_mat_free(eq);
7029 isl_basic_set_free(bset);
7030 return NULL;
7033 /* Intersect the set "set" with the affine space specified by the
7034 * equalities in "eq".
7036 static struct isl_set *set_append_equalities(struct isl_set *set,
7037 struct isl_mat *eq)
7039 int i;
7041 if (!set || !eq)
7042 goto error;
7044 for (i = 0; i < set->n; ++i) {
7045 set->p[i] = basic_set_append_equalities(set->p[i],
7046 isl_mat_copy(eq));
7047 if (!set->p[i])
7048 goto error;
7050 isl_mat_free(eq);
7051 return set;
7052 error:
7053 isl_mat_free(eq);
7054 isl_set_free(set);
7055 return NULL;
7058 /* Given a basic set "bset" that only involves parameters and existentially
7059 * quantified variables, return the index of the first equality
7060 * that only involves parameters. If there is no such equality then
7061 * return bset->n_eq.
7063 * This function assumes that isl_basic_set_gauss has been called on "bset".
7065 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7067 int i, j;
7068 unsigned nparam, n_div;
7070 if (!bset)
7071 return -1;
7073 nparam = isl_basic_set_dim(bset, isl_dim_param);
7074 n_div = isl_basic_set_dim(bset, isl_dim_div);
7076 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7077 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7078 ++i;
7081 return i;
7084 /* Compute an explicit representation for the existentially quantified
7085 * variables in "bset" by computing the "minimal value" of the set
7086 * variables. Since there are no set variables, the computation of
7087 * the minimal value essentially computes an explicit representation
7088 * of the non-empty part(s) of "bset".
7090 * The input only involves parameters and existentially quantified variables.
7091 * All equalities among parameters have been removed.
7093 * Since the existentially quantified variables in the result are in general
7094 * going to be different from those in the input, we first replace
7095 * them by the minimal number of variables based on their equalities.
7096 * This should simplify the parametric integer programming.
7098 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7100 isl_morph *morph1, *morph2;
7101 isl_set *set;
7102 unsigned n;
7104 if (!bset)
7105 return NULL;
7106 if (bset->n_eq == 0)
7107 return isl_basic_set_lexmin_compute_divs(bset);
7109 morph1 = isl_basic_set_parameter_compression(bset);
7110 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7111 bset = isl_basic_set_lift(bset);
7112 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7113 bset = isl_morph_basic_set(morph2, bset);
7114 n = isl_basic_set_dim(bset, isl_dim_set);
7115 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7117 set = isl_basic_set_lexmin_compute_divs(bset);
7119 set = isl_morph_set(isl_morph_inverse(morph1), set);
7121 return set;
7124 /* Project the given basic set onto its parameter domain, possibly introducing
7125 * new, explicit, existential variables in the constraints.
7126 * The input has parameters and (possibly implicit) existential variables.
7127 * The output has the same parameters, but only
7128 * explicit existentially quantified variables.
7130 * The actual projection is performed by pip, but pip doesn't seem
7131 * to like equalities very much, so we first remove the equalities
7132 * among the parameters by performing a variable compression on
7133 * the parameters. Afterward, an inverse transformation is performed
7134 * and the equalities among the parameters are inserted back in.
7136 * The variable compression on the parameters may uncover additional
7137 * equalities that were only implicit before. We therefore check
7138 * if there are any new parameter equalities in the result and
7139 * if so recurse. The removal of parameter equalities is required
7140 * for the parameter compression performed by base_compute_divs.
7142 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
7144 int i;
7145 struct isl_mat *eq;
7146 struct isl_mat *T, *T2;
7147 struct isl_set *set;
7148 unsigned nparam;
7150 bset = isl_basic_set_cow(bset);
7151 if (!bset)
7152 return NULL;
7154 if (bset->n_eq == 0)
7155 return base_compute_divs(bset);
7157 bset = isl_basic_set_gauss(bset, NULL);
7158 if (!bset)
7159 return NULL;
7160 if (isl_basic_set_plain_is_empty(bset))
7161 return isl_set_from_basic_set(bset);
7163 i = first_parameter_equality(bset);
7164 if (i == bset->n_eq)
7165 return base_compute_divs(bset);
7167 nparam = isl_basic_set_dim(bset, isl_dim_param);
7168 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7169 0, 1 + nparam);
7170 eq = isl_mat_cow(eq);
7171 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7172 if (T && T->n_col == 0) {
7173 isl_mat_free(T);
7174 isl_mat_free(T2);
7175 isl_mat_free(eq);
7176 bset = isl_basic_set_set_to_empty(bset);
7177 return isl_set_from_basic_set(bset);
7179 bset = basic_set_parameter_preimage(bset, T);
7181 i = first_parameter_equality(bset);
7182 if (!bset)
7183 set = NULL;
7184 else if (i == bset->n_eq)
7185 set = base_compute_divs(bset);
7186 else
7187 set = parameter_compute_divs(bset);
7188 set = set_parameter_preimage(set, T2);
7189 set = set_append_equalities(set, eq);
7190 return set;
7193 /* Insert the divs from "ls" before those of "bmap".
7195 * The number of columns is not changed, which means that the last
7196 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7197 * The caller is responsible for removing the same number of dimensions
7198 * from the space of "bmap".
7200 static __isl_give isl_basic_map *insert_divs_from_local_space(
7201 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7203 int i;
7204 int n_div;
7205 int old_n_div;
7207 n_div = isl_local_space_dim(ls, isl_dim_div);
7208 if (n_div == 0)
7209 return bmap;
7211 old_n_div = bmap->n_div;
7212 bmap = insert_div_rows(bmap, n_div);
7213 if (!bmap)
7214 return NULL;
7216 for (i = 0; i < n_div; ++i) {
7217 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7218 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7221 return bmap;
7224 /* Replace the space of "bmap" by the space and divs of "ls".
7226 * If "ls" has any divs, then we simplify the result since we may
7227 * have discovered some additional equalities that could simplify
7228 * the div expressions.
7230 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7231 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7233 int n_div;
7235 bmap = isl_basic_map_cow(bmap);
7236 if (!bmap || !ls)
7237 goto error;
7239 n_div = isl_local_space_dim(ls, isl_dim_div);
7240 bmap = insert_divs_from_local_space(bmap, ls);
7241 if (!bmap)
7242 goto error;
7244 isl_space_free(bmap->dim);
7245 bmap->dim = isl_local_space_get_space(ls);
7246 if (!bmap->dim)
7247 goto error;
7249 isl_local_space_free(ls);
7250 if (n_div > 0)
7251 bmap = isl_basic_map_simplify(bmap);
7252 bmap = isl_basic_map_finalize(bmap);
7253 return bmap;
7254 error:
7255 isl_basic_map_free(bmap);
7256 isl_local_space_free(ls);
7257 return NULL;
7260 /* Replace the space of "map" by the space and divs of "ls".
7262 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7263 __isl_take isl_local_space *ls)
7265 int i;
7267 map = isl_map_cow(map);
7268 if (!map || !ls)
7269 goto error;
7271 for (i = 0; i < map->n; ++i) {
7272 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7273 isl_local_space_copy(ls));
7274 if (!map->p[i])
7275 goto error;
7277 isl_space_free(map->dim);
7278 map->dim = isl_local_space_get_space(ls);
7279 if (!map->dim)
7280 goto error;
7282 isl_local_space_free(ls);
7283 return map;
7284 error:
7285 isl_local_space_free(ls);
7286 isl_map_free(map);
7287 return NULL;
7290 /* Compute an explicit representation for the existentially
7291 * quantified variables for which do not know any explicit representation yet.
7293 * We first sort the existentially quantified variables so that the
7294 * existentially quantified variables for which we already have an explicit
7295 * representation are placed before those for which we do not.
7296 * The input dimensions, the output dimensions and the existentially
7297 * quantified variables for which we already have an explicit
7298 * representation are then turned into parameters.
7299 * compute_divs returns a map with the same parameters and
7300 * no input or output dimensions and the dimension specification
7301 * is reset to that of the input, including the existentially quantified
7302 * variables for which we already had an explicit representation.
7304 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7306 struct isl_basic_set *bset;
7307 struct isl_set *set;
7308 struct isl_map *map;
7309 isl_space *space;
7310 isl_local_space *ls;
7311 unsigned nparam;
7312 unsigned n_in;
7313 unsigned n_out;
7314 int n_known;
7315 int i;
7317 bmap = isl_basic_map_sort_divs(bmap);
7318 bmap = isl_basic_map_cow(bmap);
7319 if (!bmap)
7320 return NULL;
7322 n_known = isl_basic_map_first_unknown_div(bmap);
7323 if (n_known < 0)
7324 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7326 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7327 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7328 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7329 space = isl_space_set_alloc(bmap->ctx,
7330 nparam + n_in + n_out + n_known, 0);
7331 if (!space)
7332 goto error;
7334 ls = isl_basic_map_get_local_space(bmap);
7335 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7336 n_known, bmap->n_div - n_known);
7337 if (n_known > 0) {
7338 for (i = n_known; i < bmap->n_div; ++i)
7339 swap_div(bmap, i - n_known, i);
7340 bmap->n_div -= n_known;
7341 bmap->extra -= n_known;
7343 bmap = isl_basic_map_reset_space(bmap, space);
7344 bset = bset_from_bmap(bmap);
7346 set = parameter_compute_divs(bset);
7347 map = set_to_map(set);
7348 map = replace_space_by_local_space(map, ls);
7350 return map;
7351 error:
7352 isl_basic_map_free(bmap);
7353 return NULL;
7356 /* Remove the explicit representation of local variable "div",
7357 * if there is any.
7359 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7360 __isl_take isl_basic_map *bmap, int div)
7362 isl_bool unknown;
7364 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7365 if (unknown < 0)
7366 return isl_basic_map_free(bmap);
7367 if (unknown)
7368 return bmap;
7370 bmap = isl_basic_map_cow(bmap);
7371 if (!bmap)
7372 return NULL;
7373 isl_int_set_si(bmap->div[div][0], 0);
7374 return bmap;
7377 /* Is local variable "div" of "bmap" marked as not having an explicit
7378 * representation?
7379 * Note that even if "div" is not marked in this way and therefore
7380 * has an explicit representation, this representation may still
7381 * depend (indirectly) on other local variables that do not
7382 * have an explicit representation.
7384 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7385 int div)
7387 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7388 return isl_bool_error;
7389 return isl_int_is_zero(bmap->div[div][0]);
7392 /* Return the position of the first local variable that does not
7393 * have an explicit representation.
7394 * Return the total number of local variables if they all have
7395 * an explicit representation.
7396 * Return -1 on error.
7398 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7400 int i;
7402 if (!bmap)
7403 return -1;
7405 for (i = 0; i < bmap->n_div; ++i) {
7406 if (!isl_basic_map_div_is_known(bmap, i))
7407 return i;
7409 return bmap->n_div;
7412 /* Return the position of the first local variable that does not
7413 * have an explicit representation.
7414 * Return the total number of local variables if they all have
7415 * an explicit representation.
7416 * Return -1 on error.
7418 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7420 return isl_basic_map_first_unknown_div(bset);
7423 /* Does "bmap" have an explicit representation for all local variables?
7425 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7427 int first, n;
7429 n = isl_basic_map_dim(bmap, isl_dim_div);
7430 first = isl_basic_map_first_unknown_div(bmap);
7431 if (first < 0)
7432 return isl_bool_error;
7433 return first == n;
7436 /* Do all basic maps in "map" have an explicit representation
7437 * for all local variables?
7439 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7441 int i;
7443 if (!map)
7444 return isl_bool_error;
7446 for (i = 0; i < map->n; ++i) {
7447 int known = isl_basic_map_divs_known(map->p[i]);
7448 if (known <= 0)
7449 return known;
7452 return isl_bool_true;
7455 /* If bmap contains any unknown divs, then compute explicit
7456 * expressions for them. However, this computation may be
7457 * quite expensive, so first try to remove divs that aren't
7458 * strictly needed.
7460 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7462 int known;
7463 struct isl_map *map;
7465 known = isl_basic_map_divs_known(bmap);
7466 if (known < 0)
7467 goto error;
7468 if (known)
7469 return isl_map_from_basic_map(bmap);
7471 bmap = isl_basic_map_drop_redundant_divs(bmap);
7473 known = isl_basic_map_divs_known(bmap);
7474 if (known < 0)
7475 goto error;
7476 if (known)
7477 return isl_map_from_basic_map(bmap);
7479 map = compute_divs(bmap);
7480 return map;
7481 error:
7482 isl_basic_map_free(bmap);
7483 return NULL;
7486 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7488 int i;
7489 int known;
7490 struct isl_map *res;
7492 if (!map)
7493 return NULL;
7494 if (map->n == 0)
7495 return map;
7497 known = isl_map_divs_known(map);
7498 if (known < 0) {
7499 isl_map_free(map);
7500 return NULL;
7502 if (known)
7503 return map;
7505 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7506 for (i = 1 ; i < map->n; ++i) {
7507 struct isl_map *r2;
7508 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7509 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7510 res = isl_map_union_disjoint(res, r2);
7511 else
7512 res = isl_map_union(res, r2);
7514 isl_map_free(map);
7516 return res;
7519 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
7521 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7524 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7526 return set_from_map(isl_map_compute_divs(set_to_map(set)));
7529 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
7531 int i;
7532 struct isl_set *set;
7534 if (!map)
7535 goto error;
7537 map = isl_map_cow(map);
7538 if (!map)
7539 return NULL;
7541 set = set_from_map(map);
7542 set->dim = isl_space_domain(set->dim);
7543 if (!set->dim)
7544 goto error;
7545 for (i = 0; i < map->n; ++i) {
7546 set->p[i] = isl_basic_map_domain(map->p[i]);
7547 if (!set->p[i])
7548 goto error;
7550 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7551 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7552 return set;
7553 error:
7554 isl_map_free(map);
7555 return NULL;
7558 /* Return the union of "map1" and "map2", where we assume for now that
7559 * "map1" and "map2" are disjoint. Note that the basic maps inside
7560 * "map1" or "map2" may not be disjoint from each other.
7561 * Also note that this function is also called from isl_map_union,
7562 * which takes care of handling the situation where "map1" and "map2"
7563 * may not be disjoint.
7565 * If one of the inputs is empty, we can simply return the other input.
7566 * Similarly, if one of the inputs is universal, then it is equal to the union.
7568 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7569 __isl_take isl_map *map2)
7571 int i;
7572 unsigned flags = 0;
7573 struct isl_map *map = NULL;
7574 int is_universe;
7576 if (!map1 || !map2)
7577 goto error;
7579 if (!isl_space_is_equal(map1->dim, map2->dim))
7580 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7581 "spaces don't match", goto error);
7583 if (map1->n == 0) {
7584 isl_map_free(map1);
7585 return map2;
7587 if (map2->n == 0) {
7588 isl_map_free(map2);
7589 return map1;
7592 is_universe = isl_map_plain_is_universe(map1);
7593 if (is_universe < 0)
7594 goto error;
7595 if (is_universe) {
7596 isl_map_free(map2);
7597 return map1;
7600 is_universe = isl_map_plain_is_universe(map2);
7601 if (is_universe < 0)
7602 goto error;
7603 if (is_universe) {
7604 isl_map_free(map1);
7605 return map2;
7608 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7609 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7610 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7612 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7613 map1->n + map2->n, flags);
7614 if (!map)
7615 goto error;
7616 for (i = 0; i < map1->n; ++i) {
7617 map = isl_map_add_basic_map(map,
7618 isl_basic_map_copy(map1->p[i]));
7619 if (!map)
7620 goto error;
7622 for (i = 0; i < map2->n; ++i) {
7623 map = isl_map_add_basic_map(map,
7624 isl_basic_map_copy(map2->p[i]));
7625 if (!map)
7626 goto error;
7628 isl_map_free(map1);
7629 isl_map_free(map2);
7630 return map;
7631 error:
7632 isl_map_free(map);
7633 isl_map_free(map1);
7634 isl_map_free(map2);
7635 return NULL;
7638 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7639 * guaranteed to be disjoint by the caller.
7641 * Note that this functions is called from within isl_map_make_disjoint,
7642 * so we have to be careful not to touch the constraints of the inputs
7643 * in any way.
7645 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7646 __isl_take isl_map *map2)
7648 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7651 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7652 * not be disjoint. The parameters are assumed to have been aligned.
7654 * We currently simply call map_union_disjoint, the internal operation
7655 * of which does not really depend on the inputs being disjoint.
7656 * If the result contains more than one basic map, then we clear
7657 * the disjoint flag since the result may contain basic maps from
7658 * both inputs and these are not guaranteed to be disjoint.
7660 * As a special case, if "map1" and "map2" are obviously equal,
7661 * then we simply return "map1".
7663 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7664 __isl_take isl_map *map2)
7666 int equal;
7668 if (!map1 || !map2)
7669 goto error;
7671 equal = isl_map_plain_is_equal(map1, map2);
7672 if (equal < 0)
7673 goto error;
7674 if (equal) {
7675 isl_map_free(map2);
7676 return map1;
7679 map1 = map_union_disjoint(map1, map2);
7680 if (!map1)
7681 return NULL;
7682 if (map1->n > 1)
7683 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7684 return map1;
7685 error:
7686 isl_map_free(map1);
7687 isl_map_free(map2);
7688 return NULL;
7691 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7692 * not be disjoint.
7694 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7695 __isl_take isl_map *map2)
7697 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7700 __isl_give isl_set *isl_set_union_disjoint(
7701 __isl_take isl_set *set1, __isl_take isl_set *set2)
7703 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7704 set_to_map(set2)));
7707 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7709 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7712 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7713 * the results.
7715 * "map" and "set" are assumed to be compatible and non-NULL.
7717 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7718 __isl_take isl_set *set,
7719 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7720 __isl_take isl_basic_set *bset))
7722 unsigned flags = 0;
7723 struct isl_map *result;
7724 int i, j;
7726 if (isl_set_plain_is_universe(set)) {
7727 isl_set_free(set);
7728 return map;
7731 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7732 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7733 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7735 result = isl_map_alloc_space(isl_space_copy(map->dim),
7736 map->n * set->n, flags);
7737 for (i = 0; result && i < map->n; ++i)
7738 for (j = 0; j < set->n; ++j) {
7739 result = isl_map_add_basic_map(result,
7740 fn(isl_basic_map_copy(map->p[i]),
7741 isl_basic_set_copy(set->p[j])));
7742 if (!result)
7743 break;
7746 isl_map_free(map);
7747 isl_set_free(set);
7748 return result;
7751 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7752 __isl_take isl_set *set)
7754 isl_bool ok;
7756 ok = isl_map_compatible_range(map, set);
7757 if (ok < 0)
7758 goto error;
7759 if (!ok)
7760 isl_die(set->ctx, isl_error_invalid,
7761 "incompatible spaces", goto error);
7763 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7764 error:
7765 isl_map_free(map);
7766 isl_set_free(set);
7767 return NULL;
7770 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7771 __isl_take isl_set *set)
7773 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7776 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7777 __isl_take isl_set *set)
7779 isl_bool ok;
7781 ok = isl_map_compatible_domain(map, set);
7782 if (ok < 0)
7783 goto error;
7784 if (!ok)
7785 isl_die(set->ctx, isl_error_invalid,
7786 "incompatible spaces", goto error);
7788 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7789 error:
7790 isl_map_free(map);
7791 isl_set_free(set);
7792 return NULL;
7795 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7796 __isl_take isl_set *set)
7798 return isl_map_align_params_map_map_and(map, set,
7799 &map_intersect_domain);
7802 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7803 * in the space B -> C, return the intersection.
7804 * The parameters are assumed to have been aligned.
7806 * The map "factor" is first extended to a map living in the space
7807 * [A -> B] -> C and then a regular intersection is computed.
7809 static __isl_give isl_map *map_intersect_domain_factor_range(
7810 __isl_take isl_map *map, __isl_take isl_map *factor)
7812 isl_space *space;
7813 isl_map *ext_factor;
7815 space = isl_space_domain_factor_domain(isl_map_get_space(map));
7816 ext_factor = isl_map_universe(space);
7817 ext_factor = isl_map_domain_product(ext_factor, factor);
7818 return map_intersect(map, ext_factor);
7821 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7822 * in the space B -> C, return the intersection.
7824 __isl_give isl_map *isl_map_intersect_domain_factor_range(
7825 __isl_take isl_map *map, __isl_take isl_map *factor)
7827 return isl_map_align_params_map_map_and(map, factor,
7828 &map_intersect_domain_factor_range);
7831 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7832 * in the space A -> C, return the intersection.
7834 * The map "factor" is first extended to a map living in the space
7835 * A -> [B -> C] and then a regular intersection is computed.
7837 static __isl_give isl_map *map_intersect_range_factor_range(
7838 __isl_take isl_map *map, __isl_take isl_map *factor)
7840 isl_space *space;
7841 isl_map *ext_factor;
7843 space = isl_space_range_factor_domain(isl_map_get_space(map));
7844 ext_factor = isl_map_universe(space);
7845 ext_factor = isl_map_range_product(ext_factor, factor);
7846 return isl_map_intersect(map, ext_factor);
7849 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7850 * in the space A -> C, return the intersection.
7852 __isl_give isl_map *isl_map_intersect_range_factor_range(
7853 __isl_take isl_map *map, __isl_take isl_map *factor)
7855 return isl_map_align_params_map_map_and(map, factor,
7856 &map_intersect_range_factor_range);
7859 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7860 __isl_take isl_map *map2)
7862 if (!map1 || !map2)
7863 goto error;
7864 map1 = isl_map_reverse(map1);
7865 map1 = isl_map_apply_range(map1, map2);
7866 return isl_map_reverse(map1);
7867 error:
7868 isl_map_free(map1);
7869 isl_map_free(map2);
7870 return NULL;
7873 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7874 __isl_take isl_map *map2)
7876 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7879 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7880 __isl_take isl_map *map2)
7882 isl_space *space;
7883 struct isl_map *result;
7884 int i, j;
7886 if (!map1 || !map2)
7887 goto error;
7889 space = isl_space_join(isl_space_copy(map1->dim),
7890 isl_space_copy(map2->dim));
7892 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
7893 if (!result)
7894 goto error;
7895 for (i = 0; i < map1->n; ++i)
7896 for (j = 0; j < map2->n; ++j) {
7897 result = isl_map_add_basic_map(result,
7898 isl_basic_map_apply_range(
7899 isl_basic_map_copy(map1->p[i]),
7900 isl_basic_map_copy(map2->p[j])));
7901 if (!result)
7902 goto error;
7904 isl_map_free(map1);
7905 isl_map_free(map2);
7906 if (result && result->n <= 1)
7907 ISL_F_SET(result, ISL_MAP_DISJOINT);
7908 return result;
7909 error:
7910 isl_map_free(map1);
7911 isl_map_free(map2);
7912 return NULL;
7915 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
7916 __isl_take isl_map *map2)
7918 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
7922 * returns range - domain
7924 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
7926 isl_space *target_space;
7927 struct isl_basic_set *bset;
7928 unsigned dim;
7929 unsigned nparam;
7930 int i;
7932 if (!bmap)
7933 goto error;
7934 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7935 bmap->dim, isl_dim_out),
7936 goto error);
7937 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
7938 dim = isl_basic_map_dim(bmap, isl_dim_in);
7939 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7940 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
7941 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
7942 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
7943 for (i = 0; i < dim; ++i) {
7944 int j = isl_basic_map_alloc_equality(bmap);
7945 if (j < 0) {
7946 bmap = isl_basic_map_free(bmap);
7947 break;
7949 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7950 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7951 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
7952 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
7954 bset = isl_basic_map_domain(bmap);
7955 bset = isl_basic_set_reset_space(bset, target_space);
7956 return bset;
7957 error:
7958 isl_basic_map_free(bmap);
7959 return NULL;
7962 /* Check that domain and range of "map" are the same.
7964 isl_stat isl_map_check_equal_tuples(__isl_keep isl_map *map)
7966 isl_space *space;
7967 isl_bool equal;
7969 space = isl_map_peek_space(map);
7970 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
7971 if (equal < 0)
7972 return isl_stat_error;
7973 if (!equal)
7974 isl_die(isl_map_get_ctx(map), isl_error_invalid,
7975 "domain and range don't match", return isl_stat_error);
7976 return isl_stat_ok;
7980 * returns range - domain
7982 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
7984 int i;
7985 isl_space *dim;
7986 struct isl_set *result;
7988 if (!map)
7989 return NULL;
7991 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
7992 map->dim, isl_dim_out),
7993 goto error);
7994 dim = isl_map_get_space(map);
7995 dim = isl_space_domain(dim);
7996 result = isl_set_alloc_space(dim, map->n, 0);
7997 if (!result)
7998 goto error;
7999 for (i = 0; i < map->n; ++i)
8000 result = isl_set_add_basic_set(result,
8001 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8002 isl_map_free(map);
8003 return result;
8004 error:
8005 isl_map_free(map);
8006 return NULL;
8010 * returns [domain -> range] -> range - domain
8012 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8013 __isl_take isl_basic_map *bmap)
8015 int i, k;
8016 isl_space *space;
8017 isl_basic_map *domain;
8018 int nparam, n;
8019 unsigned total;
8021 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8022 bmap->dim, isl_dim_out))
8023 isl_die(bmap->ctx, isl_error_invalid,
8024 "domain and range don't match", goto error);
8026 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8027 n = isl_basic_map_dim(bmap, isl_dim_in);
8029 space = isl_basic_map_get_space(bmap);
8030 space = isl_space_from_range(isl_space_domain(space));
8031 domain = isl_basic_map_universe(space);
8033 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8034 bmap = isl_basic_map_apply_range(bmap, domain);
8035 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8037 total = isl_basic_map_total_dim(bmap);
8039 for (i = 0; i < n; ++i) {
8040 k = isl_basic_map_alloc_equality(bmap);
8041 if (k < 0)
8042 goto error;
8043 isl_seq_clr(bmap->eq[k], 1 + total);
8044 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8045 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8046 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8049 bmap = isl_basic_map_gauss(bmap, NULL);
8050 return isl_basic_map_finalize(bmap);
8051 error:
8052 isl_basic_map_free(bmap);
8053 return NULL;
8057 * returns [domain -> range] -> range - domain
8059 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8061 int i;
8062 isl_space *domain_space;
8064 if (isl_map_check_equal_tuples(map) < 0)
8065 return isl_map_free(map);
8067 map = isl_map_cow(map);
8068 if (!map)
8069 return NULL;
8071 domain_space = isl_space_domain(isl_map_get_space(map));
8072 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
8073 map->dim = isl_space_join(map->dim, isl_space_from_range(domain_space));
8074 if (!map->dim)
8075 goto error;
8076 for (i = 0; i < map->n; ++i) {
8077 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
8078 if (!map->p[i])
8079 goto error;
8081 map = isl_map_unmark_normalized(map);
8082 return map;
8083 error:
8084 isl_map_free(map);
8085 return NULL;
8088 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8090 unsigned n_in, n_out;
8092 if (!space)
8093 return NULL;
8094 n_in = isl_space_dim(space, isl_dim_in);
8095 n_out = isl_space_dim(space, isl_dim_out);
8096 if (n_in != n_out)
8097 isl_die(space->ctx, isl_error_invalid,
8098 "number of input and output dimensions needs to be "
8099 "the same", goto error);
8100 return isl_basic_map_equal(space, n_in);
8101 error:
8102 isl_space_free(space);
8103 return NULL;
8106 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
8108 return isl_map_from_basic_map(isl_basic_map_identity(dim));
8111 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8113 isl_space *dim = isl_set_get_space(set);
8114 isl_map *id;
8115 id = isl_map_identity(isl_space_map_from_set(dim));
8116 return isl_map_intersect_range(id, set);
8119 /* Construct a basic set with all set dimensions having only non-negative
8120 * values.
8122 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8123 __isl_take isl_space *space)
8125 int i;
8126 unsigned nparam;
8127 unsigned dim;
8128 struct isl_basic_set *bset;
8130 if (!space)
8131 return NULL;
8132 nparam = isl_space_dim(space, isl_dim_param);
8133 dim = isl_space_dim(space, isl_dim_set);
8134 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8135 if (!bset)
8136 return NULL;
8137 for (i = 0; i < dim; ++i) {
8138 int k = isl_basic_set_alloc_inequality(bset);
8139 if (k < 0)
8140 goto error;
8141 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
8142 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8144 return bset;
8145 error:
8146 isl_basic_set_free(bset);
8147 return NULL;
8150 /* Construct the half-space x_pos >= 0.
8152 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8153 int pos)
8155 int k;
8156 isl_basic_set *nonneg;
8158 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8159 k = isl_basic_set_alloc_inequality(nonneg);
8160 if (k < 0)
8161 goto error;
8162 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
8163 isl_int_set_si(nonneg->ineq[k][pos], 1);
8165 return isl_basic_set_finalize(nonneg);
8166 error:
8167 isl_basic_set_free(nonneg);
8168 return NULL;
8171 /* Construct the half-space x_pos <= -1.
8173 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8174 int pos)
8176 int k;
8177 isl_basic_set *neg;
8179 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8180 k = isl_basic_set_alloc_inequality(neg);
8181 if (k < 0)
8182 goto error;
8183 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
8184 isl_int_set_si(neg->ineq[k][0], -1);
8185 isl_int_set_si(neg->ineq[k][pos], -1);
8187 return isl_basic_set_finalize(neg);
8188 error:
8189 isl_basic_set_free(neg);
8190 return NULL;
8193 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8194 enum isl_dim_type type, unsigned first, unsigned n)
8196 int i;
8197 unsigned offset;
8198 isl_basic_set *nonneg;
8199 isl_basic_set *neg;
8201 if (n == 0)
8202 return set;
8204 if (isl_set_check_range(set, type, first, n) < 0)
8205 return isl_set_free(set);
8207 offset = pos(set->dim, type);
8208 for (i = 0; i < n; ++i) {
8209 nonneg = nonneg_halfspace(isl_set_get_space(set),
8210 offset + first + i);
8211 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8213 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8216 return set;
8219 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8220 int len,
8221 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8222 void *user)
8224 isl_set *half;
8226 if (!set)
8227 return isl_stat_error;
8228 if (isl_set_plain_is_empty(set)) {
8229 isl_set_free(set);
8230 return isl_stat_ok;
8232 if (first == len)
8233 return fn(set, signs, user);
8235 signs[first] = 1;
8236 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8237 1 + first));
8238 half = isl_set_intersect(half, isl_set_copy(set));
8239 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8240 goto error;
8242 signs[first] = -1;
8243 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8244 1 + first));
8245 half = isl_set_intersect(half, set);
8246 return foreach_orthant(half, signs, first + 1, len, fn, user);
8247 error:
8248 isl_set_free(set);
8249 return isl_stat_error;
8252 /* Call "fn" on the intersections of "set" with each of the orthants
8253 * (except for obviously empty intersections). The orthant is identified
8254 * by the signs array, with each entry having value 1 or -1 according
8255 * to the sign of the corresponding variable.
8257 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8258 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8259 void *user)
8261 unsigned nparam;
8262 unsigned nvar;
8263 int *signs;
8264 isl_stat r;
8266 if (!set)
8267 return isl_stat_error;
8268 if (isl_set_plain_is_empty(set))
8269 return isl_stat_ok;
8271 nparam = isl_set_dim(set, isl_dim_param);
8272 nvar = isl_set_dim(set, isl_dim_set);
8274 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8276 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8277 fn, user);
8279 free(signs);
8281 return r;
8284 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8286 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8289 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8290 __isl_keep isl_basic_map *bmap2)
8292 isl_bool is_subset;
8293 struct isl_map *map1;
8294 struct isl_map *map2;
8296 if (!bmap1 || !bmap2)
8297 return isl_bool_error;
8299 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8300 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8302 is_subset = isl_map_is_subset(map1, map2);
8304 isl_map_free(map1);
8305 isl_map_free(map2);
8307 return is_subset;
8310 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8311 __isl_keep isl_basic_set *bset2)
8313 return isl_basic_map_is_subset(bset1, bset2);
8316 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8317 __isl_keep isl_basic_map *bmap2)
8319 isl_bool is_subset;
8321 if (!bmap1 || !bmap2)
8322 return isl_bool_error;
8323 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8324 if (is_subset != isl_bool_true)
8325 return is_subset;
8326 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8327 return is_subset;
8330 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8331 __isl_keep isl_basic_set *bset2)
8333 return isl_basic_map_is_equal(
8334 bset_to_bmap(bset1), bset_to_bmap(bset2));
8337 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8339 int i;
8340 int is_empty;
8342 if (!map)
8343 return isl_bool_error;
8344 for (i = 0; i < map->n; ++i) {
8345 is_empty = isl_basic_map_is_empty(map->p[i]);
8346 if (is_empty < 0)
8347 return isl_bool_error;
8348 if (!is_empty)
8349 return isl_bool_false;
8351 return isl_bool_true;
8354 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8356 return map ? map->n == 0 : isl_bool_error;
8359 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8361 return set ? set->n == 0 : isl_bool_error;
8364 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8366 return isl_map_is_empty(set_to_map(set));
8369 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
8370 __isl_keep isl_map *map2)
8372 if (!map1 || !map2)
8373 return isl_bool_error;
8375 return isl_space_is_equal(map1->dim, map2->dim);
8378 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
8379 __isl_keep isl_set *set2)
8381 if (!set1 || !set2)
8382 return isl_bool_error;
8384 return isl_space_is_equal(set1->dim, set2->dim);
8387 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8389 isl_bool is_subset;
8391 if (!map1 || !map2)
8392 return isl_bool_error;
8393 is_subset = isl_map_is_subset(map1, map2);
8394 if (is_subset != isl_bool_true)
8395 return is_subset;
8396 is_subset = isl_map_is_subset(map2, map1);
8397 return is_subset;
8400 /* Is "map1" equal to "map2"?
8402 * First check if they are obviously equal.
8403 * If not, then perform a more detailed analysis.
8405 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8407 isl_bool equal;
8409 equal = isl_map_plain_is_equal(map1, map2);
8410 if (equal < 0 || equal)
8411 return equal;
8412 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8415 isl_bool isl_basic_map_is_strict_subset(
8416 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8418 isl_bool is_subset;
8420 if (!bmap1 || !bmap2)
8421 return isl_bool_error;
8422 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8423 if (is_subset != isl_bool_true)
8424 return is_subset;
8425 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8426 return isl_bool_not(is_subset);
8429 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8430 __isl_keep isl_map *map2)
8432 isl_bool is_subset;
8434 if (!map1 || !map2)
8435 return isl_bool_error;
8436 is_subset = isl_map_is_subset(map1, map2);
8437 if (is_subset != isl_bool_true)
8438 return is_subset;
8439 is_subset = isl_map_is_subset(map2, map1);
8440 return isl_bool_not(is_subset);
8443 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8444 __isl_keep isl_set *set2)
8446 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8449 /* Is "bmap" obviously equal to the universe with the same space?
8451 * That is, does it not have any constraints?
8453 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8455 if (!bmap)
8456 return isl_bool_error;
8457 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8460 /* Is "bset" obviously equal to the universe with the same space?
8462 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8464 return isl_basic_map_plain_is_universe(bset);
8467 /* If "c" does not involve any existentially quantified variables,
8468 * then set *univ to false and abort
8470 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8472 isl_bool *univ = user;
8473 unsigned n;
8475 n = isl_constraint_dim(c, isl_dim_div);
8476 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8477 isl_constraint_free(c);
8478 if (*univ < 0 || !*univ)
8479 return isl_stat_error;
8480 return isl_stat_ok;
8483 /* Is "bmap" equal to the universe with the same space?
8485 * First check if it is obviously equal to the universe.
8486 * If not and if there are any constraints not involving
8487 * existentially quantified variables, then it is certainly
8488 * not equal to the universe.
8489 * Otherwise, check if the universe is a subset of "bmap".
8491 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8493 isl_bool univ;
8494 isl_basic_map *test;
8496 univ = isl_basic_map_plain_is_universe(bmap);
8497 if (univ < 0 || univ)
8498 return univ;
8499 if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8500 return isl_bool_false;
8501 univ = isl_bool_true;
8502 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8503 univ)
8504 return isl_bool_error;
8505 if (univ < 0 || !univ)
8506 return univ;
8507 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8508 univ = isl_basic_map_is_subset(test, bmap);
8509 isl_basic_map_free(test);
8510 return univ;
8513 /* Is "bset" equal to the universe with the same space?
8515 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8517 return isl_basic_map_is_universe(bset);
8520 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8522 int i;
8524 if (!map)
8525 return isl_bool_error;
8527 for (i = 0; i < map->n; ++i) {
8528 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8529 if (r < 0 || r)
8530 return r;
8533 return isl_bool_false;
8536 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8538 return isl_map_plain_is_universe(set_to_map(set));
8541 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8543 struct isl_basic_set *bset = NULL;
8544 struct isl_vec *sample = NULL;
8545 isl_bool empty, non_empty;
8547 if (!bmap)
8548 return isl_bool_error;
8550 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8551 return isl_bool_true;
8553 if (isl_basic_map_plain_is_universe(bmap))
8554 return isl_bool_false;
8556 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8557 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8558 copy = isl_basic_map_remove_redundancies(copy);
8559 empty = isl_basic_map_plain_is_empty(copy);
8560 isl_basic_map_free(copy);
8561 return empty;
8564 non_empty = isl_basic_map_plain_is_non_empty(bmap);
8565 if (non_empty < 0)
8566 return isl_bool_error;
8567 if (non_empty)
8568 return isl_bool_false;
8569 isl_vec_free(bmap->sample);
8570 bmap->sample = NULL;
8571 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8572 if (!bset)
8573 return isl_bool_error;
8574 sample = isl_basic_set_sample_vec(bset);
8575 if (!sample)
8576 return isl_bool_error;
8577 empty = sample->size == 0;
8578 isl_vec_free(bmap->sample);
8579 bmap->sample = sample;
8580 if (empty)
8581 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8583 return empty;
8586 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8588 if (!bmap)
8589 return isl_bool_error;
8590 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8593 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8595 if (!bset)
8596 return isl_bool_error;
8597 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8600 /* Is "bmap" known to be non-empty?
8602 * That is, is the cached sample still valid?
8604 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8606 unsigned total;
8608 if (!bmap)
8609 return isl_bool_error;
8610 if (!bmap->sample)
8611 return isl_bool_false;
8612 total = 1 + isl_basic_map_total_dim(bmap);
8613 if (bmap->sample->size != total)
8614 return isl_bool_false;
8615 return isl_basic_map_contains(bmap, bmap->sample);
8618 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8620 return isl_basic_map_is_empty(bset_to_bmap(bset));
8623 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
8624 __isl_take isl_basic_map *bmap2)
8626 struct isl_map *map;
8627 if (!bmap1 || !bmap2)
8628 goto error;
8630 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8632 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8633 if (!map)
8634 goto error;
8635 map = isl_map_add_basic_map(map, bmap1);
8636 map = isl_map_add_basic_map(map, bmap2);
8637 return map;
8638 error:
8639 isl_basic_map_free(bmap1);
8640 isl_basic_map_free(bmap2);
8641 return NULL;
8644 struct isl_set *isl_basic_set_union(
8645 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8647 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8648 bset_to_bmap(bset2)));
8651 /* Order divs such that any div only depends on previous divs */
8652 __isl_give isl_basic_map *isl_basic_map_order_divs(
8653 __isl_take isl_basic_map *bmap)
8655 int i;
8656 unsigned off;
8658 if (!bmap)
8659 return NULL;
8661 off = isl_space_dim(bmap->dim, isl_dim_all);
8663 for (i = 0; i < bmap->n_div; ++i) {
8664 int pos;
8665 if (isl_int_is_zero(bmap->div[i][0]))
8666 continue;
8667 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8668 bmap->n_div-i);
8669 if (pos == -1)
8670 continue;
8671 if (pos == 0)
8672 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8673 "integer division depends on itself",
8674 return isl_basic_map_free(bmap));
8675 bmap = isl_basic_map_swap_div(bmap, i, i + pos);
8676 if (!bmap)
8677 return NULL;
8678 --i;
8680 return bmap;
8683 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8685 return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8688 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8690 int i;
8692 if (!map)
8693 return 0;
8695 for (i = 0; i < map->n; ++i) {
8696 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8697 if (!map->p[i])
8698 goto error;
8701 return map;
8702 error:
8703 isl_map_free(map);
8704 return NULL;
8707 /* Sort the local variables of "bset".
8709 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8710 __isl_take isl_basic_set *bset)
8712 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8715 /* Apply the expansion computed by isl_merge_divs.
8716 * The expansion itself is given by "exp" while the resulting
8717 * list of divs is given by "div".
8719 * Move the integer divisions of "bmap" into the right position
8720 * according to "exp" and then introduce the additional integer
8721 * divisions, adding div constraints.
8722 * The moving should be done first to avoid moving coefficients
8723 * in the definitions of the extra integer divisions.
8725 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8726 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8728 int i, j;
8729 int n_div;
8731 bmap = isl_basic_map_cow(bmap);
8732 if (!bmap || !div)
8733 goto error;
8735 if (div->n_row < bmap->n_div)
8736 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8737 "not an expansion", goto error);
8739 n_div = bmap->n_div;
8740 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8741 div->n_row - n_div, 0,
8742 2 * (div->n_row - n_div));
8744 for (i = n_div; i < div->n_row; ++i)
8745 if (isl_basic_map_alloc_div(bmap) < 0)
8746 goto error;
8748 for (j = n_div - 1; j >= 0; --j) {
8749 if (exp[j] == j)
8750 break;
8751 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
8752 if (!bmap)
8753 goto error;
8755 j = 0;
8756 for (i = 0; i < div->n_row; ++i) {
8757 if (j < n_div && exp[j] == i) {
8758 j++;
8759 } else {
8760 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8761 if (isl_basic_map_div_is_marked_unknown(bmap, i))
8762 continue;
8763 bmap = isl_basic_map_add_div_constraints(bmap, i);
8764 if (!bmap)
8765 goto error;
8769 isl_mat_free(div);
8770 return bmap;
8771 error:
8772 isl_basic_map_free(bmap);
8773 isl_mat_free(div);
8774 return NULL;
8777 /* Apply the expansion computed by isl_merge_divs.
8778 * The expansion itself is given by "exp" while the resulting
8779 * list of divs is given by "div".
8781 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8782 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8784 return isl_basic_map_expand_divs(bset, div, exp);
8787 /* Look for a div in dst that corresponds to the div "div" in src.
8788 * The divs before "div" in src and dst are assumed to be the same.
8790 * Return the position of the corresponding div in dst
8791 * if there is one. Otherwise, return a position beyond the integer divisions.
8792 * Return -1 on error.
8794 static int find_div(__isl_keep isl_basic_map *dst,
8795 __isl_keep isl_basic_map *src, unsigned div)
8797 int i;
8798 unsigned n_div;
8799 unsigned total;
8801 if (!dst || !src)
8802 return -1;
8804 total = isl_space_dim(src->dim, isl_dim_all);
8805 n_div = isl_basic_map_dim(dst, isl_dim_div);
8806 isl_assert(dst->ctx, div <= n_div, return -1);
8807 for (i = div; i < n_div; ++i)
8808 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8809 isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8810 n_div - div) == -1)
8811 return i;
8812 return n_div;
8815 /* Align the divs of "dst" to those of "src", adding divs from "src"
8816 * if needed. That is, make sure that the first src->n_div divs
8817 * of the result are equal to those of src.
8819 * The result is not finalized as by design it will have redundant
8820 * divs if any divs from "src" were copied.
8822 __isl_give isl_basic_map *isl_basic_map_align_divs(
8823 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8825 int i;
8826 isl_bool known;
8827 int extended;
8828 unsigned total, dst_n_div;
8830 if (!dst || !src)
8831 return isl_basic_map_free(dst);
8833 if (src->n_div == 0)
8834 return dst;
8836 known = isl_basic_map_divs_known(src);
8837 if (known < 0)
8838 return isl_basic_map_free(dst);
8839 if (!known)
8840 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8841 "some src divs are unknown",
8842 return isl_basic_map_free(dst));
8844 src = isl_basic_map_order_divs(isl_basic_map_copy(src));
8845 if (!src)
8846 return isl_basic_map_free(dst);
8848 extended = 0;
8849 total = isl_space_dim(src->dim, isl_dim_all);
8850 dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
8851 for (i = 0; i < src->n_div; ++i) {
8852 int j = find_div(dst, src, i);
8853 if (j < 0)
8854 dst = isl_basic_map_free(dst);
8855 if (j == dst_n_div) {
8856 if (!extended) {
8857 int extra = src->n_div - i;
8858 dst = isl_basic_map_cow(dst);
8859 if (!dst)
8860 goto error;
8861 dst = isl_basic_map_extend_space(dst,
8862 isl_space_copy(dst->dim),
8863 extra, 0, 2 * extra);
8864 extended = 1;
8866 j = isl_basic_map_alloc_div(dst);
8867 if (j < 0)
8868 goto error;
8869 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8870 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8871 dst_n_div++;
8872 dst = isl_basic_map_add_div_constraints(dst, j);
8873 if (!dst)
8874 goto error;
8876 if (j != i)
8877 dst = isl_basic_map_swap_div(dst, i, j);
8878 if (!dst)
8879 goto error;
8881 isl_basic_map_free(src);
8882 return dst;
8883 error:
8884 isl_basic_map_free(src);
8885 isl_basic_map_free(dst);
8886 return NULL;
8889 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
8891 int i;
8893 if (!map)
8894 return NULL;
8895 if (map->n == 0)
8896 return map;
8897 map = isl_map_compute_divs(map);
8898 map = isl_map_cow(map);
8899 if (!map)
8900 return NULL;
8902 for (i = 1; i < map->n; ++i)
8903 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8904 for (i = 1; i < map->n; ++i) {
8905 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8906 if (!map->p[i])
8907 return isl_map_free(map);
8910 map = isl_map_unmark_normalized(map);
8911 return map;
8914 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
8916 return isl_map_align_divs_internal(map);
8919 struct isl_set *isl_set_align_divs(struct isl_set *set)
8921 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
8924 /* Align the divs of the basic maps in "map" to those
8925 * of the basic maps in "list", as well as to the other basic maps in "map".
8926 * The elements in "list" are assumed to have known divs.
8928 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
8929 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
8931 int i, n;
8933 map = isl_map_compute_divs(map);
8934 map = isl_map_cow(map);
8935 if (!map || !list)
8936 return isl_map_free(map);
8937 if (map->n == 0)
8938 return map;
8940 n = isl_basic_map_list_n_basic_map(list);
8941 for (i = 0; i < n; ++i) {
8942 isl_basic_map *bmap;
8944 bmap = isl_basic_map_list_get_basic_map(list, i);
8945 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
8946 isl_basic_map_free(bmap);
8948 if (!map->p[0])
8949 return isl_map_free(map);
8951 return isl_map_align_divs_internal(map);
8954 /* Align the divs of each element of "list" to those of "bmap".
8955 * Both "bmap" and the elements of "list" are assumed to have known divs.
8957 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
8958 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
8960 int i, n;
8962 if (!list || !bmap)
8963 return isl_basic_map_list_free(list);
8965 n = isl_basic_map_list_n_basic_map(list);
8966 for (i = 0; i < n; ++i) {
8967 isl_basic_map *bmap_i;
8969 bmap_i = isl_basic_map_list_get_basic_map(list, i);
8970 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
8971 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
8974 return list;
8977 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
8978 __isl_take isl_map *map)
8980 isl_bool ok;
8982 ok = isl_map_compatible_domain(map, set);
8983 if (ok < 0)
8984 goto error;
8985 if (!ok)
8986 isl_die(isl_set_get_ctx(set), isl_error_invalid,
8987 "incompatible spaces", goto error);
8988 map = isl_map_intersect_domain(map, set);
8989 set = isl_map_range(map);
8990 return set;
8991 error:
8992 isl_set_free(set);
8993 isl_map_free(map);
8994 return NULL;
8997 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
8998 __isl_take isl_map *map)
9000 return isl_map_align_params_map_map_and(set, map, &set_apply);
9003 /* There is no need to cow as removing empty parts doesn't change
9004 * the meaning of the set.
9006 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9008 int i;
9010 if (!map)
9011 return NULL;
9013 for (i = map->n - 1; i >= 0; --i)
9014 map = remove_if_empty(map, i);
9016 return map;
9019 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
9021 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9024 /* Create a binary relation that maps the shared initial "pos" dimensions
9025 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9027 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9028 __isl_keep isl_basic_set *bset2, int pos)
9030 isl_basic_map *bmap1;
9031 isl_basic_map *bmap2;
9033 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9034 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9035 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9036 isl_dim_out, 0, pos);
9037 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9038 isl_dim_out, 0, pos);
9039 return isl_basic_map_range_product(bmap1, bmap2);
9042 /* Given two basic sets bset1 and bset2, compute the maximal difference
9043 * between the values of dimension pos in bset1 and those in bset2
9044 * for any common value of the parameters and dimensions preceding pos.
9046 static enum isl_lp_result basic_set_maximal_difference_at(
9047 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9048 int pos, isl_int *opt)
9050 isl_basic_map *bmap1;
9051 struct isl_ctx *ctx;
9052 struct isl_vec *obj;
9053 unsigned total;
9054 unsigned nparam;
9055 unsigned dim1;
9056 enum isl_lp_result res;
9058 if (!bset1 || !bset2)
9059 return isl_lp_error;
9061 nparam = isl_basic_set_n_param(bset1);
9062 dim1 = isl_basic_set_n_dim(bset1);
9064 bmap1 = join_initial(bset1, bset2, pos);
9065 if (!bmap1)
9066 return isl_lp_error;
9068 total = isl_basic_map_total_dim(bmap1);
9069 ctx = bmap1->ctx;
9070 obj = isl_vec_alloc(ctx, 1 + total);
9071 if (!obj)
9072 goto error;
9073 isl_seq_clr(obj->block.data, 1 + total);
9074 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9075 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9076 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9077 opt, NULL, NULL);
9078 isl_basic_map_free(bmap1);
9079 isl_vec_free(obj);
9080 return res;
9081 error:
9082 isl_basic_map_free(bmap1);
9083 return isl_lp_error;
9086 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9087 * for any common value of the parameters and dimensions preceding pos
9088 * in both basic sets, the values of dimension pos in bset1 are
9089 * smaller or larger than those in bset2.
9091 * Returns
9092 * 1 if bset1 follows bset2
9093 * -1 if bset1 precedes bset2
9094 * 0 if bset1 and bset2 are incomparable
9095 * -2 if some error occurred.
9097 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9098 __isl_keep isl_basic_set *bset2, int pos)
9100 isl_int opt;
9101 enum isl_lp_result res;
9102 int cmp;
9104 isl_int_init(opt);
9106 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9108 if (res == isl_lp_empty)
9109 cmp = 0;
9110 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9111 res == isl_lp_unbounded)
9112 cmp = 1;
9113 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9114 cmp = -1;
9115 else
9116 cmp = -2;
9118 isl_int_clear(opt);
9119 return cmp;
9122 /* Given two basic sets bset1 and bset2, check whether
9123 * for any common value of the parameters and dimensions preceding pos
9124 * there is a value of dimension pos in bset1 that is larger
9125 * than a value of the same dimension in bset2.
9127 * Return
9128 * 1 if there exists such a pair
9129 * 0 if there is no such pair, but there is a pair of equal values
9130 * -1 otherwise
9131 * -2 if some error occurred.
9133 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9134 __isl_keep isl_basic_set *bset2, int pos)
9136 isl_bool empty;
9137 isl_basic_map *bmap;
9138 unsigned dim1;
9140 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9141 bmap = join_initial(bset1, bset2, pos);
9142 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9143 isl_dim_out, dim1 - pos);
9144 empty = isl_basic_map_is_empty(bmap);
9145 if (empty < 0)
9146 goto error;
9147 if (empty) {
9148 isl_basic_map_free(bmap);
9149 return -1;
9151 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9152 isl_dim_out, dim1 - pos);
9153 empty = isl_basic_map_is_empty(bmap);
9154 if (empty < 0)
9155 goto error;
9156 isl_basic_map_free(bmap);
9157 if (empty)
9158 return 0;
9159 return 1;
9160 error:
9161 isl_basic_map_free(bmap);
9162 return -2;
9165 /* Given two sets set1 and set2, check whether
9166 * for any common value of the parameters and dimensions preceding pos
9167 * there is a value of dimension pos in set1 that is larger
9168 * than a value of the same dimension in set2.
9170 * Return
9171 * 1 if there exists such a pair
9172 * 0 if there is no such pair, but there is a pair of equal values
9173 * -1 otherwise
9174 * -2 if some error occurred.
9176 int isl_set_follows_at(__isl_keep isl_set *set1,
9177 __isl_keep isl_set *set2, int pos)
9179 int i, j;
9180 int follows = -1;
9182 if (!set1 || !set2)
9183 return -2;
9185 for (i = 0; i < set1->n; ++i)
9186 for (j = 0; j < set2->n; ++j) {
9187 int f;
9188 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9189 if (f == 1 || f == -2)
9190 return f;
9191 if (f > follows)
9192 follows = f;
9195 return follows;
9198 static isl_bool isl_basic_map_plain_has_fixed_var(
9199 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9201 int i;
9202 int d;
9203 unsigned total;
9205 if (!bmap)
9206 return isl_bool_error;
9207 total = isl_basic_map_total_dim(bmap);
9208 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9209 for (; d+1 > pos; --d)
9210 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9211 break;
9212 if (d != pos)
9213 continue;
9214 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9215 return isl_bool_false;
9216 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9217 return isl_bool_false;
9218 if (!isl_int_is_one(bmap->eq[i][1+d]))
9219 return isl_bool_false;
9220 if (val)
9221 isl_int_neg(*val, bmap->eq[i][0]);
9222 return isl_bool_true;
9224 return isl_bool_false;
9227 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9228 unsigned pos, isl_int *val)
9230 int i;
9231 isl_int v;
9232 isl_int tmp;
9233 isl_bool fixed;
9235 if (!map)
9236 return isl_bool_error;
9237 if (map->n == 0)
9238 return isl_bool_false;
9239 if (map->n == 1)
9240 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9241 isl_int_init(v);
9242 isl_int_init(tmp);
9243 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9244 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9245 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9246 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9247 fixed = isl_bool_false;
9249 if (val)
9250 isl_int_set(*val, v);
9251 isl_int_clear(tmp);
9252 isl_int_clear(v);
9253 return fixed;
9256 static isl_bool isl_basic_set_plain_has_fixed_var(
9257 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9259 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9260 pos, val);
9263 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9264 enum isl_dim_type type, unsigned pos, isl_int *val)
9266 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9267 return isl_bool_error;
9268 return isl_basic_map_plain_has_fixed_var(bmap,
9269 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9272 /* If "bmap" obviously lies on a hyperplane where the given dimension
9273 * has a fixed value, then return that value.
9274 * Otherwise return NaN.
9276 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9277 __isl_keep isl_basic_map *bmap,
9278 enum isl_dim_type type, unsigned pos)
9280 isl_ctx *ctx;
9281 isl_val *v;
9282 isl_bool fixed;
9284 if (!bmap)
9285 return NULL;
9286 ctx = isl_basic_map_get_ctx(bmap);
9287 v = isl_val_alloc(ctx);
9288 if (!v)
9289 return NULL;
9290 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9291 if (fixed < 0)
9292 return isl_val_free(v);
9293 if (fixed) {
9294 isl_int_set_si(v->d, 1);
9295 return v;
9297 isl_val_free(v);
9298 return isl_val_nan(ctx);
9301 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9302 enum isl_dim_type type, unsigned pos, isl_int *val)
9304 if (isl_map_check_range(map, type, pos, 1) < 0)
9305 return isl_bool_error;
9306 return isl_map_plain_has_fixed_var(map,
9307 map_offset(map, type) - 1 + pos, val);
9310 /* If "map" obviously lies on a hyperplane where the given dimension
9311 * has a fixed value, then return that value.
9312 * Otherwise return NaN.
9314 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9315 enum isl_dim_type type, unsigned pos)
9317 isl_ctx *ctx;
9318 isl_val *v;
9319 isl_bool fixed;
9321 if (!map)
9322 return NULL;
9323 ctx = isl_map_get_ctx(map);
9324 v = isl_val_alloc(ctx);
9325 if (!v)
9326 return NULL;
9327 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9328 if (fixed < 0)
9329 return isl_val_free(v);
9330 if (fixed) {
9331 isl_int_set_si(v->d, 1);
9332 return v;
9334 isl_val_free(v);
9335 return isl_val_nan(ctx);
9338 /* If "set" obviously lies on a hyperplane where the given dimension
9339 * has a fixed value, then return that value.
9340 * Otherwise return NaN.
9342 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
9343 enum isl_dim_type type, unsigned pos)
9345 return isl_map_plain_get_val_if_fixed(set, type, pos);
9348 /* Check if dimension dim has fixed value and if so and if val is not NULL,
9349 * then return this fixed value in *val.
9351 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
9352 unsigned dim, isl_int *val)
9354 return isl_basic_set_plain_has_fixed_var(bset,
9355 isl_basic_set_n_param(bset) + dim, val);
9358 /* Return -1 if the constraint "c1" should be sorted before "c2"
9359 * and 1 if it should be sorted after "c2".
9360 * Return 0 if the two constraints are the same (up to the constant term).
9362 * In particular, if a constraint involves later variables than another
9363 * then it is sorted after this other constraint.
9364 * uset_gist depends on constraints without existentially quantified
9365 * variables sorting first.
9367 * For constraints that have the same latest variable, those
9368 * with the same coefficient for this latest variable (first in absolute value
9369 * and then in actual value) are grouped together.
9370 * This is useful for detecting pairs of constraints that can
9371 * be chained in their printed representation.
9373 * Finally, within a group, constraints are sorted according to
9374 * their coefficients (excluding the constant term).
9376 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9378 isl_int **c1 = (isl_int **) p1;
9379 isl_int **c2 = (isl_int **) p2;
9380 int l1, l2;
9381 unsigned size = *(unsigned *) arg;
9382 int cmp;
9384 l1 = isl_seq_last_non_zero(*c1 + 1, size);
9385 l2 = isl_seq_last_non_zero(*c2 + 1, size);
9387 if (l1 != l2)
9388 return l1 - l2;
9390 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9391 if (cmp != 0)
9392 return cmp;
9393 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9394 if (cmp != 0)
9395 return -cmp;
9397 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9400 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
9401 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
9402 * and 0 if the two constraints are the same (up to the constant term).
9404 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
9405 isl_int *c1, isl_int *c2)
9407 unsigned total;
9409 if (!bmap)
9410 return -2;
9411 total = isl_basic_map_total_dim(bmap);
9412 return sort_constraint_cmp(&c1, &c2, &total);
9415 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9416 __isl_take isl_basic_map *bmap)
9418 unsigned total;
9420 if (!bmap)
9421 return NULL;
9422 if (bmap->n_ineq == 0)
9423 return bmap;
9424 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
9425 return bmap;
9426 total = isl_basic_map_total_dim(bmap);
9427 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9428 &sort_constraint_cmp, &total) < 0)
9429 return isl_basic_map_free(bmap);
9430 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
9431 return bmap;
9434 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9435 __isl_take isl_basic_set *bset)
9437 isl_basic_map *bmap = bset_to_bmap(bset);
9438 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9441 __isl_give isl_basic_map *isl_basic_map_normalize(
9442 __isl_take isl_basic_map *bmap)
9444 bmap = isl_basic_map_remove_redundancies(bmap);
9445 bmap = isl_basic_map_sort_constraints(bmap);
9446 return bmap;
9448 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9449 __isl_keep isl_basic_map *bmap2)
9451 int i, cmp;
9452 unsigned total;
9453 isl_space *space1, *space2;
9455 if (!bmap1 || !bmap2)
9456 return -1;
9458 if (bmap1 == bmap2)
9459 return 0;
9460 space1 = isl_basic_map_peek_space(bmap1);
9461 space2 = isl_basic_map_peek_space(bmap2);
9462 cmp = isl_space_cmp(space1, space2);
9463 if (cmp)
9464 return cmp;
9465 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9466 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9467 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9468 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9469 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9470 return 0;
9471 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9472 return 1;
9473 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9474 return -1;
9475 if (bmap1->n_eq != bmap2->n_eq)
9476 return bmap1->n_eq - bmap2->n_eq;
9477 if (bmap1->n_ineq != bmap2->n_ineq)
9478 return bmap1->n_ineq - bmap2->n_ineq;
9479 if (bmap1->n_div != bmap2->n_div)
9480 return bmap1->n_div - bmap2->n_div;
9481 total = isl_basic_map_total_dim(bmap1);
9482 for (i = 0; i < bmap1->n_eq; ++i) {
9483 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9484 if (cmp)
9485 return cmp;
9487 for (i = 0; i < bmap1->n_ineq; ++i) {
9488 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9489 if (cmp)
9490 return cmp;
9492 for (i = 0; i < bmap1->n_div; ++i) {
9493 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9494 if (cmp)
9495 return cmp;
9497 return 0;
9500 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9501 __isl_keep isl_basic_set *bset2)
9503 return isl_basic_map_plain_cmp(bset1, bset2);
9506 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9508 int i, cmp;
9510 if (set1 == set2)
9511 return 0;
9512 if (set1->n != set2->n)
9513 return set1->n - set2->n;
9515 for (i = 0; i < set1->n; ++i) {
9516 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9517 if (cmp)
9518 return cmp;
9521 return 0;
9524 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9525 __isl_keep isl_basic_map *bmap2)
9527 if (!bmap1 || !bmap2)
9528 return isl_bool_error;
9529 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9532 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9533 __isl_keep isl_basic_set *bset2)
9535 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9536 bset_to_bmap(bset2));
9539 static int qsort_bmap_cmp(const void *p1, const void *p2)
9541 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9542 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9544 return isl_basic_map_plain_cmp(bmap1, bmap2);
9547 /* Sort the basic maps of "map" and remove duplicate basic maps.
9549 * While removing basic maps, we make sure that the basic maps remain
9550 * sorted because isl_map_normalize expects the basic maps of the result
9551 * to be sorted.
9553 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9555 int i, j;
9557 map = isl_map_remove_empty_parts(map);
9558 if (!map)
9559 return NULL;
9560 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9561 for (i = map->n - 1; i >= 1; --i) {
9562 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9563 continue;
9564 isl_basic_map_free(map->p[i-1]);
9565 for (j = i; j < map->n; ++j)
9566 map->p[j - 1] = map->p[j];
9567 map->n--;
9570 return map;
9573 /* Remove obvious duplicates among the basic maps of "map".
9575 * Unlike isl_map_normalize, this function does not remove redundant
9576 * constraints and only removes duplicates that have exactly the same
9577 * constraints in the input. It does sort the constraints and
9578 * the basic maps to ease the detection of duplicates.
9580 * If "map" has already been normalized or if the basic maps are
9581 * disjoint, then there can be no duplicates.
9583 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9585 int i;
9586 isl_basic_map *bmap;
9588 if (!map)
9589 return NULL;
9590 if (map->n <= 1)
9591 return map;
9592 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9593 return map;
9594 for (i = 0; i < map->n; ++i) {
9595 bmap = isl_basic_map_copy(map->p[i]);
9596 bmap = isl_basic_map_sort_constraints(bmap);
9597 if (!bmap)
9598 return isl_map_free(map);
9599 isl_basic_map_free(map->p[i]);
9600 map->p[i] = bmap;
9603 map = sort_and_remove_duplicates(map);
9604 return map;
9607 /* We normalize in place, but if anything goes wrong we need
9608 * to return NULL, so we need to make sure we don't change the
9609 * meaning of any possible other copies of map.
9611 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9613 int i;
9614 struct isl_basic_map *bmap;
9616 if (!map)
9617 return NULL;
9618 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9619 return map;
9620 for (i = 0; i < map->n; ++i) {
9621 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9622 if (!bmap)
9623 goto error;
9624 isl_basic_map_free(map->p[i]);
9625 map->p[i] = bmap;
9628 map = sort_and_remove_duplicates(map);
9629 if (map)
9630 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9631 return map;
9632 error:
9633 isl_map_free(map);
9634 return NULL;
9637 struct isl_set *isl_set_normalize(struct isl_set *set)
9639 return set_from_map(isl_map_normalize(set_to_map(set)));
9642 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9643 __isl_keep isl_map *map2)
9645 int i;
9646 isl_bool equal;
9648 if (!map1 || !map2)
9649 return isl_bool_error;
9651 if (map1 == map2)
9652 return isl_bool_true;
9653 if (!isl_space_is_equal(map1->dim, map2->dim))
9654 return isl_bool_false;
9656 map1 = isl_map_copy(map1);
9657 map2 = isl_map_copy(map2);
9658 map1 = isl_map_normalize(map1);
9659 map2 = isl_map_normalize(map2);
9660 if (!map1 || !map2)
9661 goto error;
9662 equal = map1->n == map2->n;
9663 for (i = 0; equal && i < map1->n; ++i) {
9664 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9665 if (equal < 0)
9666 goto error;
9668 isl_map_free(map1);
9669 isl_map_free(map2);
9670 return equal;
9671 error:
9672 isl_map_free(map1);
9673 isl_map_free(map2);
9674 return isl_bool_error;
9677 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9678 __isl_keep isl_set *set2)
9680 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9683 /* Return the basic maps in "map" as a list.
9685 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9686 __isl_keep isl_map *map)
9688 int i;
9689 isl_ctx *ctx;
9690 isl_basic_map_list *list;
9692 if (!map)
9693 return NULL;
9694 ctx = isl_map_get_ctx(map);
9695 list = isl_basic_map_list_alloc(ctx, map->n);
9697 for (i = 0; i < map->n; ++i) {
9698 isl_basic_map *bmap;
9700 bmap = isl_basic_map_copy(map->p[i]);
9701 list = isl_basic_map_list_add(list, bmap);
9704 return list;
9707 /* Return the intersection of the elements in the non-empty list "list".
9708 * All elements are assumed to live in the same space.
9710 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9711 __isl_take isl_basic_map_list *list)
9713 int i, n;
9714 isl_basic_map *bmap;
9716 if (!list)
9717 return NULL;
9718 n = isl_basic_map_list_n_basic_map(list);
9719 if (n < 1)
9720 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9721 "expecting non-empty list", goto error);
9723 bmap = isl_basic_map_list_get_basic_map(list, 0);
9724 for (i = 1; i < n; ++i) {
9725 isl_basic_map *bmap_i;
9727 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9728 bmap = isl_basic_map_intersect(bmap, bmap_i);
9731 isl_basic_map_list_free(list);
9732 return bmap;
9733 error:
9734 isl_basic_map_list_free(list);
9735 return NULL;
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_set *isl_basic_set_list_intersect(
9742 __isl_take isl_basic_set_list *list)
9744 return isl_basic_map_list_intersect(list);
9747 /* Return the union of the elements of "list".
9748 * The list is required to have at least one element.
9750 __isl_give isl_set *isl_basic_set_list_union(
9751 __isl_take isl_basic_set_list *list)
9753 int i, n;
9754 isl_space *space;
9755 isl_basic_set *bset;
9756 isl_set *set;
9758 if (!list)
9759 return NULL;
9760 n = isl_basic_set_list_n_basic_set(list);
9761 if (n < 1)
9762 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9763 "expecting non-empty list", goto error);
9765 bset = isl_basic_set_list_get_basic_set(list, 0);
9766 space = isl_basic_set_get_space(bset);
9767 isl_basic_set_free(bset);
9769 set = isl_set_alloc_space(space, n, 0);
9770 for (i = 0; i < n; ++i) {
9771 bset = isl_basic_set_list_get_basic_set(list, i);
9772 set = isl_set_add_basic_set(set, bset);
9775 isl_basic_set_list_free(list);
9776 return set;
9777 error:
9778 isl_basic_set_list_free(list);
9779 return NULL;
9782 /* Return the union of the elements in the non-empty list "list".
9783 * All elements are assumed to live in the same space.
9785 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9787 int i, n;
9788 isl_set *set;
9790 if (!list)
9791 return NULL;
9792 n = isl_set_list_n_set(list);
9793 if (n < 1)
9794 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9795 "expecting non-empty list", goto error);
9797 set = isl_set_list_get_set(list, 0);
9798 for (i = 1; i < n; ++i) {
9799 isl_set *set_i;
9801 set_i = isl_set_list_get_set(list, i);
9802 set = isl_set_union(set, set_i);
9805 isl_set_list_free(list);
9806 return set;
9807 error:
9808 isl_set_list_free(list);
9809 return NULL;
9812 __isl_give isl_basic_map *isl_basic_map_product(
9813 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9815 isl_space *space_result = NULL;
9816 struct isl_basic_map *bmap;
9817 unsigned in1, in2, out1, out2, nparam, total, pos;
9818 struct isl_dim_map *dim_map1, *dim_map2;
9820 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9821 goto error;
9822 space_result = isl_space_product(isl_space_copy(bmap1->dim),
9823 isl_space_copy(bmap2->dim));
9825 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9826 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9827 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9828 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9829 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9831 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9832 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9833 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9834 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9835 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9836 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9837 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9838 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9839 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9840 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9841 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9843 bmap = isl_basic_map_alloc_space(space_result,
9844 bmap1->n_div + bmap2->n_div,
9845 bmap1->n_eq + bmap2->n_eq,
9846 bmap1->n_ineq + bmap2->n_ineq);
9847 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9848 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9849 bmap = isl_basic_map_simplify(bmap);
9850 return isl_basic_map_finalize(bmap);
9851 error:
9852 isl_basic_map_free(bmap1);
9853 isl_basic_map_free(bmap2);
9854 return NULL;
9857 __isl_give isl_basic_map *isl_basic_map_flat_product(
9858 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9860 isl_basic_map *prod;
9862 prod = isl_basic_map_product(bmap1, bmap2);
9863 prod = isl_basic_map_flatten(prod);
9864 return prod;
9867 __isl_give isl_basic_set *isl_basic_set_flat_product(
9868 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9870 return isl_basic_map_flat_range_product(bset1, bset2);
9873 __isl_give isl_basic_map *isl_basic_map_domain_product(
9874 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9876 isl_space *space_result = NULL;
9877 isl_basic_map *bmap;
9878 unsigned in1, in2, out, nparam, total, pos;
9879 struct isl_dim_map *dim_map1, *dim_map2;
9881 if (!bmap1 || !bmap2)
9882 goto error;
9884 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9885 isl_space_copy(bmap2->dim));
9887 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9888 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9889 out = isl_basic_map_dim(bmap1, isl_dim_out);
9890 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9892 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9893 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9894 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9895 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9896 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9897 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9898 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9899 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9900 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9901 isl_dim_map_div(dim_map1, bmap1, pos += out);
9902 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9904 bmap = isl_basic_map_alloc_space(space_result,
9905 bmap1->n_div + bmap2->n_div,
9906 bmap1->n_eq + bmap2->n_eq,
9907 bmap1->n_ineq + bmap2->n_ineq);
9908 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9909 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9910 bmap = isl_basic_map_simplify(bmap);
9911 return isl_basic_map_finalize(bmap);
9912 error:
9913 isl_basic_map_free(bmap1);
9914 isl_basic_map_free(bmap2);
9915 return NULL;
9918 __isl_give isl_basic_map *isl_basic_map_range_product(
9919 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9921 isl_bool rational;
9922 isl_space *space_result = NULL;
9923 isl_basic_map *bmap;
9924 unsigned in, out1, out2, nparam, total, pos;
9925 struct isl_dim_map *dim_map1, *dim_map2;
9927 rational = isl_basic_map_is_rational(bmap1);
9928 if (rational >= 0 && rational)
9929 rational = isl_basic_map_is_rational(bmap2);
9930 if (!bmap1 || !bmap2 || rational < 0)
9931 goto error;
9933 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9934 goto error;
9936 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
9937 isl_space_copy(bmap2->dim));
9939 in = isl_basic_map_dim(bmap1, isl_dim_in);
9940 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9941 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9942 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9944 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
9945 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9946 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9947 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9948 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9949 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9950 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
9951 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
9952 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9953 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9954 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9956 bmap = isl_basic_map_alloc_space(space_result,
9957 bmap1->n_div + bmap2->n_div,
9958 bmap1->n_eq + bmap2->n_eq,
9959 bmap1->n_ineq + bmap2->n_ineq);
9960 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9961 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9962 if (rational)
9963 bmap = isl_basic_map_set_rational(bmap);
9964 bmap = isl_basic_map_simplify(bmap);
9965 return isl_basic_map_finalize(bmap);
9966 error:
9967 isl_basic_map_free(bmap1);
9968 isl_basic_map_free(bmap2);
9969 return NULL;
9972 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
9973 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9975 isl_basic_map *prod;
9977 prod = isl_basic_map_range_product(bmap1, bmap2);
9978 prod = isl_basic_map_flatten_range(prod);
9979 return prod;
9982 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
9983 * and collect the results.
9984 * The result live in the space obtained by calling "space_product"
9985 * on the spaces of "map1" and "map2".
9986 * If "remove_duplicates" is set then the result may contain duplicates
9987 * (even if the inputs do not) and so we try and remove the obvious
9988 * duplicates.
9990 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
9991 __isl_take isl_map *map2,
9992 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
9993 __isl_take isl_space *right),
9994 __isl_give isl_basic_map *(*basic_map_product)(
9995 __isl_take isl_basic_map *left,
9996 __isl_take isl_basic_map *right),
9997 int remove_duplicates)
9999 unsigned flags = 0;
10000 struct isl_map *result;
10001 int i, j;
10002 isl_bool m;
10004 m = isl_map_has_equal_params(map1, map2);
10005 if (m < 0)
10006 goto error;
10007 if (!m)
10008 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10009 "parameters don't match", goto error);
10011 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10012 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10013 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10015 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10016 isl_space_copy(map2->dim)),
10017 map1->n * map2->n, flags);
10018 if (!result)
10019 goto error;
10020 for (i = 0; i < map1->n; ++i)
10021 for (j = 0; j < map2->n; ++j) {
10022 struct isl_basic_map *part;
10023 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10024 isl_basic_map_copy(map2->p[j]));
10025 if (isl_basic_map_is_empty(part))
10026 isl_basic_map_free(part);
10027 else
10028 result = isl_map_add_basic_map(result, part);
10029 if (!result)
10030 goto error;
10032 if (remove_duplicates)
10033 result = isl_map_remove_obvious_duplicates(result);
10034 isl_map_free(map1);
10035 isl_map_free(map2);
10036 return result;
10037 error:
10038 isl_map_free(map1);
10039 isl_map_free(map2);
10040 return NULL;
10043 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10045 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
10046 __isl_take isl_map *map2)
10048 return map_product(map1, map2, &isl_space_product,
10049 &isl_basic_map_product, 0);
10052 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10053 __isl_take isl_map *map2)
10055 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
10058 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10060 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10061 __isl_take isl_map *map2)
10063 isl_map *prod;
10065 prod = isl_map_product(map1, map2);
10066 prod = isl_map_flatten(prod);
10067 return prod;
10070 /* Given two set A and B, construct its Cartesian product A x B.
10072 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
10074 return isl_map_range_product(set1, set2);
10077 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10078 __isl_take isl_set *set2)
10080 return isl_map_flat_range_product(set1, set2);
10083 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10085 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
10086 __isl_take isl_map *map2)
10088 return map_product(map1, map2, &isl_space_domain_product,
10089 &isl_basic_map_domain_product, 1);
10092 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10094 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
10095 __isl_take isl_map *map2)
10097 return map_product(map1, map2, &isl_space_range_product,
10098 &isl_basic_map_range_product, 1);
10101 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10102 __isl_take isl_map *map2)
10104 return isl_map_align_params_map_map_and(map1, map2,
10105 &map_domain_product_aligned);
10108 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10109 __isl_take isl_map *map2)
10111 return isl_map_align_params_map_map_and(map1, map2,
10112 &map_range_product_aligned);
10115 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10117 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10119 isl_space *space;
10120 int total1, keep1, total2, keep2;
10122 if (!map)
10123 return NULL;
10124 if (!isl_space_domain_is_wrapping(map->dim) ||
10125 !isl_space_range_is_wrapping(map->dim))
10126 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10127 "not a product", return isl_map_free(map));
10129 space = isl_map_get_space(map);
10130 total1 = isl_space_dim(space, isl_dim_in);
10131 total2 = isl_space_dim(space, isl_dim_out);
10132 space = isl_space_factor_domain(space);
10133 keep1 = isl_space_dim(space, isl_dim_in);
10134 keep2 = isl_space_dim(space, isl_dim_out);
10135 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10136 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10137 map = isl_map_reset_space(map, space);
10139 return map;
10142 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10144 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10146 isl_space *space;
10147 int total1, keep1, total2, keep2;
10149 if (!map)
10150 return NULL;
10151 if (!isl_space_domain_is_wrapping(map->dim) ||
10152 !isl_space_range_is_wrapping(map->dim))
10153 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10154 "not a product", return isl_map_free(map));
10156 space = isl_map_get_space(map);
10157 total1 = isl_space_dim(space, isl_dim_in);
10158 total2 = isl_space_dim(space, isl_dim_out);
10159 space = isl_space_factor_range(space);
10160 keep1 = isl_space_dim(space, isl_dim_in);
10161 keep2 = isl_space_dim(space, isl_dim_out);
10162 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10163 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10164 map = isl_map_reset_space(map, space);
10166 return map;
10169 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10171 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10173 isl_space *space;
10174 int total, keep;
10176 if (!map)
10177 return NULL;
10178 if (!isl_space_domain_is_wrapping(map->dim))
10179 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10180 "domain is not a product", return isl_map_free(map));
10182 space = isl_map_get_space(map);
10183 total = isl_space_dim(space, isl_dim_in);
10184 space = isl_space_domain_factor_domain(space);
10185 keep = isl_space_dim(space, isl_dim_in);
10186 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10187 map = isl_map_reset_space(map, space);
10189 return map;
10192 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10194 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10196 isl_space *space;
10197 int total, keep;
10199 if (!map)
10200 return NULL;
10201 if (!isl_space_domain_is_wrapping(map->dim))
10202 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10203 "domain is not a product", return isl_map_free(map));
10205 space = isl_map_get_space(map);
10206 total = isl_space_dim(space, isl_dim_in);
10207 space = isl_space_domain_factor_range(space);
10208 keep = isl_space_dim(space, isl_dim_in);
10209 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10210 map = isl_map_reset_space(map, space);
10212 return map;
10215 /* Given a map A -> [B -> C], extract the map A -> B.
10217 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10219 isl_space *space;
10220 int total, keep;
10222 if (!map)
10223 return NULL;
10224 if (!isl_space_range_is_wrapping(map->dim))
10225 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10226 "range is not a product", return isl_map_free(map));
10228 space = isl_map_get_space(map);
10229 total = isl_space_dim(space, isl_dim_out);
10230 space = isl_space_range_factor_domain(space);
10231 keep = isl_space_dim(space, isl_dim_out);
10232 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10233 map = isl_map_reset_space(map, space);
10235 return map;
10238 /* Given a map A -> [B -> C], extract the map A -> C.
10240 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10242 isl_space *space;
10243 int total, keep;
10245 if (!map)
10246 return NULL;
10247 if (!isl_space_range_is_wrapping(map->dim))
10248 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10249 "range is not a product", return isl_map_free(map));
10251 space = isl_map_get_space(map);
10252 total = isl_space_dim(space, isl_dim_out);
10253 space = isl_space_range_factor_range(space);
10254 keep = isl_space_dim(space, isl_dim_out);
10255 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10256 map = isl_map_reset_space(map, space);
10258 return map;
10261 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10263 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10264 __isl_take isl_map *map2)
10266 isl_map *prod;
10268 prod = isl_map_domain_product(map1, map2);
10269 prod = isl_map_flatten_domain(prod);
10270 return prod;
10273 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10275 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10276 __isl_take isl_map *map2)
10278 isl_map *prod;
10280 prod = isl_map_range_product(map1, map2);
10281 prod = isl_map_flatten_range(prod);
10282 return prod;
10285 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10287 int i;
10288 uint32_t hash = isl_hash_init();
10289 unsigned total;
10291 if (!bmap)
10292 return 0;
10293 bmap = isl_basic_map_copy(bmap);
10294 bmap = isl_basic_map_normalize(bmap);
10295 if (!bmap)
10296 return 0;
10297 total = isl_basic_map_total_dim(bmap);
10298 isl_hash_byte(hash, bmap->n_eq & 0xFF);
10299 for (i = 0; i < bmap->n_eq; ++i) {
10300 uint32_t c_hash;
10301 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
10302 isl_hash_hash(hash, c_hash);
10304 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
10305 for (i = 0; i < bmap->n_ineq; ++i) {
10306 uint32_t c_hash;
10307 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
10308 isl_hash_hash(hash, c_hash);
10310 isl_hash_byte(hash, bmap->n_div & 0xFF);
10311 for (i = 0; i < bmap->n_div; ++i) {
10312 uint32_t c_hash;
10313 if (isl_int_is_zero(bmap->div[i][0]))
10314 continue;
10315 isl_hash_byte(hash, i & 0xFF);
10316 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
10317 isl_hash_hash(hash, c_hash);
10319 isl_basic_map_free(bmap);
10320 return hash;
10323 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
10325 return isl_basic_map_get_hash(bset_to_bmap(bset));
10328 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
10330 int i;
10331 uint32_t hash;
10333 if (!map)
10334 return 0;
10335 map = isl_map_copy(map);
10336 map = isl_map_normalize(map);
10337 if (!map)
10338 return 0;
10340 hash = isl_hash_init();
10341 for (i = 0; i < map->n; ++i) {
10342 uint32_t bmap_hash;
10343 bmap_hash = isl_basic_map_get_hash(map->p[i]);
10344 isl_hash_hash(hash, bmap_hash);
10347 isl_map_free(map);
10349 return hash;
10352 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
10354 return isl_map_get_hash(set_to_map(set));
10357 /* Return the number of basic maps in the (current) representation of "map".
10359 int isl_map_n_basic_map(__isl_keep isl_map *map)
10361 return map ? map->n : 0;
10364 int isl_set_n_basic_set(__isl_keep isl_set *set)
10366 return set ? set->n : 0;
10369 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
10370 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10372 int i;
10374 if (!map)
10375 return isl_stat_error;
10377 for (i = 0; i < map->n; ++i)
10378 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10379 return isl_stat_error;
10381 return isl_stat_ok;
10384 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10385 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10387 int i;
10389 if (!set)
10390 return isl_stat_error;
10392 for (i = 0; i < set->n; ++i)
10393 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10394 return isl_stat_error;
10396 return isl_stat_ok;
10399 /* Return a list of basic sets, the union of which is equal to "set".
10401 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10402 __isl_keep isl_set *set)
10404 int i;
10405 isl_basic_set_list *list;
10407 if (!set)
10408 return NULL;
10410 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10411 for (i = 0; i < set->n; ++i) {
10412 isl_basic_set *bset;
10414 bset = isl_basic_set_copy(set->p[i]);
10415 list = isl_basic_set_list_add(list, bset);
10418 return list;
10421 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10423 isl_space *space;
10425 if (!bset)
10426 return NULL;
10428 bset = isl_basic_set_cow(bset);
10429 if (!bset)
10430 return NULL;
10432 space = isl_basic_set_get_space(bset);
10433 space = isl_space_lift(space, bset->n_div);
10434 if (!space)
10435 goto error;
10436 isl_space_free(bset->dim);
10437 bset->dim = space;
10438 bset->extra -= bset->n_div;
10439 bset->n_div = 0;
10441 bset = isl_basic_set_finalize(bset);
10443 return bset;
10444 error:
10445 isl_basic_set_free(bset);
10446 return NULL;
10449 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10451 int i;
10452 isl_space *space;
10453 unsigned n_div;
10455 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10457 if (!set)
10458 return NULL;
10460 set = isl_set_cow(set);
10461 if (!set)
10462 return NULL;
10464 n_div = set->p[0]->n_div;
10465 space = isl_set_get_space(set);
10466 space = isl_space_lift(space, n_div);
10467 if (!space)
10468 goto error;
10469 isl_space_free(set->dim);
10470 set->dim = space;
10472 for (i = 0; i < set->n; ++i) {
10473 set->p[i] = isl_basic_set_lift(set->p[i]);
10474 if (!set->p[i])
10475 goto error;
10478 return set;
10479 error:
10480 isl_set_free(set);
10481 return NULL;
10484 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10486 unsigned dim;
10487 int size = 0;
10489 if (!bset)
10490 return -1;
10492 dim = isl_basic_set_total_dim(bset);
10493 size += bset->n_eq * (1 + dim);
10494 size += bset->n_ineq * (1 + dim);
10495 size += bset->n_div * (2 + dim);
10497 return size;
10500 int isl_set_size(__isl_keep isl_set *set)
10502 int i;
10503 int size = 0;
10505 if (!set)
10506 return -1;
10508 for (i = 0; i < set->n; ++i)
10509 size += isl_basic_set_size(set->p[i]);
10511 return size;
10514 /* Check if there is any lower bound (if lower == 0) and/or upper
10515 * bound (if upper == 0) on the specified dim.
10517 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10518 enum isl_dim_type type, unsigned pos, int lower, int upper)
10520 int i;
10522 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10523 return isl_bool_error;
10525 pos += isl_basic_map_offset(bmap, type);
10527 for (i = 0; i < bmap->n_div; ++i) {
10528 if (isl_int_is_zero(bmap->div[i][0]))
10529 continue;
10530 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10531 return isl_bool_true;
10534 for (i = 0; i < bmap->n_eq; ++i)
10535 if (!isl_int_is_zero(bmap->eq[i][pos]))
10536 return isl_bool_true;
10538 for (i = 0; i < bmap->n_ineq; ++i) {
10539 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10540 if (sgn > 0)
10541 lower = 1;
10542 if (sgn < 0)
10543 upper = 1;
10546 return lower && upper;
10549 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10550 enum isl_dim_type type, unsigned pos)
10552 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10555 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10556 enum isl_dim_type type, unsigned pos)
10558 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10561 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10562 enum isl_dim_type type, unsigned pos)
10564 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10567 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10568 enum isl_dim_type type, unsigned pos)
10570 int i;
10572 if (!map)
10573 return isl_bool_error;
10575 for (i = 0; i < map->n; ++i) {
10576 isl_bool bounded;
10577 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10578 if (bounded < 0 || !bounded)
10579 return bounded;
10582 return isl_bool_true;
10585 /* Return true if the specified dim is involved in both an upper bound
10586 * and a lower bound.
10588 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10589 enum isl_dim_type type, unsigned pos)
10591 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10594 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10596 static isl_bool has_any_bound(__isl_keep isl_map *map,
10597 enum isl_dim_type type, unsigned pos,
10598 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
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 = fn(map->p[i], type, pos);
10609 if (bounded < 0 || bounded)
10610 return bounded;
10613 return isl_bool_false;
10616 /* Return 1 if the specified dim is involved in any lower bound.
10618 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10619 enum isl_dim_type type, unsigned pos)
10621 return has_any_bound(set, type, pos,
10622 &isl_basic_map_dim_has_lower_bound);
10625 /* Return 1 if the specified dim is involved in any upper bound.
10627 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10628 enum isl_dim_type type, unsigned pos)
10630 return has_any_bound(set, type, pos,
10631 &isl_basic_map_dim_has_upper_bound);
10634 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10636 static isl_bool has_bound(__isl_keep isl_map *map,
10637 enum isl_dim_type type, unsigned pos,
10638 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10639 enum isl_dim_type type, unsigned pos))
10641 int i;
10643 if (!map)
10644 return isl_bool_error;
10646 for (i = 0; i < map->n; ++i) {
10647 isl_bool bounded;
10648 bounded = fn(map->p[i], type, pos);
10649 if (bounded < 0 || !bounded)
10650 return bounded;
10653 return isl_bool_true;
10656 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10658 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10659 enum isl_dim_type type, unsigned pos)
10661 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10664 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10666 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10667 enum isl_dim_type type, unsigned pos)
10669 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10672 /* For each of the "n" variables starting at "first", determine
10673 * the sign of the variable and put the results in the first "n"
10674 * elements of the array "signs".
10675 * Sign
10676 * 1 means that the variable is non-negative
10677 * -1 means that the variable is non-positive
10678 * 0 means the variable attains both positive and negative values.
10680 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10681 unsigned first, unsigned n, int *signs)
10683 isl_vec *bound = NULL;
10684 struct isl_tab *tab = NULL;
10685 struct isl_tab_undo *snap;
10686 int i;
10688 if (!bset || !signs)
10689 return isl_stat_error;
10691 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10692 tab = isl_tab_from_basic_set(bset, 0);
10693 if (!bound || !tab)
10694 goto error;
10696 isl_seq_clr(bound->el, bound->size);
10697 isl_int_set_si(bound->el[0], -1);
10699 snap = isl_tab_snap(tab);
10700 for (i = 0; i < n; ++i) {
10701 int empty;
10703 isl_int_set_si(bound->el[1 + first + i], -1);
10704 if (isl_tab_add_ineq(tab, bound->el) < 0)
10705 goto error;
10706 empty = tab->empty;
10707 isl_int_set_si(bound->el[1 + first + i], 0);
10708 if (isl_tab_rollback(tab, snap) < 0)
10709 goto error;
10711 if (empty) {
10712 signs[i] = 1;
10713 continue;
10716 isl_int_set_si(bound->el[1 + first + i], 1);
10717 if (isl_tab_add_ineq(tab, bound->el) < 0)
10718 goto error;
10719 empty = tab->empty;
10720 isl_int_set_si(bound->el[1 + first + i], 0);
10721 if (isl_tab_rollback(tab, snap) < 0)
10722 goto error;
10724 signs[i] = empty ? -1 : 0;
10727 isl_tab_free(tab);
10728 isl_vec_free(bound);
10729 return isl_stat_ok;
10730 error:
10731 isl_tab_free(tab);
10732 isl_vec_free(bound);
10733 return isl_stat_error;
10736 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10737 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10739 if (!bset || !signs)
10740 return isl_stat_error;
10741 if (isl_basic_set_check_range(bset, type, first, n) < 0)
10742 return isl_stat_error;
10744 first += pos(bset->dim, type) - 1;
10745 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10748 /* Is it possible for the integer division "div" to depend (possibly
10749 * indirectly) on any output dimensions?
10751 * If the div is undefined, then we conservatively assume that it
10752 * may depend on them.
10753 * Otherwise, we check if it actually depends on them or on any integer
10754 * divisions that may depend on them.
10756 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10758 int i;
10759 unsigned n_out, o_out;
10760 unsigned n_div, o_div;
10762 if (isl_int_is_zero(bmap->div[div][0]))
10763 return isl_bool_true;
10765 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10766 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10768 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10769 return isl_bool_true;
10771 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10772 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10774 for (i = 0; i < n_div; ++i) {
10775 isl_bool may_involve;
10777 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10778 continue;
10779 may_involve = div_may_involve_output(bmap, i);
10780 if (may_involve < 0 || may_involve)
10781 return may_involve;
10784 return isl_bool_false;
10787 /* Return the first integer division of "bmap" in the range
10788 * [first, first + n[ that may depend on any output dimensions and
10789 * that has a non-zero coefficient in "c" (where the first coefficient
10790 * in "c" corresponds to integer division "first").
10792 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10793 isl_int *c, int first, int n)
10795 int k;
10797 if (!bmap)
10798 return -1;
10800 for (k = first; k < first + n; ++k) {
10801 isl_bool may_involve;
10803 if (isl_int_is_zero(c[k]))
10804 continue;
10805 may_involve = div_may_involve_output(bmap, k);
10806 if (may_involve < 0)
10807 return -1;
10808 if (may_involve)
10809 return k;
10812 return first + n;
10815 /* Look for a pair of inequality constraints in "bmap" of the form
10817 * -l + i >= 0 or i >= l
10818 * and
10819 * n + l - i >= 0 or i <= l + n
10821 * with n < "m" and i the output dimension at position "pos".
10822 * (Note that n >= 0 as otherwise the two constraints would conflict.)
10823 * Furthermore, "l" is only allowed to involve parameters, input dimensions
10824 * and earlier output dimensions, as well as integer divisions that do
10825 * not involve any of the output dimensions.
10827 * Return the index of the first inequality constraint or bmap->n_ineq
10828 * if no such pair can be found.
10830 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10831 int pos, isl_int m)
10833 int i, j;
10834 isl_ctx *ctx;
10835 unsigned total;
10836 unsigned n_div, o_div;
10837 unsigned n_out, o_out;
10838 int less;
10840 if (!bmap)
10841 return -1;
10843 ctx = isl_basic_map_get_ctx(bmap);
10844 total = isl_basic_map_total_dim(bmap);
10845 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10846 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10847 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10848 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10849 for (i = 0; i < bmap->n_ineq; ++i) {
10850 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
10851 continue;
10852 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
10853 n_out - (pos + 1)) != -1)
10854 continue;
10855 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
10856 0, n_div) < n_div)
10857 continue;
10858 for (j = i + 1; j < bmap->n_ineq; ++j) {
10859 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
10860 ctx->one))
10861 continue;
10862 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
10863 bmap->ineq[j] + 1, total))
10864 continue;
10865 break;
10867 if (j >= bmap->n_ineq)
10868 continue;
10869 isl_int_add(bmap->ineq[i][0],
10870 bmap->ineq[i][0], bmap->ineq[j][0]);
10871 less = isl_int_abs_lt(bmap->ineq[i][0], m);
10872 isl_int_sub(bmap->ineq[i][0],
10873 bmap->ineq[i][0], bmap->ineq[j][0]);
10874 if (!less)
10875 continue;
10876 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
10877 return i;
10878 else
10879 return j;
10882 return bmap->n_ineq;
10885 /* Return the index of the equality of "bmap" that defines
10886 * the output dimension "pos" in terms of earlier dimensions.
10887 * The equality may also involve integer divisions, as long
10888 * as those integer divisions are defined in terms of
10889 * parameters or input dimensions.
10890 * In this case, *div is set to the number of integer divisions and
10891 * *ineq is set to the number of inequality constraints (provided
10892 * div and ineq are not NULL).
10894 * The equality may also involve a single integer division involving
10895 * the output dimensions (typically only output dimension "pos") as
10896 * long as the coefficient of output dimension "pos" is 1 or -1 and
10897 * there is a pair of constraints i >= l and i <= l + n, with i referring
10898 * to output dimension "pos", l an expression involving only earlier
10899 * dimensions and n smaller than the coefficient of the integer division
10900 * in the equality. In this case, the output dimension can be defined
10901 * in terms of a modulo expression that does not involve the integer division.
10902 * *div is then set to this single integer division and
10903 * *ineq is set to the index of constraint i >= l.
10905 * Return bmap->n_eq if there is no such equality.
10906 * Return -1 on error.
10908 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
10909 int pos, int *div, int *ineq)
10911 int j, k, l;
10912 unsigned n_out, o_out;
10913 unsigned n_div, o_div;
10915 if (!bmap)
10916 return -1;
10918 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10919 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10920 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10921 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10923 if (ineq)
10924 *ineq = bmap->n_ineq;
10925 if (div)
10926 *div = n_div;
10927 for (j = 0; j < bmap->n_eq; ++j) {
10928 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
10929 continue;
10930 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
10931 n_out - (pos + 1)) != -1)
10932 continue;
10933 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10934 0, n_div);
10935 if (k >= n_div)
10936 return j;
10937 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
10938 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
10939 continue;
10940 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10941 k + 1, n_div - (k+1)) < n_div)
10942 continue;
10943 l = find_modulo_constraint_pair(bmap, pos,
10944 bmap->eq[j][o_div + k]);
10945 if (l < 0)
10946 return -1;
10947 if (l >= bmap->n_ineq)
10948 continue;
10949 if (div)
10950 *div = k;
10951 if (ineq)
10952 *ineq = l;
10953 return j;
10956 return bmap->n_eq;
10959 /* Check if the given basic map is obviously single-valued.
10960 * In particular, for each output dimension, check that there is
10961 * an equality that defines the output dimension in terms of
10962 * earlier dimensions.
10964 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
10966 int i;
10967 unsigned n_out;
10969 if (!bmap)
10970 return isl_bool_error;
10972 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10974 for (i = 0; i < n_out; ++i) {
10975 int eq;
10977 eq = isl_basic_map_output_defining_equality(bmap, i,
10978 NULL, NULL);
10979 if (eq < 0)
10980 return isl_bool_error;
10981 if (eq >= bmap->n_eq)
10982 return isl_bool_false;
10985 return isl_bool_true;
10988 /* Check if the given basic map is single-valued.
10989 * We simply compute
10991 * M \circ M^-1
10993 * and check if the result is a subset of the identity mapping.
10995 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
10997 isl_space *space;
10998 isl_basic_map *test;
10999 isl_basic_map *id;
11000 isl_bool sv;
11002 sv = isl_basic_map_plain_is_single_valued(bmap);
11003 if (sv < 0 || sv)
11004 return sv;
11006 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11007 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11009 space = isl_basic_map_get_space(bmap);
11010 space = isl_space_map_from_set(isl_space_range(space));
11011 id = isl_basic_map_identity(space);
11013 sv = isl_basic_map_is_subset(test, id);
11015 isl_basic_map_free(test);
11016 isl_basic_map_free(id);
11018 return sv;
11021 /* Check if the given map is obviously single-valued.
11023 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11025 if (!map)
11026 return isl_bool_error;
11027 if (map->n == 0)
11028 return isl_bool_true;
11029 if (map->n >= 2)
11030 return isl_bool_false;
11032 return isl_basic_map_plain_is_single_valued(map->p[0]);
11035 /* Check if the given map is single-valued.
11036 * We simply compute
11038 * M \circ M^-1
11040 * and check if the result is a subset of the identity mapping.
11042 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11044 isl_space *dim;
11045 isl_map *test;
11046 isl_map *id;
11047 isl_bool sv;
11049 sv = isl_map_plain_is_single_valued(map);
11050 if (sv < 0 || sv)
11051 return sv;
11053 test = isl_map_reverse(isl_map_copy(map));
11054 test = isl_map_apply_range(test, isl_map_copy(map));
11056 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11057 id = isl_map_identity(dim);
11059 sv = isl_map_is_subset(test, id);
11061 isl_map_free(test);
11062 isl_map_free(id);
11064 return sv;
11067 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11069 isl_bool in;
11071 map = isl_map_copy(map);
11072 map = isl_map_reverse(map);
11073 in = isl_map_is_single_valued(map);
11074 isl_map_free(map);
11076 return in;
11079 /* Check if the given map is obviously injective.
11081 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11083 isl_bool in;
11085 map = isl_map_copy(map);
11086 map = isl_map_reverse(map);
11087 in = isl_map_plain_is_single_valued(map);
11088 isl_map_free(map);
11090 return in;
11093 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11095 isl_bool sv;
11097 sv = isl_map_is_single_valued(map);
11098 if (sv < 0 || !sv)
11099 return sv;
11101 return isl_map_is_injective(map);
11104 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11106 return isl_map_is_single_valued(set_to_map(set));
11109 /* Does "map" only map elements to themselves?
11111 * If the domain and range spaces are different, then "map"
11112 * is considered not to be an identity relation, even if it is empty.
11113 * Otherwise, construct the maximal identity relation and
11114 * check whether "map" is a subset of this relation.
11116 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11118 isl_space *space;
11119 isl_map *id;
11120 isl_bool equal, is_identity;
11122 space = isl_map_get_space(map);
11123 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
11124 isl_space_free(space);
11125 if (equal < 0 || !equal)
11126 return equal;
11128 id = isl_map_identity(isl_map_get_space(map));
11129 is_identity = isl_map_is_subset(map, id);
11130 isl_map_free(id);
11132 return is_identity;
11135 int isl_map_is_translation(__isl_keep isl_map *map)
11137 int ok;
11138 isl_set *delta;
11140 delta = isl_map_deltas(isl_map_copy(map));
11141 ok = isl_set_is_singleton(delta);
11142 isl_set_free(delta);
11144 return ok;
11147 static int unique(isl_int *p, unsigned pos, unsigned len)
11149 if (isl_seq_first_non_zero(p, pos) != -1)
11150 return 0;
11151 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11152 return 0;
11153 return 1;
11156 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11158 int i, j;
11159 unsigned nvar;
11160 unsigned ovar;
11162 if (!bset)
11163 return isl_bool_error;
11165 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
11166 return isl_bool_false;
11168 nvar = isl_basic_set_dim(bset, isl_dim_set);
11169 ovar = isl_space_offset(bset->dim, isl_dim_set);
11170 for (j = 0; j < nvar; ++j) {
11171 int lower = 0, upper = 0;
11172 for (i = 0; i < bset->n_eq; ++i) {
11173 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11174 continue;
11175 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11176 return isl_bool_false;
11177 break;
11179 if (i < bset->n_eq)
11180 continue;
11181 for (i = 0; i < bset->n_ineq; ++i) {
11182 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11183 continue;
11184 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11185 return isl_bool_false;
11186 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11187 lower = 1;
11188 else
11189 upper = 1;
11191 if (!lower || !upper)
11192 return isl_bool_false;
11195 return isl_bool_true;
11198 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11200 if (!set)
11201 return isl_bool_error;
11202 if (set->n != 1)
11203 return isl_bool_false;
11205 return isl_basic_set_is_box(set->p[0]);
11208 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11210 if (!bset)
11211 return isl_bool_error;
11213 return isl_space_is_wrapping(bset->dim);
11216 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11218 if (!set)
11219 return isl_bool_error;
11221 return isl_space_is_wrapping(set->dim);
11224 /* Modify the space of "map" through a call to "change".
11225 * If "can_change" is set (not NULL), then first call it to check
11226 * if the modification is allowed, printing the error message "cannot_change"
11227 * if it is not.
11229 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11230 isl_bool (*can_change)(__isl_keep isl_map *map),
11231 const char *cannot_change,
11232 __isl_give isl_space *(*change)(__isl_take isl_space *space))
11234 isl_bool ok;
11235 isl_space *space;
11237 if (!map)
11238 return NULL;
11240 ok = can_change ? can_change(map) : isl_bool_true;
11241 if (ok < 0)
11242 return isl_map_free(map);
11243 if (!ok)
11244 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11245 return isl_map_free(map));
11247 space = change(isl_map_get_space(map));
11248 map = isl_map_reset_space(map, space);
11250 return map;
11253 /* Is the domain of "map" a wrapped relation?
11255 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11257 if (!map)
11258 return isl_bool_error;
11260 return isl_space_domain_is_wrapping(map->dim);
11263 /* Does "map" have a wrapped relation in both domain and range?
11265 isl_bool isl_map_is_product(__isl_keep isl_map *map)
11267 return isl_space_is_product(isl_map_peek_space(map));
11270 /* Is the range of "map" a wrapped relation?
11272 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
11274 if (!map)
11275 return isl_bool_error;
11277 return isl_space_range_is_wrapping(map->dim);
11280 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
11282 bmap = isl_basic_map_cow(bmap);
11283 if (!bmap)
11284 return NULL;
11286 bmap->dim = isl_space_wrap(bmap->dim);
11287 if (!bmap->dim)
11288 goto error;
11290 bmap = isl_basic_map_finalize(bmap);
11292 return bset_from_bmap(bmap);
11293 error:
11294 isl_basic_map_free(bmap);
11295 return NULL;
11298 /* Given a map A -> B, return the set (A -> B).
11300 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
11302 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
11305 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
11307 bset = isl_basic_set_cow(bset);
11308 if (!bset)
11309 return NULL;
11311 bset->dim = isl_space_unwrap(bset->dim);
11312 if (!bset->dim)
11313 goto error;
11315 bset = isl_basic_set_finalize(bset);
11317 return bset_to_bmap(bset);
11318 error:
11319 isl_basic_set_free(bset);
11320 return NULL;
11323 /* Given a set (A -> B), return the map A -> B.
11324 * Error out if "set" is not of the form (A -> B).
11326 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
11328 return isl_map_change_space(set, &isl_set_is_wrapping,
11329 "not a wrapping set", &isl_space_unwrap);
11332 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
11333 enum isl_dim_type type)
11335 if (!bmap)
11336 return NULL;
11338 if (!isl_space_is_named_or_nested(bmap->dim, type))
11339 return bmap;
11341 bmap = isl_basic_map_cow(bmap);
11342 if (!bmap)
11343 return NULL;
11345 bmap->dim = isl_space_reset(bmap->dim, type);
11346 if (!bmap->dim)
11347 goto error;
11349 bmap = isl_basic_map_finalize(bmap);
11351 return bmap;
11352 error:
11353 isl_basic_map_free(bmap);
11354 return NULL;
11357 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
11358 enum isl_dim_type type)
11360 int i;
11362 if (!map)
11363 return NULL;
11365 if (!isl_space_is_named_or_nested(map->dim, type))
11366 return map;
11368 map = isl_map_cow(map);
11369 if (!map)
11370 return NULL;
11372 for (i = 0; i < map->n; ++i) {
11373 map->p[i] = isl_basic_map_reset(map->p[i], type);
11374 if (!map->p[i])
11375 goto error;
11377 map->dim = isl_space_reset(map->dim, type);
11378 if (!map->dim)
11379 goto error;
11381 return map;
11382 error:
11383 isl_map_free(map);
11384 return NULL;
11387 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11389 if (!bmap)
11390 return NULL;
11392 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11393 return bmap;
11395 bmap = isl_basic_map_cow(bmap);
11396 if (!bmap)
11397 return NULL;
11399 bmap->dim = isl_space_flatten(bmap->dim);
11400 if (!bmap->dim)
11401 goto error;
11403 bmap = isl_basic_map_finalize(bmap);
11405 return bmap;
11406 error:
11407 isl_basic_map_free(bmap);
11408 return NULL;
11411 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11413 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11416 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11417 __isl_take isl_basic_map *bmap)
11419 if (!bmap)
11420 return NULL;
11422 if (!bmap->dim->nested[0])
11423 return bmap;
11425 bmap = isl_basic_map_cow(bmap);
11426 if (!bmap)
11427 return NULL;
11429 bmap->dim = isl_space_flatten_domain(bmap->dim);
11430 if (!bmap->dim)
11431 goto error;
11433 bmap = isl_basic_map_finalize(bmap);
11435 return bmap;
11436 error:
11437 isl_basic_map_free(bmap);
11438 return NULL;
11441 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11442 __isl_take isl_basic_map *bmap)
11444 if (!bmap)
11445 return NULL;
11447 if (!bmap->dim->nested[1])
11448 return bmap;
11450 bmap = isl_basic_map_cow(bmap);
11451 if (!bmap)
11452 return NULL;
11454 bmap->dim = isl_space_flatten_range(bmap->dim);
11455 if (!bmap->dim)
11456 goto error;
11458 bmap = isl_basic_map_finalize(bmap);
11460 return bmap;
11461 error:
11462 isl_basic_map_free(bmap);
11463 return NULL;
11466 /* Remove any internal structure from the spaces of domain and range of "map".
11468 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11470 if (!map)
11471 return NULL;
11473 if (!map->dim->nested[0] && !map->dim->nested[1])
11474 return map;
11476 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11479 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11481 return set_from_map(isl_map_flatten(set_to_map(set)));
11484 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11486 isl_space *space, *flat_space;
11487 isl_map *map;
11489 space = isl_set_get_space(set);
11490 flat_space = isl_space_flatten(isl_space_copy(space));
11491 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
11492 flat_space));
11493 map = isl_map_intersect_domain(map, set);
11495 return map;
11498 /* Remove any internal structure from the space of the domain of "map".
11500 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11502 if (!map)
11503 return NULL;
11505 if (!map->dim->nested[0])
11506 return map;
11508 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11511 /* Remove any internal structure from the space of the range of "map".
11513 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11515 if (!map)
11516 return NULL;
11518 if (!map->dim->nested[1])
11519 return map;
11521 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11524 /* Reorder the dimensions of "bmap" according to the given dim_map
11525 * and set the dimension specification to "space" and
11526 * perform Gaussian elimination on the result.
11528 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11529 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
11531 isl_basic_map *res;
11532 unsigned flags;
11533 unsigned n_div;
11535 if (!bmap || !space || !dim_map)
11536 goto error;
11538 flags = bmap->flags;
11539 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11540 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
11541 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11542 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11543 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
11544 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11545 if (res)
11546 res->flags = flags;
11547 res = isl_basic_map_gauss(res, NULL);
11548 res = isl_basic_map_finalize(res);
11549 return res;
11550 error:
11551 isl_dim_map_free(dim_map);
11552 isl_basic_map_free(bmap);
11553 isl_space_free(space);
11554 return NULL;
11557 /* Reorder the dimensions of "map" according to given reordering.
11559 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11560 __isl_take isl_reordering *r)
11562 int i;
11563 struct isl_dim_map *dim_map;
11565 map = isl_map_cow(map);
11566 dim_map = isl_dim_map_from_reordering(r);
11567 if (!map || !r || !dim_map)
11568 goto error;
11570 for (i = 0; i < map->n; ++i) {
11571 struct isl_dim_map *dim_map_i;
11572 isl_space *space;
11574 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11576 space = isl_reordering_get_space(r);
11577 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
11579 if (!map->p[i])
11580 goto error;
11583 map = isl_map_reset_space(map, isl_reordering_get_space(r));
11584 map = isl_map_unmark_normalized(map);
11586 isl_reordering_free(r);
11587 isl_dim_map_free(dim_map);
11588 return map;
11589 error:
11590 isl_dim_map_free(dim_map);
11591 isl_map_free(map);
11592 isl_reordering_free(r);
11593 return NULL;
11596 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11597 __isl_take isl_reordering *r)
11599 return set_from_map(isl_map_realign(set_to_map(set), r));
11602 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11603 __isl_take isl_space *model)
11605 isl_ctx *ctx;
11606 isl_bool aligned;
11608 if (!map || !model)
11609 goto error;
11611 ctx = isl_space_get_ctx(model);
11612 if (!isl_space_has_named_params(model))
11613 isl_die(ctx, isl_error_invalid,
11614 "model has unnamed parameters", goto error);
11615 if (isl_map_check_named_params(map) < 0)
11616 goto error;
11617 aligned = isl_map_space_has_equal_params(map, model);
11618 if (aligned < 0)
11619 goto error;
11620 if (!aligned) {
11621 isl_reordering *exp;
11623 exp = isl_parameter_alignment_reordering(map->dim, model);
11624 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11625 map = isl_map_realign(map, exp);
11628 isl_space_free(model);
11629 return map;
11630 error:
11631 isl_space_free(model);
11632 isl_map_free(map);
11633 return NULL;
11636 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11637 __isl_take isl_space *model)
11639 return isl_map_align_params(set, model);
11642 /* Align the parameters of "bmap" to those of "model", introducing
11643 * additional parameters if needed.
11645 __isl_give isl_basic_map *isl_basic_map_align_params(
11646 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11648 isl_ctx *ctx;
11649 isl_bool equal_params;
11651 if (!bmap || !model)
11652 goto error;
11654 ctx = isl_space_get_ctx(model);
11655 if (!isl_space_has_named_params(model))
11656 isl_die(ctx, isl_error_invalid,
11657 "model has unnamed parameters", goto error);
11658 if (isl_basic_map_check_named_params(bmap) < 0)
11659 goto error;
11660 equal_params = isl_space_has_equal_params(bmap->dim, model);
11661 if (equal_params < 0)
11662 goto error;
11663 if (!equal_params) {
11664 isl_reordering *exp;
11665 struct isl_dim_map *dim_map;
11667 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11668 exp = isl_reordering_extend_space(exp,
11669 isl_basic_map_get_space(bmap));
11670 dim_map = isl_dim_map_from_reordering(exp);
11671 bmap = isl_basic_map_realign(bmap,
11672 isl_reordering_get_space(exp),
11673 isl_dim_map_extend(dim_map, bmap));
11674 isl_reordering_free(exp);
11675 isl_dim_map_free(dim_map);
11678 isl_space_free(model);
11679 return bmap;
11680 error:
11681 isl_space_free(model);
11682 isl_basic_map_free(bmap);
11683 return NULL;
11686 /* Do "bset" and "space" have the same parameters?
11688 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
11689 __isl_keep isl_space *space)
11691 isl_space *bset_space;
11693 bset_space = isl_basic_set_peek_space(bset);
11694 return isl_space_has_equal_params(bset_space, space);
11697 /* Do "map" and "space" have the same parameters?
11699 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
11700 __isl_keep isl_space *space)
11702 isl_space *map_space;
11704 map_space = isl_map_peek_space(map);
11705 return isl_space_has_equal_params(map_space, space);
11708 /* Do "set" and "space" have the same parameters?
11710 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
11711 __isl_keep isl_space *space)
11713 return isl_map_space_has_equal_params(set_to_map(set), space);
11716 /* Align the parameters of "bset" to those of "model", introducing
11717 * additional parameters if needed.
11719 __isl_give isl_basic_set *isl_basic_set_align_params(
11720 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11722 return isl_basic_map_align_params(bset, model);
11725 /* Drop all parameters not referenced by "map".
11727 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
11729 int i;
11731 if (isl_map_check_named_params(map) < 0)
11732 return isl_map_free(map);
11734 for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
11735 isl_bool involves;
11737 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
11738 if (involves < 0)
11739 return isl_map_free(map);
11740 if (!involves)
11741 map = isl_map_project_out(map, isl_dim_param, i, 1);
11744 return map;
11747 /* Drop all parameters not referenced by "set".
11749 __isl_give isl_set *isl_set_drop_unused_params(
11750 __isl_take isl_set *set)
11752 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
11755 /* Drop all parameters not referenced by "bmap".
11757 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
11758 __isl_take isl_basic_map *bmap)
11760 int i;
11762 if (isl_basic_map_check_named_params(bmap) < 0)
11763 return isl_basic_map_free(bmap);
11765 for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
11766 isl_bool involves;
11768 involves = isl_basic_map_involves_dims(bmap,
11769 isl_dim_param, i, 1);
11770 if (involves < 0)
11771 return isl_basic_map_free(bmap);
11772 if (!involves)
11773 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
11776 return bmap;
11779 /* Drop all parameters not referenced by "bset".
11781 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
11782 __isl_take isl_basic_set *bset)
11784 return bset_from_bmap(isl_basic_map_drop_unused_params(
11785 bset_to_bmap(bset)));
11788 __isl_give isl_mat *isl_basic_map_equalities_matrix(
11789 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11790 enum isl_dim_type c2, enum isl_dim_type c3,
11791 enum isl_dim_type c4, enum isl_dim_type c5)
11793 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11794 struct isl_mat *mat;
11795 int i, j, k;
11796 int pos;
11798 if (!bmap)
11799 return NULL;
11800 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11801 isl_basic_map_total_dim(bmap) + 1);
11802 if (!mat)
11803 return NULL;
11804 for (i = 0; i < bmap->n_eq; ++i)
11805 for (j = 0, pos = 0; j < 5; ++j) {
11806 int off = isl_basic_map_offset(bmap, c[j]);
11807 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11808 isl_int_set(mat->row[i][pos],
11809 bmap->eq[i][off + k]);
11810 ++pos;
11814 return mat;
11817 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11818 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11819 enum isl_dim_type c2, enum isl_dim_type c3,
11820 enum isl_dim_type c4, enum isl_dim_type c5)
11822 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11823 struct isl_mat *mat;
11824 int i, j, k;
11825 int pos;
11827 if (!bmap)
11828 return NULL;
11829 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11830 isl_basic_map_total_dim(bmap) + 1);
11831 if (!mat)
11832 return NULL;
11833 for (i = 0; i < bmap->n_ineq; ++i)
11834 for (j = 0, pos = 0; j < 5; ++j) {
11835 int off = isl_basic_map_offset(bmap, c[j]);
11836 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11837 isl_int_set(mat->row[i][pos],
11838 bmap->ineq[i][off + k]);
11839 ++pos;
11843 return mat;
11846 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11847 __isl_take isl_space *space,
11848 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11849 enum isl_dim_type c2, enum isl_dim_type c3,
11850 enum isl_dim_type c4, enum isl_dim_type c5)
11852 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11853 isl_basic_map *bmap = NULL;
11854 unsigned total;
11855 unsigned extra;
11856 int i, j, k, l;
11857 int pos;
11859 if (!space || !eq || !ineq)
11860 goto error;
11862 if (eq->n_col != ineq->n_col)
11863 isl_die(space->ctx, isl_error_invalid,
11864 "equalities and inequalities matrices should have "
11865 "same number of columns", goto error);
11867 total = 1 + isl_space_dim(space, isl_dim_all);
11869 if (eq->n_col < total)
11870 isl_die(space->ctx, isl_error_invalid,
11871 "number of columns too small", goto error);
11873 extra = eq->n_col - total;
11875 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
11876 eq->n_row, ineq->n_row);
11877 if (!bmap)
11878 goto error;
11879 for (i = 0; i < extra; ++i) {
11880 k = isl_basic_map_alloc_div(bmap);
11881 if (k < 0)
11882 goto error;
11883 isl_int_set_si(bmap->div[k][0], 0);
11885 for (i = 0; i < eq->n_row; ++i) {
11886 l = isl_basic_map_alloc_equality(bmap);
11887 if (l < 0)
11888 goto error;
11889 for (j = 0, pos = 0; j < 5; ++j) {
11890 int off = isl_basic_map_offset(bmap, c[j]);
11891 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11892 isl_int_set(bmap->eq[l][off + k],
11893 eq->row[i][pos]);
11894 ++pos;
11898 for (i = 0; i < ineq->n_row; ++i) {
11899 l = isl_basic_map_alloc_inequality(bmap);
11900 if (l < 0)
11901 goto error;
11902 for (j = 0, pos = 0; j < 5; ++j) {
11903 int off = isl_basic_map_offset(bmap, c[j]);
11904 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11905 isl_int_set(bmap->ineq[l][off + k],
11906 ineq->row[i][pos]);
11907 ++pos;
11912 isl_space_free(space);
11913 isl_mat_free(eq);
11914 isl_mat_free(ineq);
11916 bmap = isl_basic_map_simplify(bmap);
11917 return isl_basic_map_finalize(bmap);
11918 error:
11919 isl_space_free(space);
11920 isl_mat_free(eq);
11921 isl_mat_free(ineq);
11922 isl_basic_map_free(bmap);
11923 return NULL;
11926 __isl_give isl_mat *isl_basic_set_equalities_matrix(
11927 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11928 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11930 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
11931 c1, c2, c3, c4, isl_dim_in);
11934 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
11935 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11936 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11938 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
11939 c1, c2, c3, c4, isl_dim_in);
11942 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
11943 __isl_take isl_space *dim,
11944 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11945 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11947 isl_basic_map *bmap;
11948 bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
11949 c1, c2, c3, c4, isl_dim_in);
11950 return bset_from_bmap(bmap);
11953 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
11955 if (!bmap)
11956 return isl_bool_error;
11958 return isl_space_can_zip(bmap->dim);
11961 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
11963 if (!map)
11964 return isl_bool_error;
11966 return isl_space_can_zip(map->dim);
11969 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
11970 * (A -> C) -> (B -> D).
11972 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
11974 unsigned pos;
11975 unsigned n1;
11976 unsigned n2;
11978 if (!bmap)
11979 return NULL;
11981 if (!isl_basic_map_can_zip(bmap))
11982 isl_die(bmap->ctx, isl_error_invalid,
11983 "basic map cannot be zipped", goto error);
11984 pos = isl_basic_map_offset(bmap, isl_dim_in) +
11985 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
11986 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
11987 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
11988 bmap = isl_basic_map_cow(bmap);
11989 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
11990 if (!bmap)
11991 return NULL;
11992 bmap->dim = isl_space_zip(bmap->dim);
11993 if (!bmap->dim)
11994 goto error;
11995 bmap = isl_basic_map_mark_final(bmap);
11996 return bmap;
11997 error:
11998 isl_basic_map_free(bmap);
11999 return NULL;
12002 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12003 * (A -> C) -> (B -> D).
12005 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12007 int i;
12009 if (!map)
12010 return NULL;
12012 if (!isl_map_can_zip(map))
12013 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12014 goto error);
12016 map = isl_map_cow(map);
12017 if (!map)
12018 return NULL;
12020 for (i = 0; i < map->n; ++i) {
12021 map->p[i] = isl_basic_map_zip(map->p[i]);
12022 if (!map->p[i])
12023 goto error;
12026 map->dim = isl_space_zip(map->dim);
12027 if (!map->dim)
12028 goto error;
12030 return map;
12031 error:
12032 isl_map_free(map);
12033 return NULL;
12036 /* Can we apply isl_basic_map_curry to "bmap"?
12037 * That is, does it have a nested relation in its domain?
12039 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12041 if (!bmap)
12042 return isl_bool_error;
12044 return isl_space_can_curry(bmap->dim);
12047 /* Can we apply isl_map_curry to "map"?
12048 * That is, does it have a nested relation in its domain?
12050 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12052 if (!map)
12053 return isl_bool_error;
12055 return isl_space_can_curry(map->dim);
12058 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12059 * A -> (B -> C).
12061 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12064 if (!bmap)
12065 return NULL;
12067 if (!isl_basic_map_can_curry(bmap))
12068 isl_die(bmap->ctx, isl_error_invalid,
12069 "basic map cannot be curried", goto error);
12070 bmap = isl_basic_map_cow(bmap);
12071 if (!bmap)
12072 return NULL;
12073 bmap->dim = isl_space_curry(bmap->dim);
12074 if (!bmap->dim)
12075 goto error;
12076 bmap = isl_basic_map_mark_final(bmap);
12077 return bmap;
12078 error:
12079 isl_basic_map_free(bmap);
12080 return NULL;
12083 /* Given a map (A -> B) -> C, return the corresponding map
12084 * A -> (B -> C).
12086 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
12088 return isl_map_change_space(map, &isl_map_can_curry,
12089 "map cannot be curried", &isl_space_curry);
12092 /* Can isl_map_range_curry be applied to "map"?
12093 * That is, does it have a nested relation in its range,
12094 * the domain of which is itself a nested relation?
12096 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
12098 if (!map)
12099 return isl_bool_error;
12101 return isl_space_can_range_curry(map->dim);
12104 /* Given a map A -> ((B -> C) -> D), return the corresponding map
12105 * A -> (B -> (C -> D)).
12107 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
12109 return isl_map_change_space(map, &isl_map_can_range_curry,
12110 "map range cannot be curried",
12111 &isl_space_range_curry);
12114 /* Can we apply isl_basic_map_uncurry to "bmap"?
12115 * That is, does it have a nested relation in its domain?
12117 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
12119 if (!bmap)
12120 return isl_bool_error;
12122 return isl_space_can_uncurry(bmap->dim);
12125 /* Can we apply isl_map_uncurry to "map"?
12126 * That is, does it have a nested relation in its domain?
12128 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
12130 if (!map)
12131 return isl_bool_error;
12133 return isl_space_can_uncurry(map->dim);
12136 /* Given a basic map A -> (B -> C), return the corresponding basic map
12137 * (A -> B) -> C.
12139 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
12142 if (!bmap)
12143 return NULL;
12145 if (!isl_basic_map_can_uncurry(bmap))
12146 isl_die(bmap->ctx, isl_error_invalid,
12147 "basic map cannot be uncurried",
12148 return isl_basic_map_free(bmap));
12149 bmap = isl_basic_map_cow(bmap);
12150 if (!bmap)
12151 return NULL;
12152 bmap->dim = isl_space_uncurry(bmap->dim);
12153 if (!bmap->dim)
12154 return isl_basic_map_free(bmap);
12155 bmap = isl_basic_map_mark_final(bmap);
12156 return bmap;
12159 /* Given a map A -> (B -> C), return the corresponding map
12160 * (A -> B) -> C.
12162 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
12164 return isl_map_change_space(map, &isl_map_can_uncurry,
12165 "map cannot be uncurried", &isl_space_uncurry);
12168 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
12169 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12171 return isl_map_equate(set, type1, pos1, type2, pos2);
12174 /* Construct a basic map where the given dimensions are equal to each other.
12176 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
12177 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12179 isl_basic_map *bmap = NULL;
12180 int i;
12182 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12183 isl_space_check_range(space, type2, pos2, 1) < 0)
12184 goto error;
12186 if (type1 == type2 && pos1 == pos2)
12187 return isl_basic_map_universe(space);
12189 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
12190 i = isl_basic_map_alloc_equality(bmap);
12191 if (i < 0)
12192 goto error;
12193 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12194 pos1 += isl_basic_map_offset(bmap, type1);
12195 pos2 += isl_basic_map_offset(bmap, type2);
12196 isl_int_set_si(bmap->eq[i][pos1], -1);
12197 isl_int_set_si(bmap->eq[i][pos2], 1);
12198 bmap = isl_basic_map_finalize(bmap);
12199 isl_space_free(space);
12200 return bmap;
12201 error:
12202 isl_space_free(space);
12203 isl_basic_map_free(bmap);
12204 return NULL;
12207 /* Add a constraint imposing that the given two dimensions are equal.
12209 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
12210 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12212 isl_basic_map *eq;
12214 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12216 bmap = isl_basic_map_intersect(bmap, eq);
12218 return bmap;
12221 /* Add a constraint imposing that the given two dimensions are equal.
12223 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
12224 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12226 isl_basic_map *bmap;
12228 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
12230 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12232 return map;
12235 /* Add a constraint imposing that the given two dimensions have opposite values.
12237 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
12238 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12240 isl_basic_map *bmap = NULL;
12241 int i;
12243 if (isl_map_check_range(map, type1, pos1, 1) < 0)
12244 return isl_map_free(map);
12245 if (isl_map_check_range(map, type2, pos2, 1) < 0)
12246 return isl_map_free(map);
12248 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
12249 i = isl_basic_map_alloc_equality(bmap);
12250 if (i < 0)
12251 goto error;
12252 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12253 pos1 += isl_basic_map_offset(bmap, type1);
12254 pos2 += isl_basic_map_offset(bmap, type2);
12255 isl_int_set_si(bmap->eq[i][pos1], 1);
12256 isl_int_set_si(bmap->eq[i][pos2], 1);
12257 bmap = isl_basic_map_finalize(bmap);
12259 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12261 return map;
12262 error:
12263 isl_basic_map_free(bmap);
12264 isl_map_free(map);
12265 return NULL;
12268 /* Construct a constraint imposing that the value of the first dimension is
12269 * greater than or equal to that of the second.
12271 static __isl_give isl_constraint *constraint_order_ge(
12272 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
12273 enum isl_dim_type type2, int pos2)
12275 isl_constraint *c;
12277 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12278 isl_space_check_range(space, type2, pos2, 1) < 0)
12279 space = isl_space_free(space);
12280 if (!space)
12281 return NULL;
12283 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
12285 if (type1 == type2 && pos1 == pos2)
12286 return c;
12288 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
12289 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
12291 return c;
12294 /* Add a constraint imposing that the value of the first dimension is
12295 * greater than or equal to that of the second.
12297 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
12298 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12300 isl_constraint *c;
12301 isl_space *space;
12303 if (type1 == type2 && pos1 == pos2)
12304 return bmap;
12305 space = isl_basic_map_get_space(bmap);
12306 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12307 bmap = isl_basic_map_add_constraint(bmap, c);
12309 return bmap;
12312 /* Add a constraint imposing that the value of the first dimension is
12313 * greater than or equal to that of the second.
12315 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12316 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12318 isl_constraint *c;
12319 isl_space *space;
12321 if (type1 == type2 && pos1 == pos2)
12322 return map;
12323 space = isl_map_get_space(map);
12324 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12325 map = isl_map_add_constraint(map, c);
12327 return map;
12330 /* Add a constraint imposing that the value of the first dimension is
12331 * less than or equal to that of the second.
12333 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12334 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12336 return isl_map_order_ge(map, type2, pos2, type1, pos1);
12339 /* Construct a basic map where the value of the first dimension is
12340 * greater than that of the second.
12342 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12343 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12345 isl_basic_map *bmap = NULL;
12346 int i;
12348 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12349 isl_space_check_range(space, type2, pos2, 1) < 0)
12350 goto error;
12352 if (type1 == type2 && pos1 == pos2)
12353 return isl_basic_map_empty(space);
12355 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12356 i = isl_basic_map_alloc_inequality(bmap);
12357 if (i < 0)
12358 return isl_basic_map_free(bmap);
12359 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12360 pos1 += isl_basic_map_offset(bmap, type1);
12361 pos2 += isl_basic_map_offset(bmap, type2);
12362 isl_int_set_si(bmap->ineq[i][pos1], 1);
12363 isl_int_set_si(bmap->ineq[i][pos2], -1);
12364 isl_int_set_si(bmap->ineq[i][0], -1);
12365 bmap = isl_basic_map_finalize(bmap);
12367 return bmap;
12368 error:
12369 isl_space_free(space);
12370 isl_basic_map_free(bmap);
12371 return NULL;
12374 /* Add a constraint imposing that the value of the first dimension is
12375 * greater than that of the second.
12377 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12378 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12380 isl_basic_map *gt;
12382 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12384 bmap = isl_basic_map_intersect(bmap, gt);
12386 return bmap;
12389 /* Add a constraint imposing that the value of the first dimension is
12390 * greater than that of the second.
12392 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12393 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12395 isl_basic_map *bmap;
12397 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12399 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12401 return map;
12404 /* Add a constraint imposing that the value of the first dimension is
12405 * smaller than that of the second.
12407 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12408 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12410 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12413 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12414 int pos)
12416 isl_aff *div;
12417 isl_local_space *ls;
12419 if (!bmap)
12420 return NULL;
12422 if (!isl_basic_map_divs_known(bmap))
12423 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12424 "some divs are unknown", return NULL);
12426 ls = isl_basic_map_get_local_space(bmap);
12427 div = isl_local_space_get_div(ls, pos);
12428 isl_local_space_free(ls);
12430 return div;
12433 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12434 int pos)
12436 return isl_basic_map_get_div(bset, pos);
12439 /* Plug in "subs" for dimension "type", "pos" of "bset".
12441 * Let i be the dimension to replace and let "subs" be of the form
12443 * f/d
12445 * Any integer division with a non-zero coefficient for i,
12447 * floor((a i + g)/m)
12449 * is replaced by
12451 * floor((a f + d g)/(m d))
12453 * Constraints of the form
12455 * a i + g
12457 * are replaced by
12459 * a f + d g
12461 * We currently require that "subs" is an integral expression.
12462 * Handling rational expressions may require us to add stride constraints
12463 * as we do in isl_basic_set_preimage_multi_aff.
12465 __isl_give isl_basic_set *isl_basic_set_substitute(
12466 __isl_take isl_basic_set *bset,
12467 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12469 int i;
12470 isl_int v;
12471 isl_ctx *ctx;
12473 if (bset && isl_basic_set_plain_is_empty(bset))
12474 return bset;
12476 bset = isl_basic_set_cow(bset);
12477 if (!bset || !subs)
12478 goto error;
12480 ctx = isl_basic_set_get_ctx(bset);
12481 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12482 isl_die(ctx, isl_error_invalid,
12483 "spaces don't match", goto error);
12484 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12485 isl_die(ctx, isl_error_unsupported,
12486 "cannot handle divs yet", goto error);
12487 if (!isl_int_is_one(subs->v->el[0]))
12488 isl_die(ctx, isl_error_invalid,
12489 "can only substitute integer expressions", goto error);
12491 pos += isl_basic_set_offset(bset, type);
12493 isl_int_init(v);
12495 for (i = 0; i < bset->n_eq; ++i) {
12496 if (isl_int_is_zero(bset->eq[i][pos]))
12497 continue;
12498 isl_int_set(v, bset->eq[i][pos]);
12499 isl_int_set_si(bset->eq[i][pos], 0);
12500 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12501 v, subs->v->el + 1, subs->v->size - 1);
12504 for (i = 0; i < bset->n_ineq; ++i) {
12505 if (isl_int_is_zero(bset->ineq[i][pos]))
12506 continue;
12507 isl_int_set(v, bset->ineq[i][pos]);
12508 isl_int_set_si(bset->ineq[i][pos], 0);
12509 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12510 v, subs->v->el + 1, subs->v->size - 1);
12513 for (i = 0; i < bset->n_div; ++i) {
12514 if (isl_int_is_zero(bset->div[i][1 + pos]))
12515 continue;
12516 isl_int_set(v, bset->div[i][1 + pos]);
12517 isl_int_set_si(bset->div[i][1 + pos], 0);
12518 isl_seq_combine(bset->div[i] + 1,
12519 subs->v->el[0], bset->div[i] + 1,
12520 v, subs->v->el + 1, subs->v->size - 1);
12521 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12524 isl_int_clear(v);
12526 bset = isl_basic_set_simplify(bset);
12527 return isl_basic_set_finalize(bset);
12528 error:
12529 isl_basic_set_free(bset);
12530 return NULL;
12533 /* Plug in "subs" for dimension "type", "pos" of "set".
12535 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12536 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12538 int i;
12540 if (set && isl_set_plain_is_empty(set))
12541 return set;
12543 set = isl_set_cow(set);
12544 if (!set || !subs)
12545 goto error;
12547 for (i = set->n - 1; i >= 0; --i) {
12548 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12549 set = set_from_map(remove_if_empty(set_to_map(set), i));
12550 if (!set)
12551 return NULL;
12554 return set;
12555 error:
12556 isl_set_free(set);
12557 return NULL;
12560 /* Check if the range of "ma" is compatible with the domain or range
12561 * (depending on "type") of "bmap".
12563 static isl_stat check_basic_map_compatible_range_multi_aff(
12564 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12565 __isl_keep isl_multi_aff *ma)
12567 isl_bool m;
12568 isl_space *ma_space;
12570 ma_space = isl_multi_aff_get_space(ma);
12572 m = isl_space_has_equal_params(bmap->dim, ma_space);
12573 if (m < 0)
12574 goto error;
12575 if (!m)
12576 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12577 "parameters don't match", goto error);
12578 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12579 if (m < 0)
12580 goto error;
12581 if (!m)
12582 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12583 "spaces don't match", goto error);
12585 isl_space_free(ma_space);
12586 return isl_stat_ok;
12587 error:
12588 isl_space_free(ma_space);
12589 return isl_stat_error;
12592 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12593 * coefficients before the transformed range of dimensions,
12594 * the "n_after" coefficients after the transformed range of dimensions
12595 * and the coefficients of the other divs in "bmap".
12597 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
12598 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12600 int i;
12601 int n_param;
12602 int n_set;
12603 isl_local_space *ls;
12605 if (n_div == 0)
12606 return bmap;
12608 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
12609 if (!ls)
12610 return isl_basic_map_free(bmap);
12612 n_param = isl_local_space_dim(ls, isl_dim_param);
12613 n_set = isl_local_space_dim(ls, isl_dim_set);
12614 for (i = 0; i < n_div; ++i) {
12615 int o_bmap = 0, o_ls = 0;
12617 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12618 o_bmap += 1 + 1 + n_param;
12619 o_ls += 1 + 1 + n_param;
12620 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12621 o_bmap += n_before;
12622 isl_seq_cpy(bmap->div[i] + o_bmap,
12623 ls->div->row[i] + o_ls, n_set);
12624 o_bmap += n_set;
12625 o_ls += n_set;
12626 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12627 o_bmap += n_after;
12628 isl_seq_cpy(bmap->div[i] + o_bmap,
12629 ls->div->row[i] + o_ls, n_div);
12630 o_bmap += n_div;
12631 o_ls += n_div;
12632 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12633 bmap = isl_basic_map_add_div_constraints(bmap, i);
12634 if (!bmap)
12635 goto error;
12638 isl_local_space_free(ls);
12639 return bmap;
12640 error:
12641 isl_local_space_free(ls);
12642 return isl_basic_map_free(bmap);
12645 /* How many stride constraints does "ma" enforce?
12646 * That is, how many of the affine expressions have a denominator
12647 * different from one?
12649 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12651 int i;
12652 int strides = 0;
12654 for (i = 0; i < ma->n; ++i)
12655 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
12656 strides++;
12658 return strides;
12661 /* For each affine expression in ma of the form
12663 * x_i = (f_i y + h_i)/m_i
12665 * with m_i different from one, add a constraint to "bmap"
12666 * of the form
12668 * f_i y + h_i = m_i alpha_i
12670 * with alpha_i an additional existentially quantified variable.
12672 * The input variables of "ma" correspond to a subset of the variables
12673 * of "bmap". There are "n_before" variables in "bmap" before this
12674 * subset and "n_after" variables after this subset.
12675 * The integer divisions of the affine expressions in "ma" are assumed
12676 * to have been aligned. There are "n_div_ma" of them and
12677 * they appear first in "bmap", straight after the "n_after" variables.
12679 static __isl_give isl_basic_map *add_ma_strides(
12680 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12681 int n_before, int n_after, int n_div_ma)
12683 int i, k;
12684 int div;
12685 int total;
12686 int n_param;
12687 int n_in;
12689 total = isl_basic_map_total_dim(bmap);
12690 n_param = isl_multi_aff_dim(ma, isl_dim_param);
12691 n_in = isl_multi_aff_dim(ma, isl_dim_in);
12692 for (i = 0; i < ma->n; ++i) {
12693 int o_bmap = 0, o_ma = 1;
12695 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
12696 continue;
12697 div = isl_basic_map_alloc_div(bmap);
12698 k = isl_basic_map_alloc_equality(bmap);
12699 if (div < 0 || k < 0)
12700 goto error;
12701 isl_int_set_si(bmap->div[div][0], 0);
12702 isl_seq_cpy(bmap->eq[k] + o_bmap,
12703 ma->u.p[i]->v->el + o_ma, 1 + n_param);
12704 o_bmap += 1 + n_param;
12705 o_ma += 1 + n_param;
12706 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12707 o_bmap += n_before;
12708 isl_seq_cpy(bmap->eq[k] + o_bmap,
12709 ma->u.p[i]->v->el + o_ma, n_in);
12710 o_bmap += n_in;
12711 o_ma += n_in;
12712 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12713 o_bmap += n_after;
12714 isl_seq_cpy(bmap->eq[k] + o_bmap,
12715 ma->u.p[i]->v->el + o_ma, n_div_ma);
12716 o_bmap += n_div_ma;
12717 o_ma += n_div_ma;
12718 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12719 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
12720 total++;
12723 return bmap;
12724 error:
12725 isl_basic_map_free(bmap);
12726 return NULL;
12729 /* Replace the domain or range space (depending on "type) of "space" by "set".
12731 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12732 enum isl_dim_type type, __isl_take isl_space *set)
12734 if (type == isl_dim_in) {
12735 space = isl_space_range(space);
12736 space = isl_space_map_from_domain_and_range(set, space);
12737 } else {
12738 space = isl_space_domain(space);
12739 space = isl_space_map_from_domain_and_range(space, set);
12742 return space;
12745 /* Compute the preimage of the domain or range (depending on "type")
12746 * of "bmap" under the function represented by "ma".
12747 * In other words, plug in "ma" in the domain or range of "bmap".
12748 * The result is a basic map that lives in the same space as "bmap"
12749 * except that the domain or range has been replaced by
12750 * the domain space of "ma".
12752 * If bmap is represented by
12754 * A(p) + S u + B x + T v + C(divs) >= 0,
12756 * where u and x are input and output dimensions if type == isl_dim_out
12757 * while x and v are input and output dimensions if type == isl_dim_in,
12758 * and ma is represented by
12760 * x = D(p) + F(y) + G(divs')
12762 * then the result is
12764 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12766 * The divs in the input set are similarly adjusted.
12767 * In particular
12769 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12771 * becomes
12773 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12774 * B_i G(divs') + c_i(divs))/n_i)
12776 * If bmap is not a rational map and if F(y) involves any denominators
12778 * x_i = (f_i y + h_i)/m_i
12780 * then additional constraints are added to ensure that we only
12781 * map back integer points. That is we enforce
12783 * f_i y + h_i = m_i alpha_i
12785 * with alpha_i an additional existentially quantified variable.
12787 * We first copy over the divs from "ma".
12788 * Then we add the modified constraints and divs from "bmap".
12789 * Finally, we add the stride constraints, if needed.
12791 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12792 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12793 __isl_take isl_multi_aff *ma)
12795 int i, k;
12796 isl_space *space;
12797 isl_basic_map *res = NULL;
12798 int n_before, n_after, n_div_bmap, n_div_ma;
12799 isl_int f, c1, c2, g;
12800 isl_bool rational;
12801 int strides;
12803 isl_int_init(f);
12804 isl_int_init(c1);
12805 isl_int_init(c2);
12806 isl_int_init(g);
12808 ma = isl_multi_aff_align_divs(ma);
12809 if (!bmap || !ma)
12810 goto error;
12811 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12812 goto error;
12814 if (type == isl_dim_in) {
12815 n_before = 0;
12816 n_after = isl_basic_map_dim(bmap, isl_dim_out);
12817 } else {
12818 n_before = isl_basic_map_dim(bmap, isl_dim_in);
12819 n_after = 0;
12821 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12822 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
12824 space = isl_multi_aff_get_domain_space(ma);
12825 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12826 rational = isl_basic_map_is_rational(bmap);
12827 strides = rational ? 0 : multi_aff_strides(ma);
12828 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12829 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12830 if (rational)
12831 res = isl_basic_map_set_rational(res);
12833 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12834 if (isl_basic_map_alloc_div(res) < 0)
12835 goto error;
12837 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
12838 if (!res)
12839 goto error;
12841 for (i = 0; i < bmap->n_eq; ++i) {
12842 k = isl_basic_map_alloc_equality(res);
12843 if (k < 0)
12844 goto error;
12845 if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
12846 n_after, n_div_ma, n_div_bmap,
12847 f, c1, c2, g, 0) < 0)
12848 goto error;
12851 for (i = 0; i < bmap->n_ineq; ++i) {
12852 k = isl_basic_map_alloc_inequality(res);
12853 if (k < 0)
12854 goto error;
12855 if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
12856 n_after, n_div_ma, n_div_bmap,
12857 f, c1, c2, g, 0) < 0)
12858 goto error;
12861 for (i = 0; i < bmap->n_div; ++i) {
12862 if (isl_int_is_zero(bmap->div[i][0])) {
12863 isl_int_set_si(res->div[n_div_ma + i][0], 0);
12864 continue;
12866 if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
12867 n_before, n_after, n_div_ma, n_div_bmap,
12868 f, c1, c2, g, 1) < 0)
12869 goto error;
12872 if (strides)
12873 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
12875 isl_int_clear(f);
12876 isl_int_clear(c1);
12877 isl_int_clear(c2);
12878 isl_int_clear(g);
12879 isl_basic_map_free(bmap);
12880 isl_multi_aff_free(ma);
12881 res = isl_basic_map_simplify(res);
12882 return isl_basic_map_finalize(res);
12883 error:
12884 isl_int_clear(f);
12885 isl_int_clear(c1);
12886 isl_int_clear(c2);
12887 isl_int_clear(g);
12888 isl_basic_map_free(bmap);
12889 isl_multi_aff_free(ma);
12890 isl_basic_map_free(res);
12891 return NULL;
12894 /* Compute the preimage of "bset" under the function represented by "ma".
12895 * In other words, plug in "ma" in "bset". The result is a basic set
12896 * that lives in the domain space of "ma".
12898 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
12899 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
12901 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
12904 /* Compute the preimage of the domain of "bmap" under the function
12905 * represented by "ma".
12906 * In other words, plug in "ma" in the domain of "bmap".
12907 * The result is a basic map that lives in the same space as "bmap"
12908 * except that the domain has been replaced by the domain space of "ma".
12910 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
12911 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12913 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
12916 /* Compute the preimage of the range of "bmap" under the function
12917 * represented by "ma".
12918 * In other words, plug in "ma" in the range of "bmap".
12919 * The result is a basic map that lives in the same space as "bmap"
12920 * except that the range has been replaced by the domain space of "ma".
12922 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
12923 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12925 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
12928 /* Check if the range of "ma" is compatible with the domain or range
12929 * (depending on "type") of "map".
12930 * Return isl_stat_error if anything is wrong.
12932 static isl_stat check_map_compatible_range_multi_aff(
12933 __isl_keep isl_map *map, enum isl_dim_type type,
12934 __isl_keep isl_multi_aff *ma)
12936 isl_bool m;
12937 isl_space *ma_space;
12939 ma_space = isl_multi_aff_get_space(ma);
12940 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
12941 isl_space_free(ma_space);
12942 if (m < 0)
12943 return isl_stat_error;
12944 if (!m)
12945 isl_die(isl_map_get_ctx(map), isl_error_invalid,
12946 "spaces don't match", return isl_stat_error);
12947 return isl_stat_ok;
12950 /* Compute the preimage of the domain or range (depending on "type")
12951 * of "map" under the function represented by "ma".
12952 * In other words, plug in "ma" in the domain or range of "map".
12953 * The result is a map that lives in the same space as "map"
12954 * except that the domain or range has been replaced by
12955 * the domain space of "ma".
12957 * The parameters are assumed to have been aligned.
12959 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
12960 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12962 int i;
12963 isl_space *space;
12965 map = isl_map_cow(map);
12966 ma = isl_multi_aff_align_divs(ma);
12967 if (!map || !ma)
12968 goto error;
12969 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
12970 goto error;
12972 for (i = 0; i < map->n; ++i) {
12973 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
12974 isl_multi_aff_copy(ma));
12975 if (!map->p[i])
12976 goto error;
12979 space = isl_multi_aff_get_domain_space(ma);
12980 space = isl_space_set(isl_map_get_space(map), type, space);
12982 isl_space_free(map->dim);
12983 map->dim = space;
12984 if (!map->dim)
12985 goto error;
12987 isl_multi_aff_free(ma);
12988 if (map->n > 1)
12989 ISL_F_CLR(map, ISL_MAP_DISJOINT);
12990 ISL_F_CLR(map, ISL_SET_NORMALIZED);
12991 return map;
12992 error:
12993 isl_multi_aff_free(ma);
12994 isl_map_free(map);
12995 return NULL;
12998 /* Compute the preimage of the domain or range (depending on "type")
12999 * of "map" under the function represented by "ma".
13000 * In other words, plug in "ma" in the domain or range of "map".
13001 * The result is a map that lives in the same space as "map"
13002 * except that the domain or range has been replaced by
13003 * the domain space of "ma".
13005 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13006 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13008 isl_bool aligned;
13010 if (!map || !ma)
13011 goto error;
13013 aligned = isl_map_space_has_equal_params(map, ma->space);
13014 if (aligned < 0)
13015 goto error;
13016 if (aligned)
13017 return map_preimage_multi_aff(map, type, ma);
13019 if (isl_map_check_named_params(map) < 0)
13020 goto error;
13021 if (!isl_space_has_named_params(ma->space))
13022 isl_die(map->ctx, isl_error_invalid,
13023 "unaligned unnamed parameters", goto error);
13024 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13025 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13027 return map_preimage_multi_aff(map, type, ma);
13028 error:
13029 isl_multi_aff_free(ma);
13030 return isl_map_free(map);
13033 /* Compute the preimage of "set" under the function represented by "ma".
13034 * In other words, plug in "ma" in "set". The result is a set
13035 * that lives in the domain space of "ma".
13037 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13038 __isl_take isl_multi_aff *ma)
13040 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13043 /* Compute the preimage of the domain of "map" under the function
13044 * represented by "ma".
13045 * In other words, plug in "ma" in the domain of "map".
13046 * The result is a map that lives in the same space as "map"
13047 * except that the domain has been replaced by the domain space of "ma".
13049 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13050 __isl_take isl_multi_aff *ma)
13052 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13055 /* Compute the preimage of the range of "map" under the function
13056 * represented by "ma".
13057 * In other words, plug in "ma" in the range of "map".
13058 * The result is a map that lives in the same space as "map"
13059 * except that the range has been replaced by the domain space of "ma".
13061 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13062 __isl_take isl_multi_aff *ma)
13064 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
13067 /* Compute the preimage of "map" under the function represented by "pma".
13068 * In other words, plug in "pma" in the domain or range of "map".
13069 * The result is a map that lives in the same space as "map",
13070 * except that the space of type "type" has been replaced by
13071 * the domain space of "pma".
13073 * The parameters of "map" and "pma" are assumed to have been aligned.
13075 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
13076 __isl_take isl_map *map, enum isl_dim_type type,
13077 __isl_take isl_pw_multi_aff *pma)
13079 int i;
13080 isl_map *res;
13082 if (!pma)
13083 goto error;
13085 if (pma->n == 0) {
13086 isl_pw_multi_aff_free(pma);
13087 res = isl_map_empty(isl_map_get_space(map));
13088 isl_map_free(map);
13089 return res;
13092 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13093 isl_multi_aff_copy(pma->p[0].maff));
13094 if (type == isl_dim_in)
13095 res = isl_map_intersect_domain(res,
13096 isl_map_copy(pma->p[0].set));
13097 else
13098 res = isl_map_intersect_range(res,
13099 isl_map_copy(pma->p[0].set));
13101 for (i = 1; i < pma->n; ++i) {
13102 isl_map *res_i;
13104 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13105 isl_multi_aff_copy(pma->p[i].maff));
13106 if (type == isl_dim_in)
13107 res_i = isl_map_intersect_domain(res_i,
13108 isl_map_copy(pma->p[i].set));
13109 else
13110 res_i = isl_map_intersect_range(res_i,
13111 isl_map_copy(pma->p[i].set));
13112 res = isl_map_union(res, res_i);
13115 isl_pw_multi_aff_free(pma);
13116 isl_map_free(map);
13117 return res;
13118 error:
13119 isl_pw_multi_aff_free(pma);
13120 isl_map_free(map);
13121 return NULL;
13124 /* Compute the preimage of "map" under the function represented by "pma".
13125 * In other words, plug in "pma" in the domain or range of "map".
13126 * The result is a map that lives in the same space as "map",
13127 * except that the space of type "type" has been replaced by
13128 * the domain space of "pma".
13130 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
13131 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
13133 isl_bool aligned;
13135 if (!map || !pma)
13136 goto error;
13138 aligned = isl_map_space_has_equal_params(map, pma->dim);
13139 if (aligned < 0)
13140 goto error;
13141 if (aligned)
13142 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13144 if (isl_map_check_named_params(map) < 0)
13145 goto error;
13146 if (isl_pw_multi_aff_check_named_params(pma) < 0)
13147 goto error;
13148 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
13149 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
13151 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13152 error:
13153 isl_pw_multi_aff_free(pma);
13154 return isl_map_free(map);
13157 /* Compute the preimage of "set" under the function represented by "pma".
13158 * In other words, plug in "pma" in "set". The result is a set
13159 * that lives in the domain space of "pma".
13161 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
13162 __isl_take isl_pw_multi_aff *pma)
13164 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
13167 /* Compute the preimage of the domain of "map" under the function
13168 * represented by "pma".
13169 * In other words, plug in "pma" in the domain of "map".
13170 * The result is a map that lives in the same space as "map",
13171 * except that domain space has been replaced by the domain space of "pma".
13173 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
13174 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13176 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
13179 /* Compute the preimage of the range of "map" under the function
13180 * represented by "pma".
13181 * In other words, plug in "pma" in the range of "map".
13182 * The result is a map that lives in the same space as "map",
13183 * except that range space has been replaced by the domain space of "pma".
13185 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
13186 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13188 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
13191 /* Compute the preimage of "map" under the function represented by "mpa".
13192 * In other words, plug in "mpa" in the domain or range of "map".
13193 * The result is a map that lives in the same space as "map",
13194 * except that the space of type "type" has been replaced by
13195 * the domain space of "mpa".
13197 * If the map does not involve any constraints that refer to the
13198 * dimensions of the substituted space, then the only possible
13199 * effect of "mpa" on the map is to map the space to a different space.
13200 * We create a separate isl_multi_aff to effectuate this change
13201 * in order to avoid spurious splitting of the map along the pieces
13202 * of "mpa".
13203 * If "mpa" has a non-trivial explicit domain, however,
13204 * then the full substitution should be performed.
13206 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
13207 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
13209 int n;
13210 isl_bool full;
13211 isl_pw_multi_aff *pma;
13213 if (!map || !mpa)
13214 goto error;
13216 n = isl_map_dim(map, type);
13217 full = isl_map_involves_dims(map, type, 0, n);
13218 if (full >= 0 && !full)
13219 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
13220 if (full < 0)
13221 goto error;
13222 if (!full) {
13223 isl_space *space;
13224 isl_multi_aff *ma;
13226 space = isl_multi_pw_aff_get_space(mpa);
13227 isl_multi_pw_aff_free(mpa);
13228 ma = isl_multi_aff_zero(space);
13229 return isl_map_preimage_multi_aff(map, type, ma);
13232 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
13233 return isl_map_preimage_pw_multi_aff(map, type, pma);
13234 error:
13235 isl_map_free(map);
13236 isl_multi_pw_aff_free(mpa);
13237 return NULL;
13240 /* Compute the preimage of "map" under the function represented by "mpa".
13241 * In other words, plug in "mpa" in the domain "map".
13242 * The result is a map that lives in the same space as "map",
13243 * except that domain space has been replaced by the domain space of "mpa".
13245 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
13246 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
13248 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
13251 /* Compute the preimage of "set" by the function represented by "mpa".
13252 * In other words, plug in "mpa" in "set".
13254 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
13255 __isl_take isl_multi_pw_aff *mpa)
13257 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
13260 /* Return a copy of the equality constraints of "bset" as a matrix.
13262 __isl_give isl_mat *isl_basic_set_extract_equalities(
13263 __isl_keep isl_basic_set *bset)
13265 isl_ctx *ctx;
13266 unsigned total;
13268 if (!bset)
13269 return NULL;
13271 ctx = isl_basic_set_get_ctx(bset);
13272 total = 1 + isl_basic_set_dim(bset, isl_dim_all);
13273 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
13276 /* Are the "n" "coefficients" starting at "first" of the integer division
13277 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
13278 * to each other?
13279 * The "coefficient" at position 0 is the denominator.
13280 * The "coefficient" at position 1 is the constant term.
13282 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
13283 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
13284 unsigned first, unsigned n)
13286 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
13287 return isl_bool_error;
13288 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
13289 return isl_bool_error;
13290 return isl_seq_eq(bmap1->div[pos1] + first,
13291 bmap2->div[pos2] + first, n);
13294 /* Are the integer division expressions at position "pos1" in "bmap1" and
13295 * "pos2" in "bmap2" equal to each other, except that the constant terms
13296 * are different?
13298 isl_bool isl_basic_map_equal_div_expr_except_constant(
13299 __isl_keep isl_basic_map *bmap1, int pos1,
13300 __isl_keep isl_basic_map *bmap2, int pos2)
13302 isl_bool equal;
13303 unsigned total;
13305 if (!bmap1 || !bmap2)
13306 return isl_bool_error;
13307 total = isl_basic_map_total_dim(bmap1);
13308 if (total != isl_basic_map_total_dim(bmap2))
13309 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
13310 "incomparable div expressions", return isl_bool_error);
13311 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13312 0, 1);
13313 if (equal < 0 || !equal)
13314 return equal;
13315 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13316 1, 1);
13317 if (equal < 0 || equal)
13318 return isl_bool_not(equal);
13319 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13320 2, total);
13323 /* Replace the numerator of the constant term of the integer division
13324 * expression at position "div" in "bmap" by "value".
13325 * The caller guarantees that this does not change the meaning
13326 * of the input.
13328 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
13329 __isl_take isl_basic_map *bmap, int div, int value)
13331 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
13332 return isl_basic_map_free(bmap);
13334 isl_int_set_si(bmap->div[div][1], value);
13336 return bmap;
13339 /* Is the point "inner" internal to inequality constraint "ineq"
13340 * of "bset"?
13341 * The point is considered to be internal to the inequality constraint,
13342 * if it strictly lies on the positive side of the inequality constraint,
13343 * or if it lies on the constraint and the constraint is lexico-positive.
13345 static isl_bool is_internal(__isl_keep isl_vec *inner,
13346 __isl_keep isl_basic_set *bset, int ineq)
13348 isl_ctx *ctx;
13349 int pos;
13350 unsigned total;
13352 if (!inner || !bset)
13353 return isl_bool_error;
13355 ctx = isl_basic_set_get_ctx(bset);
13356 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13357 &ctx->normalize_gcd);
13358 if (!isl_int_is_zero(ctx->normalize_gcd))
13359 return isl_int_is_nonneg(ctx->normalize_gcd);
13361 total = isl_basic_set_dim(bset, isl_dim_all);
13362 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13363 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13366 /* Tighten the inequality constraints of "bset" that are outward with respect
13367 * to the point "vec".
13368 * That is, tighten the constraints that are not satisfied by "vec".
13370 * "vec" is a point internal to some superset S of "bset" that is used
13371 * to make the subsets of S disjoint, by tightening one half of the constraints
13372 * that separate two subsets. In particular, the constraints of S
13373 * are all satisfied by "vec" and should not be tightened.
13374 * Of the internal constraints, those that have "vec" on the outside
13375 * are tightened. The shared facet is included in the adjacent subset
13376 * with the opposite constraint.
13377 * For constraints that saturate "vec", this criterion cannot be used
13378 * to determine which of the two sides should be tightened.
13379 * Instead, the sign of the first non-zero coefficient is used
13380 * to make this choice. Note that this second criterion is never used
13381 * on the constraints of S since "vec" is interior to "S".
13383 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13384 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13386 int j;
13388 bset = isl_basic_set_cow(bset);
13389 if (!bset)
13390 return NULL;
13391 for (j = 0; j < bset->n_ineq; ++j) {
13392 isl_bool internal;
13394 internal = is_internal(vec, bset, j);
13395 if (internal < 0)
13396 return isl_basic_set_free(bset);
13397 if (internal)
13398 continue;
13399 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13402 return bset;
13405 /* Replace the variables x of type "type" starting at "first" in "bmap"
13406 * by x' with x = M x' with M the matrix trans.
13407 * That is, replace the corresponding coefficients c by c M.
13409 * The transformation matrix should be a square matrix.
13411 __isl_give isl_basic_map *isl_basic_map_transform_dims(
13412 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
13413 __isl_take isl_mat *trans)
13415 unsigned pos;
13417 bmap = isl_basic_map_cow(bmap);
13418 if (!bmap || !trans)
13419 goto error;
13421 if (trans->n_row != trans->n_col)
13422 isl_die(trans->ctx, isl_error_invalid,
13423 "expecting square transformation matrix", goto error);
13424 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
13425 goto error;
13427 pos = isl_basic_map_offset(bmap, type) + first;
13429 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
13430 isl_mat_copy(trans)) < 0)
13431 goto error;
13432 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
13433 isl_mat_copy(trans)) < 0)
13434 goto error;
13435 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
13436 isl_mat_copy(trans)) < 0)
13437 goto error;
13439 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
13440 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
13442 isl_mat_free(trans);
13443 return bmap;
13444 error:
13445 isl_mat_free(trans);
13446 isl_basic_map_free(bmap);
13447 return NULL;
13450 /* Replace the variables x of type "type" starting at "first" in "bset"
13451 * by x' with x = M x' with M the matrix trans.
13452 * That is, replace the corresponding coefficients c by c M.
13454 * The transformation matrix should be a square matrix.
13456 __isl_give isl_basic_set *isl_basic_set_transform_dims(
13457 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
13458 __isl_take isl_mat *trans)
13460 return isl_basic_map_transform_dims(bset, type, first, trans);