export isl_set_unwrap
[isl.git] / isl_map.c
blobdb588e20b12c70e128cffe89388db1b2aae1712e
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2014 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
6 * Copyright 2016 INRIA Paris
7 * Copyright 2016 Sven Verdoolaege
8 * Copyright 2018 Cerebras Systems
10 * Use of this software is governed by the MIT license
12 * Written by Sven Verdoolaege, K.U.Leuven, Departement
13 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
14 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
15 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
16 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
17 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
18 * B.P. 105 - 78153 Le Chesnay, France
19 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
20 * CS 42112, 75589 Paris Cedex 12, France
21 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
24 #include <string.h>
25 #include <isl_ctx_private.h>
26 #include <isl_map_private.h>
27 #include <isl_blk.h>
28 #include <isl_id_private.h>
29 #include <isl/constraint.h>
30 #include "isl_space_private.h"
31 #include "isl_equalities.h"
32 #include <isl_lp_private.h>
33 #include <isl_seq.h>
34 #include <isl/set.h>
35 #include <isl/map.h>
36 #include <isl_reordering.h>
37 #include "isl_sample.h"
38 #include <isl_sort.h>
39 #include "isl_tab.h"
40 #include <isl/vec.h>
41 #include <isl_mat_private.h>
42 #include <isl_vec_private.h>
43 #include <isl_dim_map.h>
44 #include <isl_local_space_private.h>
45 #include <isl_aff_private.h>
46 #include <isl_options_private.h>
47 #include <isl_morph.h>
48 #include <isl_val_private.h>
49 #include <isl_printer_private.h>
51 #include <bset_to_bmap.c>
52 #include <bset_from_bmap.c>
53 #include <set_to_map.c>
54 #include <set_from_map.c>
56 /* Treat "bset" as a basic map.
57 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
58 * this function performs a redundant cast.
60 static __isl_keep const isl_basic_map *const_bset_to_bmap(
61 __isl_keep const isl_basic_set *bset)
63 return (const isl_basic_map *) bset;
66 #undef TYPE
67 #define TYPE isl_basic_map
68 #include "has_single_reference_templ.c"
70 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
72 switch (type) {
73 case isl_dim_param: return 1;
74 case isl_dim_in: return 1 + dim->nparam;
75 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
76 default: return 0;
80 isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
81 enum isl_dim_type type)
83 if (!bmap)
84 return isl_size_error;
85 switch (type) {
86 case isl_dim_cst: return 1;
87 case isl_dim_param:
88 case isl_dim_in:
89 case isl_dim_out: return isl_space_dim(bmap->dim, type);
90 case isl_dim_div: return bmap->n_div;
91 case isl_dim_all: return isl_basic_map_total_dim(bmap);
92 default: return 0;
96 /* Return the space of "map".
98 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
100 return map ? map->dim : NULL;
103 /* Return the space of "set".
105 __isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
107 return isl_map_peek_space(set_to_map(set));
110 isl_size isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
112 return isl_space_dim(isl_map_peek_space(map), type);
115 isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
117 return isl_map_dim(set_to_map(set), type);
120 /* Return the position of the variables of the given type
121 * within the sequence of variables of "bmap".
123 isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
124 enum isl_dim_type type)
126 isl_space *space;
128 space = isl_basic_map_peek_space(bmap);
129 if (!space)
130 return isl_size_error;
132 switch (type) {
133 case isl_dim_param:
134 case isl_dim_in:
135 case isl_dim_out: return isl_space_offset(space, type);
136 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
137 case isl_dim_cst:
138 default:
139 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
140 "invalid dimension type", return isl_size_error);
144 /* Return the position of the variables of the given type
145 * within the sequence of variables of "bset".
147 isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
148 enum isl_dim_type type)
150 return isl_basic_map_var_offset(bset_to_bmap(bset), type);
153 /* Return the position of the coefficients of the variables of the given type
154 * within the sequence of coefficients of "bmap".
156 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
157 enum isl_dim_type type)
159 switch (type) {
160 case isl_dim_cst: return 0;
161 case isl_dim_param:
162 case isl_dim_in:
163 case isl_dim_out:
164 case isl_dim_div: return 1 + isl_basic_map_var_offset(bmap, type);
165 default: return 0;
169 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
170 enum isl_dim_type type)
172 return isl_basic_map_offset(bset, type);
175 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
177 return pos(map->dim, type);
180 isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,
181 enum isl_dim_type type)
183 return isl_basic_map_dim(bset, type);
186 isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
188 return isl_basic_set_dim(bset, isl_dim_set);
191 isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
193 return isl_basic_set_dim(bset, isl_dim_param);
196 isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
198 return isl_basic_map_total_dim(const_bset_to_bmap(bset));
201 isl_size isl_set_n_dim(__isl_keep isl_set *set)
203 return isl_set_dim(set, isl_dim_set);
206 isl_size isl_set_n_param(__isl_keep isl_set *set)
208 return isl_set_dim(set, isl_dim_param);
211 isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
213 isl_size dim;
215 if (!bmap)
216 return isl_size_error;
217 dim = isl_space_dim(bmap->dim, isl_dim_all);
218 if (dim < 0)
219 return isl_size_error;
220 return dim + bmap->n_div;
223 /* Return the number of equality constraints in the description of "bmap".
224 * Return -1 on error.
226 int isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
228 if (!bmap)
229 return -1;
230 return bmap->n_eq;
233 /* Return the number of equality constraints in the description of "bset".
234 * Return -1 on error.
236 int isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
238 return isl_basic_map_n_equality(bset_to_bmap(bset));
241 /* Return the number of inequality constraints in the description of "bmap".
242 * Return -1 on error.
244 int isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
246 if (!bmap)
247 return -1;
248 return bmap->n_ineq;
251 /* Return the number of inequality constraints in the description of "bset".
252 * Return -1 on error.
254 int isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
256 return isl_basic_map_n_inequality(bset_to_bmap(bset));
259 /* Do "bmap1" and "bmap2" have the same parameters?
261 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
262 __isl_keep isl_basic_map *bmap2)
264 isl_space *space1, *space2;
266 space1 = isl_basic_map_peek_space(bmap1);
267 space2 = isl_basic_map_peek_space(bmap2);
268 return isl_space_has_equal_params(space1, space2);
271 /* Do "map1" and "map2" have the same parameters?
273 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
274 __isl_keep isl_map *map2)
276 isl_space *space1, *space2;
278 space1 = isl_map_peek_space(map1);
279 space2 = isl_map_peek_space(map2);
280 return isl_space_has_equal_params(space1, space2);
283 /* Do "map" and "set" have the same parameters?
285 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
286 __isl_keep isl_set *set)
288 return isl_map_has_equal_params(map, set_to_map(set));
291 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
292 __isl_keep isl_set *set)
294 isl_bool m;
295 if (!map || !set)
296 return isl_bool_error;
297 m = isl_map_has_equal_params(map, set_to_map(set));
298 if (m < 0 || !m)
299 return m;
300 return isl_space_tuple_is_equal(map->dim, isl_dim_in,
301 set->dim, isl_dim_set);
304 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
305 __isl_keep isl_basic_set *bset)
307 isl_bool m;
308 if (!bmap || !bset)
309 return isl_bool_error;
310 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
311 if (m < 0 || !m)
312 return m;
313 return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
314 bset->dim, isl_dim_set);
317 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
318 __isl_keep isl_set *set)
320 isl_bool m;
321 if (!map || !set)
322 return isl_bool_error;
323 m = isl_map_has_equal_params(map, set_to_map(set));
324 if (m < 0 || !m)
325 return m;
326 return isl_space_tuple_is_equal(map->dim, isl_dim_out,
327 set->dim, isl_dim_set);
330 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
331 __isl_keep isl_basic_set *bset)
333 isl_bool m;
334 if (!bmap || !bset)
335 return isl_bool_error;
336 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
337 if (m < 0 || !m)
338 return m;
339 return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
340 bset->dim, isl_dim_set);
343 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
345 return bmap ? bmap->ctx : NULL;
348 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
350 return bset ? bset->ctx : NULL;
353 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
355 return map ? map->ctx : NULL;
358 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
360 return set ? set->ctx : NULL;
363 /* Return the space of "bmap".
365 __isl_keep isl_space *isl_basic_map_peek_space(
366 __isl_keep const isl_basic_map *bmap)
368 return bmap ? bmap->dim : NULL;
371 /* Return the space of "bset".
373 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
375 return isl_basic_map_peek_space(bset_to_bmap(bset));
378 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
380 return isl_space_copy(isl_basic_map_peek_space(bmap));
383 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
385 return isl_basic_map_get_space(bset_to_bmap(bset));
388 /* Extract the divs in "bmap" as a matrix.
390 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
392 int i;
393 isl_ctx *ctx;
394 isl_mat *div;
395 isl_size v_div;
396 unsigned cols;
398 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
399 if (v_div < 0)
400 return NULL;
402 ctx = isl_basic_map_get_ctx(bmap);
403 cols = 1 + 1 + v_div + bmap->n_div;
404 div = isl_mat_alloc(ctx, bmap->n_div, cols);
405 if (!div)
406 return NULL;
408 for (i = 0; i < bmap->n_div; ++i)
409 isl_seq_cpy(div->row[i], bmap->div[i], cols);
411 return div;
414 /* Extract the divs in "bset" as a matrix.
416 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
418 return isl_basic_map_get_divs(bset);
421 __isl_give isl_local_space *isl_basic_map_get_local_space(
422 __isl_keep isl_basic_map *bmap)
424 isl_mat *div;
426 if (!bmap)
427 return NULL;
429 div = isl_basic_map_get_divs(bmap);
430 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
433 __isl_give isl_local_space *isl_basic_set_get_local_space(
434 __isl_keep isl_basic_set *bset)
436 return isl_basic_map_get_local_space(bset);
439 /* For each known div d = floor(f/m), add the constraints
441 * f - m d >= 0
442 * -(f-(m-1)) + m d >= 0
444 * Do not finalize the result.
446 static __isl_give isl_basic_map *add_known_div_constraints(
447 __isl_take isl_basic_map *bmap)
449 int i;
450 isl_size n_div;
452 n_div = isl_basic_map_dim(bmap, isl_dim_div);
453 if (n_div < 0)
454 return isl_basic_map_free(bmap);
455 if (n_div == 0)
456 return bmap;
457 bmap = isl_basic_map_cow(bmap);
458 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
459 if (!bmap)
460 return NULL;
461 for (i = 0; i < n_div; ++i) {
462 if (isl_int_is_zero(bmap->div[i][0]))
463 continue;
464 bmap = isl_basic_map_add_div_constraints(bmap, i);
467 return bmap;
470 __isl_give isl_basic_map *isl_basic_map_from_local_space(
471 __isl_take isl_local_space *ls)
473 int i;
474 isl_size n_div;
475 isl_basic_map *bmap;
477 n_div = isl_local_space_dim(ls, isl_dim_div);
478 if (n_div < 0)
479 ls = isl_local_space_free(ls);
480 if (!ls)
481 return NULL;
483 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
484 n_div, 0, 2 * n_div);
486 for (i = 0; i < n_div; ++i)
487 if (isl_basic_map_alloc_div(bmap) < 0)
488 goto error;
490 for (i = 0; i < n_div; ++i)
491 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
492 bmap = add_known_div_constraints(bmap);
494 isl_local_space_free(ls);
495 return bmap;
496 error:
497 isl_local_space_free(ls);
498 isl_basic_map_free(bmap);
499 return NULL;
502 __isl_give isl_basic_set *isl_basic_set_from_local_space(
503 __isl_take isl_local_space *ls)
505 return isl_basic_map_from_local_space(ls);
508 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
510 return isl_space_copy(isl_map_peek_space(map));
513 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
515 if (!set)
516 return NULL;
517 return isl_space_copy(set->dim);
520 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
521 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
523 bmap = isl_basic_map_cow(bmap);
524 if (!bmap)
525 return NULL;
526 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
527 if (!bmap->dim)
528 goto error;
529 bmap = isl_basic_map_finalize(bmap);
530 return bmap;
531 error:
532 isl_basic_map_free(bmap);
533 return NULL;
536 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
537 __isl_take isl_basic_set *bset, const char *s)
539 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
542 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
543 enum isl_dim_type type)
545 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
548 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
549 enum isl_dim_type type, const char *s)
551 int i;
553 map = isl_map_cow(map);
554 if (!map)
555 return NULL;
557 map->dim = isl_space_set_tuple_name(map->dim, type, s);
558 if (!map->dim)
559 goto error;
561 for (i = 0; i < map->n; ++i) {
562 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
563 if (!map->p[i])
564 goto error;
567 return map;
568 error:
569 isl_map_free(map);
570 return NULL;
573 /* Replace the identifier of the tuple of type "type" by "id".
575 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
576 __isl_take isl_basic_map *bmap,
577 enum isl_dim_type type, __isl_take isl_id *id)
579 bmap = isl_basic_map_cow(bmap);
580 if (!bmap)
581 goto error;
582 bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
583 if (!bmap->dim)
584 return isl_basic_map_free(bmap);
585 bmap = isl_basic_map_finalize(bmap);
586 return bmap;
587 error:
588 isl_id_free(id);
589 return NULL;
592 /* Replace the identifier of the tuple by "id".
594 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
595 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
597 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
600 /* Does the input or output tuple have a name?
602 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
604 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
607 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
608 enum isl_dim_type type)
610 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
613 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
614 const char *s)
616 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
617 isl_dim_set, s));
620 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
621 enum isl_dim_type type, __isl_take isl_id *id)
623 map = isl_map_cow(map);
624 if (!map)
625 goto error;
627 map->dim = isl_space_set_tuple_id(map->dim, type, id);
629 return isl_map_reset_space(map, isl_space_copy(map->dim));
630 error:
631 isl_id_free(id);
632 return NULL;
635 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
636 __isl_take isl_id *id)
638 return isl_map_set_tuple_id(set, isl_dim_set, id);
641 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
642 enum isl_dim_type type)
644 map = isl_map_cow(map);
645 if (!map)
646 return NULL;
648 map->dim = isl_space_reset_tuple_id(map->dim, type);
650 return isl_map_reset_space(map, isl_space_copy(map->dim));
653 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
655 return isl_map_reset_tuple_id(set, isl_dim_set);
658 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
660 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
663 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
664 enum isl_dim_type type)
666 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
669 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
671 return isl_map_has_tuple_id(set, isl_dim_set);
674 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
676 return isl_map_get_tuple_id(set, isl_dim_set);
679 /* Does the set tuple have a name?
681 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
683 if (!set)
684 return isl_bool_error;
685 return isl_space_has_tuple_name(set->dim, isl_dim_set);
689 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
691 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
694 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
696 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
699 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
700 enum isl_dim_type type, unsigned pos)
702 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
705 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
706 enum isl_dim_type type, unsigned pos)
708 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
711 /* Does the given dimension have a name?
713 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
714 enum isl_dim_type type, unsigned pos)
716 if (!map)
717 return isl_bool_error;
718 return isl_space_has_dim_name(map->dim, type, pos);
721 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
722 enum isl_dim_type type, unsigned pos)
724 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
727 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
728 enum isl_dim_type type, unsigned pos)
730 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
733 /* Does the given dimension have a name?
735 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
736 enum isl_dim_type type, unsigned pos)
738 if (!set)
739 return isl_bool_error;
740 return isl_space_has_dim_name(set->dim, type, pos);
743 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
744 __isl_take isl_basic_map *bmap,
745 enum isl_dim_type type, unsigned pos, const char *s)
747 bmap = isl_basic_map_cow(bmap);
748 if (!bmap)
749 return NULL;
750 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
751 if (!bmap->dim)
752 goto error;
753 return isl_basic_map_finalize(bmap);
754 error:
755 isl_basic_map_free(bmap);
756 return NULL;
759 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
760 enum isl_dim_type type, unsigned pos, const char *s)
762 int i;
764 map = isl_map_cow(map);
765 if (!map)
766 return NULL;
768 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
769 if (!map->dim)
770 goto error;
772 for (i = 0; i < map->n; ++i) {
773 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
774 if (!map->p[i])
775 goto error;
778 return map;
779 error:
780 isl_map_free(map);
781 return NULL;
784 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
785 __isl_take isl_basic_set *bset,
786 enum isl_dim_type type, unsigned pos, const char *s)
788 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
789 type, pos, s));
792 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
793 enum isl_dim_type type, unsigned pos, const char *s)
795 return set_from_map(isl_map_set_dim_name(set_to_map(set),
796 type, pos, s));
799 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
800 enum isl_dim_type type, unsigned pos)
802 if (!bmap)
803 return isl_bool_error;
804 return isl_space_has_dim_id(bmap->dim, type, pos);
807 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
808 enum isl_dim_type type, unsigned pos)
810 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
813 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
814 enum isl_dim_type type, unsigned pos)
816 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
819 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
820 enum isl_dim_type type, unsigned pos)
822 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
825 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
826 enum isl_dim_type type, unsigned pos)
828 return isl_map_has_dim_id(set, type, pos);
831 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
832 enum isl_dim_type type, unsigned pos)
834 return isl_map_get_dim_id(set, type, pos);
837 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
838 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
840 map = isl_map_cow(map);
841 if (!map)
842 goto error;
844 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
846 return isl_map_reset_space(map, isl_space_copy(map->dim));
847 error:
848 isl_id_free(id);
849 return NULL;
852 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
853 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
855 return isl_map_set_dim_id(set, type, pos, id);
858 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
859 __isl_keep isl_id *id)
861 if (!map)
862 return -1;
863 return isl_space_find_dim_by_id(map->dim, type, id);
866 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
867 __isl_keep isl_id *id)
869 return isl_map_find_dim_by_id(set, type, id);
872 /* Return the position of the dimension of the given type and name
873 * in "bmap".
874 * Return -1 if no such dimension can be found.
876 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
877 enum isl_dim_type type, const char *name)
879 if (!bmap)
880 return -1;
881 return isl_space_find_dim_by_name(bmap->dim, type, name);
884 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
885 const char *name)
887 if (!map)
888 return -1;
889 return isl_space_find_dim_by_name(map->dim, type, name);
892 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
893 const char *name)
895 return isl_map_find_dim_by_name(set, type, name);
898 /* Check whether equality i of bset is a pure stride constraint
899 * on a single dimension, i.e., of the form
901 * v = k e
903 * with k a constant and e an existentially quantified variable.
905 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
907 isl_size nparam;
908 isl_size d;
909 isl_size n_div;
910 int pos1;
911 int pos2;
913 nparam = isl_basic_set_dim(bset, isl_dim_param);
914 d = isl_basic_set_dim(bset, isl_dim_set);
915 n_div = isl_basic_set_dim(bset, isl_dim_div);
916 if (nparam < 0 || d < 0 || n_div < 0)
917 return isl_bool_error;
919 if (!isl_int_is_zero(bset->eq[i][0]))
920 return isl_bool_false;
922 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
923 return isl_bool_false;
924 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
925 if (pos1 == -1)
926 return isl_bool_false;
927 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
928 d - pos1 - 1) != -1)
929 return isl_bool_false;
931 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
932 if (pos2 == -1)
933 return isl_bool_false;
934 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
935 n_div - pos2 - 1) != -1)
936 return isl_bool_false;
937 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
938 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
939 return isl_bool_false;
941 return isl_bool_true;
944 /* Reset the user pointer on all identifiers of parameters and tuples
945 * of the space of "map".
947 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
949 isl_space *space;
951 space = isl_map_get_space(map);
952 space = isl_space_reset_user(space);
953 map = isl_map_reset_space(map, space);
955 return map;
958 /* Reset the user pointer on all identifiers of parameters and tuples
959 * of the space of "set".
961 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
963 return isl_map_reset_user(set);
966 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
968 if (!bmap)
969 return isl_bool_error;
970 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
973 /* Has "map" been marked as a rational map?
974 * In particular, have all basic maps in "map" been marked this way?
975 * An empty map is not considered to be rational.
976 * Maps where only some of the basic maps are marked rational
977 * are not allowed.
979 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
981 int i;
982 isl_bool rational;
984 if (!map)
985 return isl_bool_error;
986 if (map->n == 0)
987 return isl_bool_false;
988 rational = isl_basic_map_is_rational(map->p[0]);
989 if (rational < 0)
990 return rational;
991 for (i = 1; i < map->n; ++i) {
992 isl_bool rational_i;
994 rational_i = isl_basic_map_is_rational(map->p[i]);
995 if (rational_i < 0)
996 return rational_i;
997 if (rational != rational_i)
998 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
999 "mixed rational and integer basic maps "
1000 "not supported", return isl_bool_error);
1003 return rational;
1006 /* Has "set" been marked as a rational set?
1007 * In particular, have all basic set in "set" been marked this way?
1008 * An empty set is not considered to be rational.
1009 * Sets where only some of the basic sets are marked rational
1010 * are not allowed.
1012 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1014 return isl_map_is_rational(set);
1017 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1019 return isl_basic_map_is_rational(bset);
1022 /* Does "bmap" contain any rational points?
1024 * If "bmap" has an equality for each dimension, equating the dimension
1025 * to an integer constant, then it has no rational points, even if it
1026 * is marked as rational.
1028 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1030 isl_bool has_rational = isl_bool_true;
1031 isl_size total;
1033 if (!bmap)
1034 return isl_bool_error;
1035 if (isl_basic_map_plain_is_empty(bmap))
1036 return isl_bool_false;
1037 if (!isl_basic_map_is_rational(bmap))
1038 return isl_bool_false;
1039 bmap = isl_basic_map_copy(bmap);
1040 bmap = isl_basic_map_implicit_equalities(bmap);
1041 total = isl_basic_map_dim(bmap, isl_dim_all);
1042 if (total < 0)
1043 return isl_bool_error;
1044 if (bmap->n_eq == total) {
1045 int i, j;
1046 for (i = 0; i < bmap->n_eq; ++i) {
1047 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1048 if (j < 0)
1049 break;
1050 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1051 !isl_int_is_negone(bmap->eq[i][1 + j]))
1052 break;
1053 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1054 total - j - 1);
1055 if (j >= 0)
1056 break;
1058 if (i == bmap->n_eq)
1059 has_rational = isl_bool_false;
1061 isl_basic_map_free(bmap);
1063 return has_rational;
1066 /* Does "map" contain any rational points?
1068 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1070 int i;
1071 isl_bool has_rational;
1073 if (!map)
1074 return isl_bool_error;
1075 for (i = 0; i < map->n; ++i) {
1076 has_rational = isl_basic_map_has_rational(map->p[i]);
1077 if (has_rational < 0 || has_rational)
1078 return has_rational;
1080 return isl_bool_false;
1083 /* Does "set" contain any rational points?
1085 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1087 return isl_map_has_rational(set);
1090 /* Is this basic set a parameter domain?
1092 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1094 if (!bset)
1095 return isl_bool_error;
1096 return isl_space_is_params(bset->dim);
1099 /* Is this set a parameter domain?
1101 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1103 if (!set)
1104 return isl_bool_error;
1105 return isl_space_is_params(set->dim);
1108 /* Is this map actually a parameter domain?
1109 * Users should never call this function. Outside of isl,
1110 * a map can never be a parameter domain.
1112 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1114 if (!map)
1115 return isl_bool_error;
1116 return isl_space_is_params(map->dim);
1119 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1120 __isl_take isl_basic_map *bmap, unsigned extra,
1121 unsigned n_eq, unsigned n_ineq)
1123 int i;
1124 isl_space *space = isl_basic_map_peek_space(bmap);
1125 isl_size n_var = isl_space_dim(space, isl_dim_all);
1126 size_t row_size = 1 + n_var + extra;
1128 bmap->ctx = ctx;
1129 isl_ctx_ref(ctx);
1131 if (n_var < 0)
1132 return isl_basic_map_free(bmap);
1134 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1135 if (isl_blk_is_error(bmap->block))
1136 goto error;
1138 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1139 if ((n_ineq + n_eq) && !bmap->ineq)
1140 goto error;
1142 if (extra == 0) {
1143 bmap->block2 = isl_blk_empty();
1144 bmap->div = NULL;
1145 } else {
1146 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1147 if (isl_blk_is_error(bmap->block2))
1148 goto error;
1150 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1151 if (!bmap->div)
1152 goto error;
1155 for (i = 0; i < n_ineq + n_eq; ++i)
1156 bmap->ineq[i] = bmap->block.data + i * row_size;
1158 for (i = 0; i < extra; ++i)
1159 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1161 bmap->ref = 1;
1162 bmap->flags = 0;
1163 bmap->c_size = n_eq + n_ineq;
1164 bmap->eq = bmap->ineq + n_ineq;
1165 bmap->extra = extra;
1166 bmap->n_eq = 0;
1167 bmap->n_ineq = 0;
1168 bmap->n_div = 0;
1169 bmap->sample = NULL;
1171 return bmap;
1172 error:
1173 isl_basic_map_free(bmap);
1174 return NULL;
1177 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1178 unsigned nparam, unsigned dim, unsigned extra,
1179 unsigned n_eq, unsigned n_ineq)
1181 struct isl_basic_map *bmap;
1182 isl_space *space;
1184 space = isl_space_set_alloc(ctx, nparam, dim);
1185 if (!space)
1186 return NULL;
1188 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1189 return bset_from_bmap(bmap);
1192 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1193 unsigned extra, unsigned n_eq, unsigned n_ineq)
1195 struct isl_basic_map *bmap;
1196 if (!dim)
1197 return NULL;
1198 isl_assert(dim->ctx, dim->n_in == 0, goto error);
1199 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1200 return bset_from_bmap(bmap);
1201 error:
1202 isl_space_free(dim);
1203 return NULL;
1206 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1207 unsigned extra, unsigned n_eq, unsigned n_ineq)
1209 struct isl_basic_map *bmap;
1211 if (!space)
1212 return NULL;
1213 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1214 if (!bmap)
1215 goto error;
1216 bmap->dim = space;
1218 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1219 error:
1220 isl_space_free(space);
1221 return NULL;
1224 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1225 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1226 unsigned n_eq, unsigned n_ineq)
1228 struct isl_basic_map *bmap;
1229 isl_space *dim;
1231 dim = isl_space_alloc(ctx, nparam, in, out);
1232 if (!dim)
1233 return NULL;
1235 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1236 return bmap;
1239 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1240 __isl_keep isl_basic_map *src)
1242 int i;
1243 isl_size total = isl_basic_map_dim(src, isl_dim_all);
1245 if (!dst || total < 0)
1246 return isl_basic_map_free(dst);
1248 for (i = 0; i < src->n_eq; ++i) {
1249 int j = isl_basic_map_alloc_equality(dst);
1250 if (j < 0)
1251 return isl_basic_map_free(dst);
1252 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1255 for (i = 0; i < src->n_ineq; ++i) {
1256 int j = isl_basic_map_alloc_inequality(dst);
1257 if (j < 0)
1258 return isl_basic_map_free(dst);
1259 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1262 for (i = 0; i < src->n_div; ++i) {
1263 int j = isl_basic_map_alloc_div(dst);
1264 if (j < 0)
1265 return isl_basic_map_free(dst);
1266 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1268 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1269 return dst;
1272 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1274 struct isl_basic_map *dup;
1276 if (!bmap)
1277 return NULL;
1278 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1279 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1280 dup = dup_constraints(dup, bmap);
1281 if (!dup)
1282 return NULL;
1283 dup->flags = bmap->flags;
1284 dup->sample = isl_vec_copy(bmap->sample);
1285 return dup;
1288 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1290 struct isl_basic_map *dup;
1292 dup = isl_basic_map_dup(bset_to_bmap(bset));
1293 return bset_from_bmap(dup);
1296 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1298 if (!bset)
1299 return NULL;
1301 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1302 bset->ref++;
1303 return bset;
1305 return isl_basic_set_dup(bset);
1308 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1310 if (!set)
1311 return NULL;
1313 set->ref++;
1314 return set;
1317 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1319 if (!bmap)
1320 return NULL;
1322 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1323 bmap->ref++;
1324 return bmap;
1326 bmap = isl_basic_map_dup(bmap);
1327 if (bmap)
1328 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1329 return bmap;
1332 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1334 if (!map)
1335 return NULL;
1337 map->ref++;
1338 return map;
1341 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1343 if (!bmap)
1344 return NULL;
1346 if (--bmap->ref > 0)
1347 return NULL;
1349 isl_ctx_deref(bmap->ctx);
1350 free(bmap->div);
1351 isl_blk_free(bmap->ctx, bmap->block2);
1352 free(bmap->ineq);
1353 isl_blk_free(bmap->ctx, bmap->block);
1354 isl_vec_free(bmap->sample);
1355 isl_space_free(bmap->dim);
1356 free(bmap);
1358 return NULL;
1361 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1363 return isl_basic_map_free(bset_to_bmap(bset));
1366 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1368 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1371 /* Check that "bset" does not involve any parameters.
1373 isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1375 isl_size nparam;
1377 nparam = isl_basic_set_dim(bset, isl_dim_param);
1378 if (nparam < 0)
1379 return isl_stat_error;
1380 if (nparam != 0)
1381 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1382 "basic set should not have any parameters",
1383 return isl_stat_error);
1384 return isl_stat_ok;
1387 /* Check that "bset" does not involve any local variables.
1389 isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1391 isl_size n_div;
1393 n_div = isl_basic_set_dim(bset, isl_dim_div);
1394 if (n_div < 0)
1395 return isl_stat_error;
1396 if (n_div != 0)
1397 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1398 "basic set should not have any local variables",
1399 return isl_stat_error);
1400 return isl_stat_ok;
1403 /* Check that "map" has only named parameters, reporting an error
1404 * if it does not.
1406 isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1408 return isl_space_check_named_params(isl_map_peek_space(map));
1411 /* Check that "bmap" has only named parameters, reporting an error
1412 * if it does not.
1414 static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
1416 return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
1419 /* Check that "bmap1" and "bmap2" have the same parameters,
1420 * reporting an error if they do not.
1422 static isl_stat isl_basic_map_check_equal_params(
1423 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1425 isl_bool match;
1427 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1428 if (match < 0)
1429 return isl_stat_error;
1430 if (!match)
1431 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1432 "parameters don't match", return isl_stat_error);
1433 return isl_stat_ok;
1436 __isl_give isl_map *isl_map_align_params_map_map_and(
1437 __isl_take isl_map *map1, __isl_take isl_map *map2,
1438 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1439 __isl_take isl_map *map2))
1441 if (!map1 || !map2)
1442 goto error;
1443 if (isl_map_has_equal_params(map1, map2))
1444 return fn(map1, map2);
1445 if (isl_map_check_named_params(map1) < 0)
1446 goto error;
1447 if (isl_map_check_named_params(map2) < 0)
1448 goto error;
1449 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1450 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1451 return fn(map1, map2);
1452 error:
1453 isl_map_free(map1);
1454 isl_map_free(map2);
1455 return NULL;
1458 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1459 __isl_keep isl_map *map2,
1460 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1462 isl_bool r;
1464 if (!map1 || !map2)
1465 return isl_bool_error;
1466 if (isl_map_has_equal_params(map1, map2))
1467 return fn(map1, map2);
1468 if (isl_map_check_named_params(map1) < 0)
1469 return isl_bool_error;
1470 if (isl_map_check_named_params(map2) < 0)
1471 return isl_bool_error;
1472 map1 = isl_map_copy(map1);
1473 map2 = isl_map_copy(map2);
1474 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1475 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1476 r = fn(map1, map2);
1477 isl_map_free(map1);
1478 isl_map_free(map2);
1479 return r;
1482 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1484 isl_size total;
1485 struct isl_ctx *ctx;
1487 total = isl_basic_map_dim(bmap, isl_dim_all);
1488 if (total < 0)
1489 return -1;
1490 ctx = bmap->ctx;
1491 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1492 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1493 return -1);
1494 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1495 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1496 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1497 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1498 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1499 isl_int *t;
1500 int j = isl_basic_map_alloc_inequality(bmap);
1501 if (j < 0)
1502 return -1;
1503 t = bmap->ineq[j];
1504 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1505 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1506 bmap->eq[-1] = t;
1507 bmap->n_eq++;
1508 bmap->n_ineq--;
1509 bmap->eq--;
1510 return 0;
1512 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + total,
1513 bmap->extra - bmap->n_div);
1514 return bmap->n_eq++;
1517 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1519 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1522 __isl_give isl_basic_map *isl_basic_map_free_equality(
1523 __isl_take isl_basic_map *bmap, unsigned n)
1525 if (!bmap)
1526 return NULL;
1527 if (n > bmap->n_eq)
1528 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1529 "invalid number of equalities",
1530 isl_basic_map_free(bmap));
1531 bmap->n_eq -= n;
1532 return bmap;
1535 __isl_give isl_basic_set *isl_basic_set_free_equality(
1536 __isl_take isl_basic_set *bset, unsigned n)
1538 return bset_from_bmap(isl_basic_map_free_equality(bset_to_bmap(bset),
1539 n));
1542 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1544 isl_int *t;
1545 if (!bmap)
1546 return -1;
1547 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1549 if (pos != bmap->n_eq - 1) {
1550 t = bmap->eq[pos];
1551 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1552 bmap->eq[bmap->n_eq - 1] = t;
1554 bmap->n_eq--;
1555 return 0;
1558 /* Turn inequality "pos" of "bmap" into an equality.
1560 * In particular, we move the inequality in front of the equalities
1561 * and move the last inequality in the position of the moved inequality.
1562 * Note that isl_tab_make_equalities_explicit depends on this particular
1563 * change in the ordering of the constraints.
1565 void isl_basic_map_inequality_to_equality(
1566 struct isl_basic_map *bmap, unsigned pos)
1568 isl_int *t;
1570 t = bmap->ineq[pos];
1571 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1572 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1573 bmap->eq[-1] = t;
1574 bmap->n_eq++;
1575 bmap->n_ineq--;
1576 bmap->eq--;
1577 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1578 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1579 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1580 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1583 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1585 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1588 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1590 isl_size total;
1591 struct isl_ctx *ctx;
1593 total = isl_basic_map_dim(bmap, isl_dim_all);
1594 if (total < 0)
1595 return -1;
1596 ctx = bmap->ctx;
1597 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1598 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1599 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1600 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1601 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1602 isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1 + total,
1603 bmap->extra - bmap->n_div);
1604 return bmap->n_ineq++;
1607 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1609 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1612 __isl_give isl_basic_map *isl_basic_map_free_inequality(
1613 __isl_take isl_basic_map *bmap, unsigned n)
1615 if (!bmap)
1616 return NULL;
1617 if (n > bmap->n_ineq)
1618 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1619 "invalid number of inequalities",
1620 return isl_basic_map_free(bmap));
1621 bmap->n_ineq -= n;
1622 return bmap;
1625 __isl_give isl_basic_set *isl_basic_set_free_inequality(
1626 __isl_take isl_basic_set *bset, unsigned n)
1628 return bset_from_bmap(isl_basic_map_free_inequality(bset_to_bmap(bset),
1629 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 isl_size total;
1659 int k;
1661 empty = isl_basic_map_plain_is_empty(bmap);
1662 if (empty < 0)
1663 return isl_basic_map_free(bmap);
1664 if (empty)
1665 return bmap;
1667 bmap = isl_basic_map_cow(bmap);
1668 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1669 total = isl_basic_map_dim(bmap, isl_dim_all);
1670 if (total < 0)
1671 return isl_basic_map_free(bmap);
1672 k = isl_basic_map_alloc_equality(bmap);
1673 if (k < 0)
1674 goto error;
1675 isl_seq_cpy(bmap->eq[k], eq, 1 + total);
1676 return bmap;
1677 error:
1678 isl_basic_map_free(bmap);
1679 return NULL;
1682 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1683 isl_int *eq)
1685 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1688 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1689 isl_int *ineq)
1691 isl_size total;
1692 int k;
1694 bmap = isl_basic_map_cow(bmap);
1695 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1696 total = isl_basic_map_dim(bmap, isl_dim_all);
1697 if (total < 0)
1698 return isl_basic_map_free(bmap);
1699 k = isl_basic_map_alloc_inequality(bmap);
1700 if (k < 0)
1701 goto error;
1702 isl_seq_cpy(bmap->ineq[k], ineq, 1 + total);
1703 return bmap;
1704 error:
1705 isl_basic_map_free(bmap);
1706 return NULL;
1709 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1710 isl_int *ineq)
1712 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1715 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1717 isl_size total;
1719 total = isl_basic_map_dim(bmap, isl_dim_all);
1720 if (total < 0)
1721 return -1;
1722 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1723 isl_seq_clr(bmap->div[bmap->n_div] + 1 + 1 + total,
1724 bmap->extra - bmap->n_div);
1725 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1726 return bmap->n_div++;
1729 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1731 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1734 #undef TYPE
1735 #define TYPE isl_basic_map
1736 #include "check_type_range_templ.c"
1738 /* Check that there are "n" dimensions of type "type" starting at "first"
1739 * in "bset".
1741 isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1742 enum isl_dim_type type, unsigned first, unsigned n)
1744 return isl_basic_map_check_range(bset_to_bmap(bset),
1745 type, first, n);
1748 /* Insert an extra integer division, prescribed by "div", to "bmap"
1749 * at (integer division) position "pos".
1751 * The integer division is first added at the end and then moved
1752 * into the right position.
1754 __isl_give isl_basic_map *isl_basic_map_insert_div(
1755 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1757 int i, k;
1758 isl_size total;
1760 bmap = isl_basic_map_cow(bmap);
1761 total = isl_basic_map_dim(bmap, isl_dim_all);
1762 if (total < 0 || !div)
1763 return isl_basic_map_free(bmap);
1765 if (div->size != 1 + 1 + total)
1766 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1767 "unexpected size", return isl_basic_map_free(bmap));
1768 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1769 return isl_basic_map_free(bmap);
1771 bmap = isl_basic_map_extend_space(bmap,
1772 isl_basic_map_get_space(bmap), 1, 0, 2);
1773 k = isl_basic_map_alloc_div(bmap);
1774 if (k < 0)
1775 return isl_basic_map_free(bmap);
1776 isl_seq_cpy(bmap->div[k], div->el, div->size);
1777 isl_int_set_si(bmap->div[k][div->size], 0);
1779 for (i = k; i > pos; --i)
1780 bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1782 return bmap;
1785 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1787 if (!bmap)
1788 return isl_stat_error;
1789 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1790 bmap->n_div -= n;
1791 return isl_stat_ok;
1794 static __isl_give isl_basic_map *add_constraints(
1795 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1796 unsigned i_pos, unsigned o_pos)
1798 isl_size total, n_param, n_in, n_out, n_div;
1799 unsigned o_in, o_out;
1800 isl_ctx *ctx;
1801 isl_space *space;
1802 struct isl_dim_map *dim_map;
1804 space = isl_basic_map_peek_space(bmap2);
1805 if (!bmap1 || !space)
1806 goto error;
1808 total = isl_basic_map_dim(bmap1, isl_dim_all);
1809 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1810 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1811 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1812 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1813 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1814 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1815 if (total < 0 || n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
1816 goto error;
1817 ctx = isl_basic_map_get_ctx(bmap1);
1818 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1819 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1820 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1821 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1822 isl_dim_map_div(dim_map, bmap2, total);
1824 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1825 error:
1826 isl_basic_map_free(bmap1);
1827 isl_basic_map_free(bmap2);
1828 return NULL;
1831 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1832 struct isl_basic_set *bset2, unsigned pos)
1834 return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1835 bset_to_bmap(bset2), 0, pos));
1838 __isl_give isl_basic_map *isl_basic_map_extend_space(
1839 __isl_take isl_basic_map *base, __isl_take isl_space *space,
1840 unsigned extra, unsigned n_eq, unsigned n_ineq)
1842 struct isl_basic_map *ext;
1843 unsigned flags;
1844 int dims_ok;
1846 if (!space)
1847 goto error;
1849 if (!base)
1850 goto error;
1852 dims_ok = isl_space_is_equal(base->dim, space) &&
1853 base->extra >= base->n_div + extra;
1855 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1856 room_for_ineq(base, n_ineq)) {
1857 isl_space_free(space);
1858 return base;
1861 isl_assert(base->ctx, base->dim->nparam <= space->nparam, goto error);
1862 isl_assert(base->ctx, base->dim->n_in <= space->n_in, goto error);
1863 isl_assert(base->ctx, base->dim->n_out <= space->n_out, goto error);
1864 extra += base->extra;
1865 n_eq += base->n_eq;
1866 n_ineq += base->n_ineq;
1868 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1869 space = NULL;
1870 if (!ext)
1871 goto error;
1873 if (dims_ok)
1874 ext->sample = isl_vec_copy(base->sample);
1875 flags = base->flags;
1876 ext = add_constraints(ext, base, 0, 0);
1877 if (ext) {
1878 ext->flags = flags;
1879 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1882 return ext;
1884 error:
1885 isl_space_free(space);
1886 isl_basic_map_free(base);
1887 return NULL;
1890 __isl_give isl_basic_set *isl_basic_set_extend_space(
1891 __isl_take isl_basic_set *base,
1892 __isl_take isl_space *dim, unsigned extra,
1893 unsigned n_eq, unsigned n_ineq)
1895 return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1896 dim, extra, n_eq, n_ineq));
1899 struct isl_basic_map *isl_basic_map_extend_constraints(
1900 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1902 if (!base)
1903 return NULL;
1904 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1905 0, n_eq, n_ineq);
1908 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1909 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1910 unsigned n_eq, unsigned n_ineq)
1912 struct isl_basic_map *bmap;
1913 isl_space *dim;
1915 if (!base)
1916 return NULL;
1917 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1918 if (!dim)
1919 goto error;
1921 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1922 return bmap;
1923 error:
1924 isl_basic_map_free(base);
1925 return NULL;
1928 struct isl_basic_set *isl_basic_set_extend_constraints(
1929 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1931 isl_basic_map *bmap = bset_to_bmap(base);
1932 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1933 return bset_from_bmap(bmap);
1936 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1938 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1941 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1943 if (!bmap)
1944 return NULL;
1946 if (bmap->ref > 1) {
1947 bmap->ref--;
1948 bmap = isl_basic_map_dup(bmap);
1950 if (bmap) {
1951 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1952 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1954 return bmap;
1957 /* Clear all cached information in "map", either because it is about
1958 * to be modified or because it is being freed.
1959 * Always return the same pointer that is passed in.
1960 * This is needed for the use in isl_map_free.
1962 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1964 isl_basic_map_free(map->cached_simple_hull[0]);
1965 isl_basic_map_free(map->cached_simple_hull[1]);
1966 map->cached_simple_hull[0] = NULL;
1967 map->cached_simple_hull[1] = NULL;
1968 return map;
1971 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
1973 return isl_map_cow(set);
1976 /* Return an isl_map that is equal to "map" and that has only
1977 * a single reference.
1979 * If the original input already has only one reference, then
1980 * simply return it, but clear all cached information, since
1981 * it may be rendered invalid by the operations that will be
1982 * performed on the result.
1984 * Otherwise, create a duplicate (without any cached information).
1986 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
1988 if (!map)
1989 return NULL;
1991 if (map->ref == 1)
1992 return clear_caches(map);
1993 map->ref--;
1994 return isl_map_dup(map);
1997 static void swap_vars(struct isl_blk blk, isl_int *a,
1998 unsigned a_len, unsigned b_len)
2000 isl_seq_cpy(blk.data, a+a_len, b_len);
2001 isl_seq_cpy(blk.data+b_len, a, a_len);
2002 isl_seq_cpy(a, blk.data, b_len+a_len);
2005 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
2006 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
2008 int i;
2009 struct isl_blk blk;
2011 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
2012 goto error;
2014 if (n1 == 0 || n2 == 0)
2015 return bmap;
2017 bmap = isl_basic_map_cow(bmap);
2018 if (!bmap)
2019 return NULL;
2021 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2022 if (isl_blk_is_error(blk))
2023 goto error;
2025 for (i = 0; i < bmap->n_eq; ++i)
2026 swap_vars(blk,
2027 bmap->eq[i] + pos, n1, n2);
2029 for (i = 0; i < bmap->n_ineq; ++i)
2030 swap_vars(blk,
2031 bmap->ineq[i] + pos, n1, n2);
2033 for (i = 0; i < bmap->n_div; ++i)
2034 swap_vars(blk,
2035 bmap->div[i]+1 + pos, n1, n2);
2037 isl_blk_free(bmap->ctx, blk);
2039 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2040 bmap = isl_basic_map_gauss(bmap, NULL);
2041 return isl_basic_map_finalize(bmap);
2042 error:
2043 isl_basic_map_free(bmap);
2044 return NULL;
2047 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2048 __isl_take isl_basic_map *bmap)
2050 int i = 0;
2051 isl_size total;
2053 total = isl_basic_map_dim(bmap, isl_dim_all);
2054 if (total < 0)
2055 return isl_basic_map_free(bmap);
2056 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2057 return isl_basic_map_free(bmap);
2058 bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2059 if (!bmap)
2060 return NULL;
2061 if (bmap->n_eq > 0) {
2062 bmap = isl_basic_map_free_equality(bmap, bmap->n_eq - 1);
2063 if (!bmap)
2064 return NULL;
2065 } else {
2066 i = isl_basic_map_alloc_equality(bmap);
2067 if (i < 0)
2068 goto error;
2070 isl_int_set_si(bmap->eq[i][0], 1);
2071 isl_seq_clr(bmap->eq[i]+1, total);
2072 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2073 isl_vec_free(bmap->sample);
2074 bmap->sample = NULL;
2075 return isl_basic_map_finalize(bmap);
2076 error:
2077 isl_basic_map_free(bmap);
2078 return NULL;
2081 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2082 __isl_take isl_basic_set *bset)
2084 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2087 __isl_give isl_basic_map *isl_basic_map_set_rational(
2088 __isl_take isl_basic_map *bmap)
2090 if (!bmap)
2091 return NULL;
2093 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2094 return bmap;
2096 bmap = isl_basic_map_cow(bmap);
2097 if (!bmap)
2098 return NULL;
2100 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2102 return isl_basic_map_finalize(bmap);
2105 __isl_give isl_basic_set *isl_basic_set_set_rational(
2106 __isl_take isl_basic_set *bset)
2108 return isl_basic_map_set_rational(bset);
2111 __isl_give isl_basic_set *isl_basic_set_set_integral(
2112 __isl_take isl_basic_set *bset)
2114 if (!bset)
2115 return NULL;
2117 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2118 return bset;
2120 bset = isl_basic_set_cow(bset);
2121 if (!bset)
2122 return NULL;
2124 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2126 return isl_basic_set_finalize(bset);
2129 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2131 int i;
2133 map = isl_map_cow(map);
2134 if (!map)
2135 return NULL;
2136 for (i = 0; i < map->n; ++i) {
2137 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2138 if (!map->p[i])
2139 goto error;
2141 return map;
2142 error:
2143 isl_map_free(map);
2144 return NULL;
2147 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2149 return isl_map_set_rational(set);
2152 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2153 * of "bmap").
2155 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2157 isl_int *t = bmap->div[a];
2158 bmap->div[a] = bmap->div[b];
2159 bmap->div[b] = t;
2162 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2163 * div definitions accordingly.
2165 __isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2166 int a, int b)
2168 int i;
2169 isl_size off;
2171 off = isl_basic_map_var_offset(bmap, isl_dim_div);
2172 if (off < 0)
2173 return isl_basic_map_free(bmap);
2175 swap_div(bmap, a, b);
2177 for (i = 0; i < bmap->n_eq; ++i)
2178 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2180 for (i = 0; i < bmap->n_ineq; ++i)
2181 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2183 for (i = 0; i < bmap->n_div; ++i)
2184 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2185 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2187 return bmap;
2190 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2192 isl_seq_cpy(c, c + n, rem);
2193 isl_seq_clr(c + rem, n);
2196 /* Drop n dimensions starting at first.
2198 * In principle, this frees up some extra variables as the number
2199 * of columns remains constant, but we would have to extend
2200 * the div array too as the number of rows in this array is assumed
2201 * to be equal to extra.
2203 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2204 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2206 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2209 /* Move "n" divs starting at "first" to the end of the list of divs.
2211 static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
2212 unsigned first, unsigned n)
2214 isl_int **div;
2215 int i;
2217 if (first + n == bmap->n_div)
2218 return bmap;
2220 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2221 if (!div)
2222 goto error;
2223 for (i = 0; i < n; ++i)
2224 div[i] = bmap->div[first + i];
2225 for (i = 0; i < bmap->n_div - first - n; ++i)
2226 bmap->div[first + i] = bmap->div[first + n + i];
2227 for (i = 0; i < n; ++i)
2228 bmap->div[bmap->n_div - n + i] = div[i];
2229 free(div);
2230 return bmap;
2231 error:
2232 isl_basic_map_free(bmap);
2233 return NULL;
2236 #undef TYPE
2237 #define TYPE isl_map
2238 static
2239 #include "check_type_range_templ.c"
2241 /* Check that there are "n" dimensions of type "type" starting at "first"
2242 * in "set".
2244 static isl_stat isl_set_check_range(__isl_keep isl_set *set,
2245 enum isl_dim_type type, unsigned first, unsigned n)
2247 return isl_map_check_range(set_to_map(set), type, first, n);
2250 /* Drop "n" dimensions of type "type" starting at "first".
2251 * Perform the core computation, without cowing or
2252 * simplifying and finalizing the result.
2254 * In principle, this frees up some extra variables as the number
2255 * of columns remains constant, but we would have to extend
2256 * the div array too as the number of rows in this array is assumed
2257 * to be equal to extra.
2259 __isl_give isl_basic_map *isl_basic_map_drop_core(
2260 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2261 unsigned first, unsigned n)
2263 int i;
2264 unsigned offset;
2265 unsigned left;
2266 isl_size total;
2268 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2269 return isl_basic_map_free(bmap);
2271 total = isl_basic_map_dim(bmap, isl_dim_all);
2272 if (total < 0)
2273 return isl_basic_map_free(bmap);
2275 offset = isl_basic_map_offset(bmap, type) + first;
2276 left = total - (offset - 1) - n;
2277 for (i = 0; i < bmap->n_eq; ++i)
2278 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2280 for (i = 0; i < bmap->n_ineq; ++i)
2281 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2283 for (i = 0; i < bmap->n_div; ++i)
2284 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2286 if (type == isl_dim_div) {
2287 bmap = move_divs_last(bmap, first, n);
2288 if (!bmap)
2289 return NULL;
2290 if (isl_basic_map_free_div(bmap, n) < 0)
2291 return isl_basic_map_free(bmap);
2292 } else
2293 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2294 if (!bmap->dim)
2295 return isl_basic_map_free(bmap);
2297 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2298 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2299 return bmap;
2302 /* Drop "n" dimensions of type "type" starting at "first".
2304 * In principle, this frees up some extra variables as the number
2305 * of columns remains constant, but we would have to extend
2306 * the div array too as the number of rows in this array is assumed
2307 * to be equal to extra.
2309 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2310 enum isl_dim_type type, unsigned first, unsigned n)
2312 if (!bmap)
2313 return NULL;
2314 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2315 return bmap;
2317 bmap = isl_basic_map_cow(bmap);
2318 if (!bmap)
2319 return NULL;
2321 bmap = isl_basic_map_drop_core(bmap, type, first, n);
2323 bmap = isl_basic_map_simplify(bmap);
2324 return isl_basic_map_finalize(bmap);
2327 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2328 enum isl_dim_type type, unsigned first, unsigned n)
2330 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2331 type, first, n));
2334 /* No longer consider "map" to be normalized.
2336 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2338 if (!map)
2339 return NULL;
2340 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2341 return map;
2344 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2345 enum isl_dim_type type, unsigned first, unsigned n)
2347 int i;
2349 if (isl_map_check_range(map, type, first, n) < 0)
2350 return isl_map_free(map);
2352 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2353 return map;
2354 map = isl_map_cow(map);
2355 if (!map)
2356 goto error;
2357 map->dim = isl_space_drop_dims(map->dim, type, first, n);
2358 if (!map->dim)
2359 goto error;
2361 for (i = 0; i < map->n; ++i) {
2362 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2363 if (!map->p[i])
2364 goto error;
2366 map = isl_map_unmark_normalized(map);
2368 return map;
2369 error:
2370 isl_map_free(map);
2371 return NULL;
2374 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2375 enum isl_dim_type type, unsigned first, unsigned n)
2377 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2380 /* Drop the integer division at position "div", which is assumed
2381 * not to appear in any of the constraints or
2382 * in any of the other integer divisions.
2384 * Since the integer division is redundant, there is no need to cow.
2386 __isl_give isl_basic_map *isl_basic_map_drop_div(
2387 __isl_take isl_basic_map *bmap, unsigned div)
2389 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2392 /* Eliminate the specified n dimensions starting at first from the
2393 * constraints, without removing the dimensions from the space.
2394 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2396 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2397 enum isl_dim_type type, unsigned first, unsigned n)
2399 int i;
2401 if (n == 0)
2402 return map;
2404 if (isl_map_check_range(map, type, first, n) < 0)
2405 return isl_map_free(map);
2407 map = isl_map_cow(map);
2408 if (!map)
2409 return NULL;
2411 for (i = 0; i < map->n; ++i) {
2412 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2413 if (!map->p[i])
2414 goto error;
2416 return map;
2417 error:
2418 isl_map_free(map);
2419 return NULL;
2422 /* Eliminate the specified n dimensions starting at first from the
2423 * constraints, without removing the dimensions from the space.
2424 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2426 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2427 enum isl_dim_type type, unsigned first, unsigned n)
2429 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2432 /* Eliminate the specified n dimensions starting at first from the
2433 * constraints, without removing the dimensions from the space.
2434 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2436 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2437 unsigned first, unsigned n)
2439 return isl_set_eliminate(set, isl_dim_set, first, n);
2442 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2443 __isl_take isl_basic_map *bmap)
2445 isl_size v_div;
2447 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2448 if (v_div < 0)
2449 return isl_basic_map_free(bmap);
2450 bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);
2451 if (!bmap)
2452 return NULL;
2453 bmap->n_div = 0;
2454 return isl_basic_map_finalize(bmap);
2457 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2458 __isl_take isl_basic_set *bset)
2460 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2463 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2465 int i;
2467 if (!map)
2468 return NULL;
2469 if (map->n == 0)
2470 return map;
2472 map = isl_map_cow(map);
2473 if (!map)
2474 return NULL;
2476 for (i = 0; i < map->n; ++i) {
2477 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2478 if (!map->p[i])
2479 goto error;
2481 return map;
2482 error:
2483 isl_map_free(map);
2484 return NULL;
2487 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2489 return isl_map_remove_divs(set);
2492 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2493 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2494 unsigned first, unsigned n)
2496 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2497 return isl_basic_map_free(bmap);
2498 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2499 return bmap;
2500 bmap = isl_basic_map_eliminate_vars(bmap,
2501 isl_basic_map_offset(bmap, type) - 1 + first, n);
2502 if (!bmap)
2503 return bmap;
2504 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2505 return bmap;
2506 bmap = isl_basic_map_drop(bmap, type, first, n);
2507 return bmap;
2510 /* Return true if the definition of the given div (recursively) involves
2511 * any of the given variables.
2513 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2514 unsigned first, unsigned n)
2516 int i;
2517 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2519 if (isl_int_is_zero(bmap->div[div][0]))
2520 return isl_bool_false;
2521 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2522 return isl_bool_true;
2524 for (i = bmap->n_div - 1; i >= 0; --i) {
2525 isl_bool involves;
2527 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2528 continue;
2529 involves = div_involves_vars(bmap, i, first, n);
2530 if (involves < 0 || involves)
2531 return involves;
2534 return isl_bool_false;
2537 /* Try and add a lower and/or upper bound on "div" to "bmap"
2538 * based on inequality "i".
2539 * "total" is the total number of variables (excluding the divs).
2540 * "v" is a temporary object that can be used during the calculations.
2541 * If "lb" is set, then a lower bound should be constructed.
2542 * If "ub" is set, then an upper bound should be constructed.
2544 * The calling function has already checked that the inequality does not
2545 * reference "div", but we still need to check that the inequality is
2546 * of the right form. We'll consider the case where we want to construct
2547 * a lower bound. The construction of upper bounds is similar.
2549 * Let "div" be of the form
2551 * q = floor((a + f(x))/d)
2553 * We essentially check if constraint "i" is of the form
2555 * b + f(x) >= 0
2557 * so that we can use it to derive a lower bound on "div".
2558 * However, we allow a slightly more general form
2560 * b + g(x) >= 0
2562 * with the condition that the coefficients of g(x) - f(x) are all
2563 * divisible by d.
2564 * Rewriting this constraint as
2566 * 0 >= -b - g(x)
2568 * adding a + f(x) to both sides and dividing by d, we obtain
2570 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2572 * Taking the floor on both sides, we obtain
2574 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2576 * or
2578 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2580 * In the case of an upper bound, we construct the constraint
2582 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2585 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2586 __isl_take isl_basic_map *bmap, int div, int i,
2587 unsigned total, isl_int v, int lb, int ub)
2589 int j;
2591 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2592 if (lb) {
2593 isl_int_sub(v, bmap->ineq[i][1 + j],
2594 bmap->div[div][1 + 1 + j]);
2595 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2597 if (ub) {
2598 isl_int_add(v, bmap->ineq[i][1 + j],
2599 bmap->div[div][1 + 1 + j]);
2600 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2603 if (!lb && !ub)
2604 return bmap;
2606 bmap = isl_basic_map_cow(bmap);
2607 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2608 if (lb) {
2609 int k = isl_basic_map_alloc_inequality(bmap);
2610 if (k < 0)
2611 goto error;
2612 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2613 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2614 bmap->div[div][1 + j]);
2615 isl_int_cdiv_q(bmap->ineq[k][j],
2616 bmap->ineq[k][j], bmap->div[div][0]);
2618 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2620 if (ub) {
2621 int k = isl_basic_map_alloc_inequality(bmap);
2622 if (k < 0)
2623 goto error;
2624 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2625 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2626 bmap->div[div][1 + j]);
2627 isl_int_fdiv_q(bmap->ineq[k][j],
2628 bmap->ineq[k][j], bmap->div[div][0]);
2630 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2633 return bmap;
2634 error:
2635 isl_basic_map_free(bmap);
2636 return NULL;
2639 /* This function is called right before "div" is eliminated from "bmap"
2640 * using Fourier-Motzkin.
2641 * Look through the constraints of "bmap" for constraints on the argument
2642 * of the integer division and use them to construct constraints on the
2643 * integer division itself. These constraints can then be combined
2644 * during the Fourier-Motzkin elimination.
2645 * Note that it is only useful to introduce lower bounds on "div"
2646 * if "bmap" already contains upper bounds on "div" as the newly
2647 * introduce lower bounds can then be combined with the pre-existing
2648 * upper bounds. Similarly for upper bounds.
2649 * We therefore first check if "bmap" contains any lower and/or upper bounds
2650 * on "div".
2652 * It is interesting to note that the introduction of these constraints
2653 * can indeed lead to more accurate results, even when compared to
2654 * deriving constraints on the argument of "div" from constraints on "div".
2655 * Consider, for example, the set
2657 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2659 * The second constraint can be rewritten as
2661 * 2 * [(-i-2j+3)/4] + k >= 0
2663 * from which we can derive
2665 * -i - 2j + 3 >= -2k
2667 * or
2669 * i + 2j <= 3 + 2k
2671 * Combined with the first constraint, we obtain
2673 * -3 <= 3 + 2k or k >= -3
2675 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2676 * the first constraint, we obtain
2678 * [(i + 2j)/4] >= [-3/4] = -1
2680 * Combining this constraint with the second constraint, we obtain
2682 * k >= -2
2684 static __isl_give isl_basic_map *insert_bounds_on_div(
2685 __isl_take isl_basic_map *bmap, int div)
2687 int i;
2688 int check_lb, check_ub;
2689 isl_int v;
2690 isl_size v_div;
2692 if (!bmap)
2693 return NULL;
2695 if (isl_int_is_zero(bmap->div[div][0]))
2696 return bmap;
2698 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2699 if (v_div < 0)
2700 return isl_basic_map_free(bmap);
2702 check_lb = 0;
2703 check_ub = 0;
2704 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2705 int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);
2706 if (s > 0)
2707 check_ub = 1;
2708 if (s < 0)
2709 check_lb = 1;
2712 if (!check_lb && !check_ub)
2713 return bmap;
2715 isl_int_init(v);
2717 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2718 if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))
2719 continue;
2721 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,
2722 check_lb, check_ub);
2725 isl_int_clear(v);
2727 return bmap;
2730 /* Remove all divs (recursively) involving any of the given dimensions
2731 * in their definitions.
2733 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2734 __isl_take isl_basic_map *bmap,
2735 enum isl_dim_type type, unsigned first, unsigned n)
2737 int i;
2739 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2740 return isl_basic_map_free(bmap);
2741 first += isl_basic_map_offset(bmap, type);
2743 for (i = bmap->n_div - 1; i >= 0; --i) {
2744 isl_bool involves;
2746 involves = div_involves_vars(bmap, i, first, n);
2747 if (involves < 0)
2748 return isl_basic_map_free(bmap);
2749 if (!involves)
2750 continue;
2751 bmap = insert_bounds_on_div(bmap, i);
2752 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2753 if (!bmap)
2754 return NULL;
2755 i = bmap->n_div;
2758 return bmap;
2761 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2762 __isl_take isl_basic_set *bset,
2763 enum isl_dim_type type, unsigned first, unsigned n)
2765 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2768 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2769 enum isl_dim_type type, unsigned first, unsigned n)
2771 int i;
2773 if (!map)
2774 return NULL;
2775 if (map->n == 0)
2776 return map;
2778 map = isl_map_cow(map);
2779 if (!map)
2780 return NULL;
2782 for (i = 0; i < map->n; ++i) {
2783 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2784 type, first, n);
2785 if (!map->p[i])
2786 goto error;
2788 return map;
2789 error:
2790 isl_map_free(map);
2791 return NULL;
2794 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2795 enum isl_dim_type type, unsigned first, unsigned n)
2797 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2798 type, first, n));
2801 /* Does the description of "bmap" depend on the specified dimensions?
2802 * We also check whether the dimensions appear in any of the div definitions.
2803 * In principle there is no need for this check. If the dimensions appear
2804 * in a div definition, they also appear in the defining constraints of that
2805 * div.
2807 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2808 enum isl_dim_type type, unsigned first, unsigned n)
2810 int i;
2812 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2813 return isl_bool_error;
2815 first += isl_basic_map_offset(bmap, type);
2816 for (i = 0; i < bmap->n_eq; ++i)
2817 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2818 return isl_bool_true;
2819 for (i = 0; i < bmap->n_ineq; ++i)
2820 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2821 return isl_bool_true;
2822 for (i = 0; i < bmap->n_div; ++i) {
2823 if (isl_int_is_zero(bmap->div[i][0]))
2824 continue;
2825 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2826 return isl_bool_true;
2829 return isl_bool_false;
2832 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2833 enum isl_dim_type type, unsigned first, unsigned n)
2835 int i;
2837 if (isl_map_check_range(map, type, first, n) < 0)
2838 return isl_bool_error;
2840 for (i = 0; i < map->n; ++i) {
2841 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2842 type, first, n);
2843 if (involves < 0 || involves)
2844 return involves;
2847 return isl_bool_false;
2850 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2851 enum isl_dim_type type, unsigned first, unsigned n)
2853 return isl_basic_map_involves_dims(bset, type, first, n);
2856 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2857 enum isl_dim_type type, unsigned first, unsigned n)
2859 return isl_map_involves_dims(set, type, first, n);
2862 /* Drop all constraints in bmap that involve any of the dimensions
2863 * first to first+n-1.
2864 * This function only performs the actual removal of constraints.
2866 * This function should not call finalize since it is used by
2867 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
2869 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2870 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2872 int i;
2874 if (n == 0)
2875 return bmap;
2877 bmap = isl_basic_map_cow(bmap);
2879 if (!bmap)
2880 return NULL;
2882 for (i = bmap->n_eq - 1; i >= 0; --i) {
2883 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2884 continue;
2885 isl_basic_map_drop_equality(bmap, i);
2888 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2889 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2890 continue;
2891 isl_basic_map_drop_inequality(bmap, i);
2894 return bmap;
2897 /* Drop all constraints in bset that involve any of the dimensions
2898 * first to first+n-1.
2899 * This function only performs the actual removal of constraints.
2901 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2902 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2904 return isl_basic_map_drop_constraints_involving(bset, first, n);
2907 /* Drop all constraints in bmap that do not involve any of the dimensions
2908 * first to first + n - 1 of the given type.
2910 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2911 __isl_take isl_basic_map *bmap,
2912 enum isl_dim_type type, unsigned first, unsigned n)
2914 int i;
2916 if (n == 0) {
2917 isl_space *space = isl_basic_map_get_space(bmap);
2918 isl_basic_map_free(bmap);
2919 return isl_basic_map_universe(space);
2921 bmap = isl_basic_map_cow(bmap);
2922 if (!bmap)
2923 return NULL;
2925 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2926 return isl_basic_map_free(bmap);
2928 first += isl_basic_map_offset(bmap, type) - 1;
2930 for (i = bmap->n_eq - 1; i >= 0; --i) {
2931 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2932 continue;
2933 isl_basic_map_drop_equality(bmap, i);
2936 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2937 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2938 continue;
2939 isl_basic_map_drop_inequality(bmap, i);
2942 bmap = isl_basic_map_add_known_div_constraints(bmap);
2943 return bmap;
2946 /* Drop all constraints in bset that do not involve any of the dimensions
2947 * first to first + n - 1 of the given type.
2949 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2950 __isl_take isl_basic_set *bset,
2951 enum isl_dim_type type, unsigned first, unsigned n)
2953 return isl_basic_map_drop_constraints_not_involving_dims(bset,
2954 type, first, n);
2957 /* Drop all constraints in bmap that involve any of the dimensions
2958 * first to first + n - 1 of the given type.
2960 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2961 __isl_take isl_basic_map *bmap,
2962 enum isl_dim_type type, unsigned first, unsigned n)
2964 if (!bmap)
2965 return NULL;
2966 if (n == 0)
2967 return bmap;
2969 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2970 return isl_basic_map_free(bmap);
2972 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2973 first += isl_basic_map_offset(bmap, type) - 1;
2974 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
2975 bmap = isl_basic_map_add_known_div_constraints(bmap);
2976 return bmap;
2979 /* Drop all constraints in bset that involve any of the dimensions
2980 * first to first + n - 1 of the given type.
2982 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2983 __isl_take isl_basic_set *bset,
2984 enum isl_dim_type type, unsigned first, unsigned n)
2986 return isl_basic_map_drop_constraints_involving_dims(bset,
2987 type, first, n);
2990 /* Drop constraints from "map" by applying "drop" to each basic map.
2992 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2993 enum isl_dim_type type, unsigned first, unsigned n,
2994 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2995 enum isl_dim_type type, unsigned first, unsigned n))
2997 int i;
2999 if (isl_map_check_range(map, type, first, n) < 0)
3000 return isl_map_free(map);
3002 map = isl_map_cow(map);
3003 if (!map)
3004 return NULL;
3006 for (i = 0; i < map->n; ++i) {
3007 map->p[i] = drop(map->p[i], type, first, n);
3008 if (!map->p[i])
3009 return isl_map_free(map);
3012 if (map->n > 1)
3013 ISL_F_CLR(map, ISL_MAP_DISJOINT);
3015 return map;
3018 /* Drop all constraints in map that involve any of the dimensions
3019 * first to first + n - 1 of the given type.
3021 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
3022 __isl_take isl_map *map,
3023 enum isl_dim_type type, unsigned first, unsigned n)
3025 if (n == 0)
3026 return map;
3027 return drop_constraints(map, type, first, n,
3028 &isl_basic_map_drop_constraints_involving_dims);
3031 /* Drop all constraints in "map" that do not involve any of the dimensions
3032 * first to first + n - 1 of the given type.
3034 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3035 __isl_take isl_map *map,
3036 enum isl_dim_type type, unsigned first, unsigned n)
3038 if (n == 0) {
3039 isl_space *space = isl_map_get_space(map);
3040 isl_map_free(map);
3041 return isl_map_universe(space);
3043 return drop_constraints(map, type, first, n,
3044 &isl_basic_map_drop_constraints_not_involving_dims);
3047 /* Drop all constraints in set that involve any of the dimensions
3048 * first to first + n - 1 of the given type.
3050 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3051 __isl_take isl_set *set,
3052 enum isl_dim_type type, unsigned first, unsigned n)
3054 return isl_map_drop_constraints_involving_dims(set, type, first, n);
3057 /* Drop all constraints in "set" that do not involve any of the dimensions
3058 * first to first + n - 1 of the given type.
3060 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3061 __isl_take isl_set *set,
3062 enum isl_dim_type type, unsigned first, unsigned n)
3064 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3067 /* Does local variable "div" of "bmap" have a complete explicit representation?
3068 * Having a complete explicit representation requires not only
3069 * an explicit representation, but also that all local variables
3070 * that appear in this explicit representation in turn have
3071 * a complete explicit representation.
3073 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3075 int i;
3076 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3077 isl_bool marked;
3079 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3080 if (marked < 0 || marked)
3081 return isl_bool_not(marked);
3083 for (i = bmap->n_div - 1; i >= 0; --i) {
3084 isl_bool known;
3086 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3087 continue;
3088 known = isl_basic_map_div_is_known(bmap, i);
3089 if (known < 0 || !known)
3090 return known;
3093 return isl_bool_true;
3096 /* Remove all divs that are unknown or defined in terms of unknown divs.
3098 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3099 __isl_take isl_basic_map *bmap)
3101 int i;
3103 if (!bmap)
3104 return NULL;
3106 for (i = bmap->n_div - 1; i >= 0; --i) {
3107 if (isl_basic_map_div_is_known(bmap, i))
3108 continue;
3109 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3110 if (!bmap)
3111 return NULL;
3112 i = bmap->n_div;
3115 return bmap;
3118 /* Remove all divs that are unknown or defined in terms of unknown divs.
3120 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3121 __isl_take isl_basic_set *bset)
3123 return isl_basic_map_remove_unknown_divs(bset);
3126 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3128 int i;
3130 if (!map)
3131 return NULL;
3132 if (map->n == 0)
3133 return map;
3135 map = isl_map_cow(map);
3136 if (!map)
3137 return NULL;
3139 for (i = 0; i < map->n; ++i) {
3140 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3141 if (!map->p[i])
3142 goto error;
3144 return map;
3145 error:
3146 isl_map_free(map);
3147 return NULL;
3150 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3152 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3155 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3156 __isl_take isl_basic_set *bset,
3157 enum isl_dim_type type, unsigned first, unsigned n)
3159 isl_basic_map *bmap = bset_to_bmap(bset);
3160 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3161 return bset_from_bmap(bmap);
3164 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3165 enum isl_dim_type type, unsigned first, unsigned n)
3167 int i;
3169 if (n == 0)
3170 return map;
3172 map = isl_map_cow(map);
3173 if (isl_map_check_range(map, type, first, n) < 0)
3174 return isl_map_free(map);
3176 for (i = 0; i < map->n; ++i) {
3177 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3178 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3179 if (!map->p[i])
3180 goto error;
3182 map = isl_map_drop(map, type, first, n);
3183 return map;
3184 error:
3185 isl_map_free(map);
3186 return NULL;
3189 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3190 enum isl_dim_type type, unsigned first, unsigned n)
3192 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3193 type, first, n));
3196 /* Project out n inputs starting at first using Fourier-Motzkin */
3197 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
3198 unsigned first, unsigned n)
3200 return isl_map_remove_dims(map, isl_dim_in, first, n);
3203 void isl_basic_set_print_internal(struct isl_basic_set *bset,
3204 FILE *out, int indent)
3206 isl_printer *p;
3208 if (!bset) {
3209 fprintf(out, "null basic set\n");
3210 return;
3213 fprintf(out, "%*s", indent, "");
3214 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3215 bset->ref, bset->dim->nparam, bset->dim->n_out,
3216 bset->extra, bset->flags);
3218 p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
3219 p = isl_printer_set_dump(p, 1);
3220 p = isl_printer_set_indent(p, indent);
3221 p = isl_printer_start_line(p);
3222 p = isl_printer_print_basic_set(p, bset);
3223 p = isl_printer_end_line(p);
3224 isl_printer_free(p);
3227 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
3228 FILE *out, int indent)
3230 isl_printer *p;
3232 if (!bmap) {
3233 fprintf(out, "null basic map\n");
3234 return;
3237 fprintf(out, "%*s", indent, "");
3238 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3239 "flags: %x, n_name: %d\n",
3240 bmap->ref,
3241 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3242 bmap->extra, bmap->flags, bmap->dim->n_id);
3244 p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
3245 p = isl_printer_set_dump(p, 1);
3246 p = isl_printer_set_indent(p, indent);
3247 p = isl_printer_start_line(p);
3248 p = isl_printer_print_basic_map(p, bmap);
3249 p = isl_printer_end_line(p);
3250 isl_printer_free(p);
3253 __isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3254 unsigned pos)
3256 isl_size total;
3258 total = isl_basic_map_dim(bmap, isl_dim_all);
3259 if (total < 0)
3260 return isl_basic_map_free(bmap);
3261 if (pos >= bmap->n_ineq)
3262 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3263 "invalid position", return isl_basic_map_free(bmap));
3264 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3265 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3266 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3267 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3268 return bmap;
3271 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3272 unsigned flags)
3274 if (isl_space_check_is_set(space) < 0)
3275 goto error;
3276 return isl_map_alloc_space(space, n, flags);
3277 error:
3278 isl_space_free(space);
3279 return NULL;
3282 /* Make sure "map" has room for at least "n" more basic maps.
3284 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3286 int i;
3287 struct isl_map *grown = NULL;
3289 if (!map)
3290 return NULL;
3291 isl_assert(map->ctx, n >= 0, goto error);
3292 if (map->n + n <= map->size)
3293 return map;
3294 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3295 if (!grown)
3296 goto error;
3297 for (i = 0; i < map->n; ++i) {
3298 grown->p[i] = isl_basic_map_copy(map->p[i]);
3299 if (!grown->p[i])
3300 goto error;
3301 grown->n++;
3303 isl_map_free(map);
3304 return grown;
3305 error:
3306 isl_map_free(grown);
3307 isl_map_free(map);
3308 return NULL;
3311 /* Make sure "set" has room for at least "n" more basic sets.
3313 struct isl_set *isl_set_grow(struct isl_set *set, int n)
3315 return set_from_map(isl_map_grow(set_to_map(set), n));
3318 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3320 return isl_map_from_basic_map(bset);
3323 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3325 struct isl_map *map;
3327 if (!bmap)
3328 return NULL;
3330 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3331 return isl_map_add_basic_map(map, bmap);
3334 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3335 __isl_take isl_basic_set *bset)
3337 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3338 bset_to_bmap(bset)));
3341 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3343 return isl_map_free(set);
3346 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3348 int i;
3350 if (!set) {
3351 fprintf(out, "null set\n");
3352 return;
3355 fprintf(out, "%*s", indent, "");
3356 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3357 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3358 set->flags);
3359 for (i = 0; i < set->n; ++i) {
3360 fprintf(out, "%*s", indent, "");
3361 fprintf(out, "basic set %d:\n", i);
3362 isl_basic_set_print_internal(set->p[i], out, indent+4);
3366 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3368 int i;
3370 if (!map) {
3371 fprintf(out, "null map\n");
3372 return;
3375 fprintf(out, "%*s", indent, "");
3376 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3377 "flags: %x, n_name: %d\n",
3378 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3379 map->dim->n_out, map->flags, map->dim->n_id);
3380 for (i = 0; i < map->n; ++i) {
3381 fprintf(out, "%*s", indent, "");
3382 fprintf(out, "basic map %d:\n", i);
3383 isl_basic_map_print_internal(map->p[i], out, indent+4);
3387 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3388 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3390 struct isl_basic_map *bmap_domain;
3391 isl_size dim;
3393 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3394 goto error;
3396 dim = isl_basic_set_dim(bset, isl_dim_set);
3397 if (dim < 0)
3398 goto error;
3399 if (dim != 0)
3400 isl_assert(bset->ctx,
3401 isl_basic_map_compatible_domain(bmap, bset), goto error);
3403 bmap = isl_basic_map_cow(bmap);
3404 if (!bmap)
3405 goto error;
3406 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3407 bset->n_div, bset->n_eq, bset->n_ineq);
3408 bmap_domain = isl_basic_map_from_domain(bset);
3409 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3411 bmap = isl_basic_map_simplify(bmap);
3412 return isl_basic_map_finalize(bmap);
3413 error:
3414 isl_basic_map_free(bmap);
3415 isl_basic_set_free(bset);
3416 return NULL;
3419 /* Check that the space of "bset" is the same as that of the range of "bmap".
3421 static isl_stat isl_basic_map_check_compatible_range(
3422 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3424 isl_bool ok;
3426 ok = isl_basic_map_compatible_range(bmap, bset);
3427 if (ok < 0)
3428 return isl_stat_error;
3429 if (!ok)
3430 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3431 "incompatible spaces", return isl_stat_error);
3433 return isl_stat_ok;
3436 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3437 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3439 struct isl_basic_map *bmap_range;
3440 isl_size dim;
3442 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3443 goto error;
3445 dim = isl_basic_set_dim(bset, isl_dim_set);
3446 if (dim < 0)
3447 goto error;
3448 if (dim != 0 && isl_basic_map_check_compatible_range(bmap, bset) < 0)
3449 goto error;
3451 if (isl_basic_set_plain_is_universe(bset)) {
3452 isl_basic_set_free(bset);
3453 return bmap;
3456 bmap = isl_basic_map_cow(bmap);
3457 if (!bmap)
3458 goto error;
3459 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3460 bset->n_div, bset->n_eq, bset->n_ineq);
3461 bmap_range = bset_to_bmap(bset);
3462 bmap = add_constraints(bmap, bmap_range, 0, 0);
3464 bmap = isl_basic_map_simplify(bmap);
3465 return isl_basic_map_finalize(bmap);
3466 error:
3467 isl_basic_map_free(bmap);
3468 isl_basic_set_free(bset);
3469 return NULL;
3472 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3473 __isl_keep isl_vec *vec)
3475 int i;
3476 isl_size total;
3477 isl_int s;
3479 total = isl_basic_map_dim(bmap, isl_dim_all);
3480 if (total < 0 || !vec)
3481 return isl_bool_error;
3483 if (1 + total != vec->size)
3484 return isl_bool_false;
3486 isl_int_init(s);
3488 for (i = 0; i < bmap->n_eq; ++i) {
3489 isl_seq_inner_product(vec->el, bmap->eq[i], 1 + total, &s);
3490 if (!isl_int_is_zero(s)) {
3491 isl_int_clear(s);
3492 return isl_bool_false;
3496 for (i = 0; i < bmap->n_ineq; ++i) {
3497 isl_seq_inner_product(vec->el, bmap->ineq[i], 1 + total, &s);
3498 if (isl_int_is_neg(s)) {
3499 isl_int_clear(s);
3500 return isl_bool_false;
3504 isl_int_clear(s);
3506 return isl_bool_true;
3509 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3510 __isl_keep isl_vec *vec)
3512 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3515 __isl_give isl_basic_map *isl_basic_map_intersect(
3516 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3518 struct isl_vec *sample = NULL;
3519 isl_space *space1, *space2;
3520 isl_size dim1, dim2, nparam1, nparam2;
3522 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3523 goto error;
3524 space1 = isl_basic_map_peek_space(bmap1);
3525 space2 = isl_basic_map_peek_space(bmap2);
3526 dim1 = isl_space_dim(space1, isl_dim_all);
3527 dim2 = isl_space_dim(space2, isl_dim_all);
3528 nparam1 = isl_space_dim(space1, isl_dim_param);
3529 nparam2 = isl_space_dim(space2, isl_dim_param);
3530 if (dim1 < 0 || dim2 < 0 || nparam1 < 0 || nparam2 < 0)
3531 goto error;
3532 if (dim1 == nparam1 && dim2 != nparam2)
3533 return isl_basic_map_intersect(bmap2, bmap1);
3535 if (dim2 != nparam2)
3536 isl_assert(bmap1->ctx,
3537 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3539 if (isl_basic_map_plain_is_empty(bmap1)) {
3540 isl_basic_map_free(bmap2);
3541 return bmap1;
3543 if (isl_basic_map_plain_is_empty(bmap2)) {
3544 isl_basic_map_free(bmap1);
3545 return bmap2;
3548 if (bmap1->sample &&
3549 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3550 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3551 sample = isl_vec_copy(bmap1->sample);
3552 else if (bmap2->sample &&
3553 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3554 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3555 sample = isl_vec_copy(bmap2->sample);
3557 bmap1 = isl_basic_map_cow(bmap1);
3558 if (!bmap1)
3559 goto error;
3560 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3561 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3562 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3564 if (!bmap1)
3565 isl_vec_free(sample);
3566 else if (sample) {
3567 isl_vec_free(bmap1->sample);
3568 bmap1->sample = sample;
3571 bmap1 = isl_basic_map_simplify(bmap1);
3572 return isl_basic_map_finalize(bmap1);
3573 error:
3574 if (sample)
3575 isl_vec_free(sample);
3576 isl_basic_map_free(bmap1);
3577 isl_basic_map_free(bmap2);
3578 return NULL;
3581 struct isl_basic_set *isl_basic_set_intersect(
3582 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3584 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3585 bset_to_bmap(bset2)));
3588 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3589 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3591 return isl_basic_set_intersect(bset1, bset2);
3594 /* Special case of isl_map_intersect, where both map1 and map2
3595 * are convex, without any divs and such that either map1 or map2
3596 * contains a single constraint. This constraint is then simply
3597 * added to the other map.
3599 static __isl_give isl_map *map_intersect_add_constraint(
3600 __isl_take isl_map *map1, __isl_take isl_map *map2)
3602 isl_assert(map1->ctx, map1->n == 1, goto error);
3603 isl_assert(map2->ctx, map1->n == 1, goto error);
3604 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3605 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3607 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3608 return isl_map_intersect(map2, map1);
3610 map1 = isl_map_cow(map1);
3611 if (!map1)
3612 goto error;
3613 if (isl_map_plain_is_empty(map1)) {
3614 isl_map_free(map2);
3615 return map1;
3617 if (map2->p[0]->n_eq == 1)
3618 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3619 else
3620 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3621 map2->p[0]->ineq[0]);
3623 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3624 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3625 if (!map1->p[0])
3626 goto error;
3628 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3629 isl_basic_map_free(map1->p[0]);
3630 map1->n = 0;
3633 isl_map_free(map2);
3635 map1 = isl_map_unmark_normalized(map1);
3636 return map1;
3637 error:
3638 isl_map_free(map1);
3639 isl_map_free(map2);
3640 return NULL;
3643 /* map2 may be either a parameter domain or a map living in the same
3644 * space as map1.
3646 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3647 __isl_take isl_map *map2)
3649 unsigned flags = 0;
3650 isl_bool equal;
3651 isl_map *result;
3652 int i, j;
3653 isl_size dim2, nparam2;
3655 if (!map1 || !map2)
3656 goto error;
3658 if ((isl_map_plain_is_empty(map1) ||
3659 isl_map_plain_is_universe(map2)) &&
3660 isl_space_is_equal(map1->dim, map2->dim)) {
3661 isl_map_free(map2);
3662 return map1;
3664 if ((isl_map_plain_is_empty(map2) ||
3665 isl_map_plain_is_universe(map1)) &&
3666 isl_space_is_equal(map1->dim, map2->dim)) {
3667 isl_map_free(map1);
3668 return map2;
3671 if (map1->n == 1 && map2->n == 1 &&
3672 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3673 isl_space_is_equal(map1->dim, map2->dim) &&
3674 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3675 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3676 return map_intersect_add_constraint(map1, map2);
3678 equal = isl_map_plain_is_equal(map1, map2);
3679 if (equal < 0)
3680 goto error;
3681 if (equal) {
3682 isl_map_free(map2);
3683 return map1;
3686 dim2 = isl_map_dim(map2, isl_dim_all);
3687 nparam2 = isl_map_dim(map2, isl_dim_param);
3688 if (dim2 < 0 || nparam2 < 0)
3689 goto error;
3690 if (dim2 != nparam2)
3691 isl_assert(map1->ctx,
3692 isl_space_is_equal(map1->dim, map2->dim), goto error);
3694 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3695 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3696 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3698 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3699 map1->n * map2->n, flags);
3700 if (!result)
3701 goto error;
3702 for (i = 0; i < map1->n; ++i)
3703 for (j = 0; j < map2->n; ++j) {
3704 struct isl_basic_map *part;
3705 part = isl_basic_map_intersect(
3706 isl_basic_map_copy(map1->p[i]),
3707 isl_basic_map_copy(map2->p[j]));
3708 if (isl_basic_map_is_empty(part) < 0)
3709 part = isl_basic_map_free(part);
3710 result = isl_map_add_basic_map(result, part);
3711 if (!result)
3712 goto error;
3714 isl_map_free(map1);
3715 isl_map_free(map2);
3716 return result;
3717 error:
3718 isl_map_free(map1);
3719 isl_map_free(map2);
3720 return NULL;
3723 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3724 __isl_take isl_map *map2)
3726 if (!map1 || !map2)
3727 goto error;
3728 if (!isl_space_is_equal(map1->dim, map2->dim))
3729 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3730 "spaces don't match", goto error);
3731 return map_intersect_internal(map1, map2);
3732 error:
3733 isl_map_free(map1);
3734 isl_map_free(map2);
3735 return NULL;
3738 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3739 __isl_take isl_map *map2)
3741 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3744 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3746 return set_from_map(isl_map_intersect(set_to_map(set1),
3747 set_to_map(set2)));
3750 /* map_intersect_internal accepts intersections
3751 * with parameter domains, so we can just call that function.
3753 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3754 __isl_take isl_set *params)
3756 return map_intersect_internal(map, params);
3759 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3760 __isl_take isl_map *map2)
3762 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3765 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3766 __isl_take isl_set *params)
3768 return isl_map_intersect_params(set, params);
3771 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3773 isl_space *space;
3774 unsigned pos;
3775 isl_size n1, n2;
3777 if (!bmap)
3778 return NULL;
3779 bmap = isl_basic_map_cow(bmap);
3780 if (!bmap)
3781 return NULL;
3782 space = isl_space_reverse(isl_space_copy(bmap->dim));
3783 pos = isl_basic_map_offset(bmap, isl_dim_in);
3784 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3785 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3786 if (n1 < 0 || n2 < 0)
3787 bmap = isl_basic_map_free(bmap);
3788 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3789 return isl_basic_map_reset_space(bmap, space);
3792 static __isl_give isl_basic_map *basic_map_space_reset(
3793 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3795 isl_space *space;
3797 if (!bmap)
3798 return NULL;
3799 if (!isl_space_is_named_or_nested(bmap->dim, type))
3800 return bmap;
3802 space = isl_basic_map_get_space(bmap);
3803 space = isl_space_reset(space, type);
3804 bmap = isl_basic_map_reset_space(bmap, space);
3805 return bmap;
3808 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3809 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3810 unsigned pos, unsigned n)
3812 isl_bool rational, is_empty;
3813 isl_space *res_space;
3814 struct isl_basic_map *res;
3815 struct isl_dim_map *dim_map;
3816 isl_size total;
3817 unsigned off;
3818 enum isl_dim_type t;
3820 if (n == 0)
3821 return basic_map_space_reset(bmap, type);
3823 is_empty = isl_basic_map_plain_is_empty(bmap);
3824 total = isl_basic_map_dim(bmap, isl_dim_all);
3825 if (is_empty < 0 || total < 0)
3826 return isl_basic_map_free(bmap);
3827 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3828 type, pos, n);
3829 if (!res_space)
3830 return isl_basic_map_free(bmap);
3831 if (is_empty) {
3832 isl_basic_map_free(bmap);
3833 return isl_basic_map_empty(res_space);
3836 dim_map = isl_dim_map_alloc(bmap->ctx, total + n);
3837 off = 0;
3838 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3839 isl_size dim;
3841 if (t != type) {
3842 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3843 } else {
3844 isl_size size = isl_basic_map_dim(bmap, t);
3845 if (size < 0)
3846 dim_map = isl_dim_map_free(dim_map);
3847 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3848 0, pos, off);
3849 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3850 pos, size - pos, off + pos + n);
3852 dim = isl_space_dim(res_space, t);
3853 if (dim < 0)
3854 dim_map = isl_dim_map_free(dim_map);
3855 off += dim;
3857 isl_dim_map_div(dim_map, bmap, off);
3859 res = isl_basic_map_alloc_space(res_space,
3860 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3861 rational = isl_basic_map_is_rational(bmap);
3862 if (rational < 0)
3863 res = isl_basic_map_free(res);
3864 if (rational)
3865 res = isl_basic_map_set_rational(res);
3866 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3867 return isl_basic_map_finalize(res);
3870 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3871 __isl_take isl_basic_set *bset,
3872 enum isl_dim_type type, unsigned pos, unsigned n)
3874 return isl_basic_map_insert_dims(bset, type, pos, n);
3877 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3878 enum isl_dim_type type, unsigned n)
3880 isl_size dim;
3882 dim = isl_basic_map_dim(bmap, type);
3883 if (dim < 0)
3884 return isl_basic_map_free(bmap);
3885 return isl_basic_map_insert_dims(bmap, type, dim, n);
3888 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3889 enum isl_dim_type type, unsigned n)
3891 if (!bset)
3892 return NULL;
3893 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3894 return isl_basic_map_add_dims(bset, type, n);
3895 error:
3896 isl_basic_set_free(bset);
3897 return NULL;
3900 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3901 enum isl_dim_type type)
3903 isl_space *space;
3905 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3906 return map;
3908 space = isl_map_get_space(map);
3909 space = isl_space_reset(space, type);
3910 map = isl_map_reset_space(map, space);
3911 return map;
3914 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3915 enum isl_dim_type type, unsigned pos, unsigned n)
3917 int i;
3919 if (n == 0)
3920 return map_space_reset(map, type);
3922 map = isl_map_cow(map);
3923 if (!map)
3924 return NULL;
3926 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3927 if (!map->dim)
3928 goto error;
3930 for (i = 0; i < map->n; ++i) {
3931 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3932 if (!map->p[i])
3933 goto error;
3936 return map;
3937 error:
3938 isl_map_free(map);
3939 return NULL;
3942 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3943 enum isl_dim_type type, unsigned pos, unsigned n)
3945 return isl_map_insert_dims(set, type, pos, n);
3948 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3949 enum isl_dim_type type, unsigned n)
3951 isl_size dim;
3953 dim = isl_map_dim(map, type);
3954 if (dim < 0)
3955 return isl_map_free(map);
3956 return isl_map_insert_dims(map, type, dim, n);
3959 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3960 enum isl_dim_type type, unsigned n)
3962 if (!set)
3963 return NULL;
3964 isl_assert(set->ctx, type != isl_dim_in, goto error);
3965 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
3966 error:
3967 isl_set_free(set);
3968 return NULL;
3971 __isl_give isl_basic_map *isl_basic_map_move_dims(
3972 __isl_take isl_basic_map *bmap,
3973 enum isl_dim_type dst_type, unsigned dst_pos,
3974 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3976 isl_space *space;
3977 struct isl_dim_map *dim_map;
3978 struct isl_basic_map *res;
3979 enum isl_dim_type t;
3980 isl_size total;
3981 unsigned off;
3983 if (!bmap)
3984 return NULL;
3985 if (n == 0) {
3986 bmap = isl_basic_map_reset(bmap, src_type);
3987 bmap = isl_basic_map_reset(bmap, dst_type);
3988 return bmap;
3991 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
3992 return isl_basic_map_free(bmap);
3994 if (dst_type == src_type && dst_pos == src_pos)
3995 return bmap;
3997 isl_assert(bmap->ctx, dst_type != src_type, goto error);
3999 if (pos(bmap->dim, dst_type) + dst_pos ==
4000 pos(bmap->dim, src_type) + src_pos +
4001 ((src_type < dst_type) ? n : 0)) {
4002 bmap = isl_basic_map_cow(bmap);
4003 if (!bmap)
4004 return NULL;
4006 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4007 src_type, src_pos, n);
4008 if (!bmap->dim)
4009 goto error;
4011 bmap = isl_basic_map_finalize(bmap);
4013 return bmap;
4016 total = isl_basic_map_dim(bmap, isl_dim_all);
4017 if (total < 0)
4018 return isl_basic_map_free(bmap);
4019 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4021 off = 0;
4022 space = isl_basic_map_peek_space(bmap);
4023 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4024 isl_size size = isl_space_dim(space, t);
4025 if (size < 0)
4026 dim_map = isl_dim_map_free(dim_map);
4027 if (t == dst_type) {
4028 isl_dim_map_dim_range(dim_map, space, t,
4029 0, dst_pos, off);
4030 off += dst_pos;
4031 isl_dim_map_dim_range(dim_map, space, src_type,
4032 src_pos, n, off);
4033 off += n;
4034 isl_dim_map_dim_range(dim_map, space, t,
4035 dst_pos, size - dst_pos, off);
4036 off += size - dst_pos;
4037 } else if (t == src_type) {
4038 isl_dim_map_dim_range(dim_map, space, t,
4039 0, src_pos, off);
4040 off += src_pos;
4041 isl_dim_map_dim_range(dim_map, space, t,
4042 src_pos + n, size - src_pos - n, off);
4043 off += size - src_pos - n;
4044 } else {
4045 isl_dim_map_dim(dim_map, space, t, off);
4046 off += size;
4049 isl_dim_map_div(dim_map, bmap, off);
4051 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4052 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4053 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4054 if (!bmap)
4055 goto error;
4057 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4058 src_type, src_pos, n);
4059 if (!bmap->dim)
4060 goto error;
4062 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4063 bmap = isl_basic_map_gauss(bmap, NULL);
4064 bmap = isl_basic_map_finalize(bmap);
4066 return bmap;
4067 error:
4068 isl_basic_map_free(bmap);
4069 return NULL;
4072 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4073 enum isl_dim_type dst_type, unsigned dst_pos,
4074 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4076 isl_basic_map *bmap = bset_to_bmap(bset);
4077 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4078 src_type, src_pos, n);
4079 return bset_from_bmap(bmap);
4082 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4083 enum isl_dim_type dst_type, unsigned dst_pos,
4084 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4086 if (!set)
4087 return NULL;
4088 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4089 return set_from_map(isl_map_move_dims(set_to_map(set),
4090 dst_type, dst_pos, src_type, src_pos, n));
4091 error:
4092 isl_set_free(set);
4093 return NULL;
4096 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4097 enum isl_dim_type dst_type, unsigned dst_pos,
4098 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4100 int i;
4102 if (n == 0) {
4103 map = isl_map_reset(map, src_type);
4104 map = isl_map_reset(map, dst_type);
4105 return map;
4108 if (isl_map_check_range(map, src_type, src_pos, n))
4109 return isl_map_free(map);
4111 if (dst_type == src_type && dst_pos == src_pos)
4112 return map;
4114 isl_assert(map->ctx, dst_type != src_type, goto error);
4116 map = isl_map_cow(map);
4117 if (!map)
4118 return NULL;
4120 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
4121 if (!map->dim)
4122 goto error;
4124 for (i = 0; i < map->n; ++i) {
4125 map->p[i] = isl_basic_map_move_dims(map->p[i],
4126 dst_type, dst_pos,
4127 src_type, src_pos, n);
4128 if (!map->p[i])
4129 goto error;
4132 return map;
4133 error:
4134 isl_map_free(map);
4135 return NULL;
4138 /* Move the specified dimensions to the last columns right before
4139 * the divs. Don't change the dimension specification of bmap.
4140 * That's the responsibility of the caller.
4142 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4143 enum isl_dim_type type, unsigned first, unsigned n)
4145 isl_space *space;
4146 struct isl_dim_map *dim_map;
4147 struct isl_basic_map *res;
4148 enum isl_dim_type t;
4149 isl_size total;
4150 unsigned off;
4152 if (!bmap)
4153 return NULL;
4154 if (isl_basic_map_offset(bmap, type) + first + n ==
4155 isl_basic_map_offset(bmap, isl_dim_div))
4156 return bmap;
4158 total = isl_basic_map_dim(bmap, isl_dim_all);
4159 if (total < 0)
4160 return isl_basic_map_free(bmap);
4161 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4163 off = 0;
4164 space = isl_basic_map_peek_space(bmap);
4165 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4166 isl_size size = isl_space_dim(space, t);
4167 if (size < 0)
4168 dim_map = isl_dim_map_free(dim_map);
4169 if (t == type) {
4170 isl_dim_map_dim_range(dim_map, space, t,
4171 0, first, off);
4172 off += first;
4173 isl_dim_map_dim_range(dim_map, space, t,
4174 first, n, total - bmap->n_div - n);
4175 isl_dim_map_dim_range(dim_map, space, t,
4176 first + n, size - (first + n), off);
4177 off += size - (first + n);
4178 } else {
4179 isl_dim_map_dim(dim_map, space, t, off);
4180 off += size;
4183 isl_dim_map_div(dim_map, bmap, off + n);
4185 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4186 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4187 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4188 return res;
4191 /* Insert "n" rows in the divs of "bmap".
4193 * The number of columns is not changed, which means that the last
4194 * dimensions of "bmap" are being reintepreted as the new divs.
4195 * The space of "bmap" is not adjusted, however, which means
4196 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4197 * from the space of "bmap" is the responsibility of the caller.
4199 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4200 int n)
4202 int i;
4203 size_t row_size;
4204 isl_int **new_div;
4205 isl_int *old;
4207 bmap = isl_basic_map_cow(bmap);
4208 if (!bmap)
4209 return NULL;
4211 row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;
4212 old = bmap->block2.data;
4213 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4214 (bmap->extra + n) * (1 + row_size));
4215 if (!bmap->block2.data)
4216 return isl_basic_map_free(bmap);
4217 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4218 if (!new_div)
4219 return isl_basic_map_free(bmap);
4220 for (i = 0; i < n; ++i) {
4221 new_div[i] = bmap->block2.data +
4222 (bmap->extra + i) * (1 + row_size);
4223 isl_seq_clr(new_div[i], 1 + row_size);
4225 for (i = 0; i < bmap->extra; ++i)
4226 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4227 free(bmap->div);
4228 bmap->div = new_div;
4229 bmap->n_div += n;
4230 bmap->extra += n;
4232 return bmap;
4235 /* Drop constraints from "bmap" that only involve the variables
4236 * of "type" in the range [first, first + n] that are not related
4237 * to any of the variables outside that interval.
4238 * These constraints cannot influence the values for the variables
4239 * outside the interval, except in case they cause "bmap" to be empty.
4240 * Only drop the constraints if "bmap" is known to be non-empty.
4242 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4243 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4244 unsigned first, unsigned n)
4246 int i;
4247 int *groups;
4248 isl_size dim, n_div;
4249 isl_bool non_empty;
4251 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4252 if (non_empty < 0)
4253 return isl_basic_map_free(bmap);
4254 if (!non_empty)
4255 return bmap;
4257 dim = isl_basic_map_dim(bmap, isl_dim_all);
4258 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4259 if (dim < 0 || n_div < 0)
4260 return isl_basic_map_free(bmap);
4261 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4262 if (!groups)
4263 return isl_basic_map_free(bmap);
4264 first += isl_basic_map_offset(bmap, type) - 1;
4265 for (i = 0; i < first; ++i)
4266 groups[i] = -1;
4267 for (i = first + n; i < dim - n_div; ++i)
4268 groups[i] = -1;
4270 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4272 return bmap;
4275 /* Turn the n dimensions of type type, starting at first
4276 * into existentially quantified variables.
4278 * If a subset of the projected out variables are unrelated
4279 * to any of the variables that remain, then the constraints
4280 * involving this subset are simply dropped first.
4282 __isl_give isl_basic_map *isl_basic_map_project_out(
4283 __isl_take isl_basic_map *bmap,
4284 enum isl_dim_type type, unsigned first, unsigned n)
4286 isl_bool empty;
4288 if (n == 0)
4289 return basic_map_space_reset(bmap, type);
4290 if (type == isl_dim_div)
4291 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4292 "cannot project out existentially quantified variables",
4293 return isl_basic_map_free(bmap));
4295 empty = isl_basic_map_plain_is_empty(bmap);
4296 if (empty < 0)
4297 return isl_basic_map_free(bmap);
4298 if (empty)
4299 bmap = isl_basic_map_set_to_empty(bmap);
4301 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4302 if (!bmap)
4303 return NULL;
4305 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4306 return isl_basic_map_remove_dims(bmap, type, first, n);
4308 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4309 return isl_basic_map_free(bmap);
4311 bmap = move_last(bmap, type, first, n);
4312 bmap = isl_basic_map_cow(bmap);
4313 bmap = insert_div_rows(bmap, n);
4314 if (!bmap)
4315 return NULL;
4317 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
4318 if (!bmap->dim)
4319 goto error;
4320 bmap = isl_basic_map_simplify(bmap);
4321 bmap = isl_basic_map_drop_redundant_divs(bmap);
4322 return isl_basic_map_finalize(bmap);
4323 error:
4324 isl_basic_map_free(bmap);
4325 return NULL;
4328 /* Turn the n dimensions of type type, starting at first
4329 * into existentially quantified variables.
4331 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
4332 enum isl_dim_type type, unsigned first, unsigned n)
4334 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4335 type, first, n));
4338 /* Turn the n dimensions of type type, starting at first
4339 * into existentially quantified variables.
4341 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4342 enum isl_dim_type type, unsigned first, unsigned n)
4344 int i;
4346 if (n == 0)
4347 return map_space_reset(map, type);
4349 if (isl_map_check_range(map, type, first, n) < 0)
4350 return isl_map_free(map);
4352 map = isl_map_cow(map);
4353 if (!map)
4354 return NULL;
4356 map->dim = isl_space_drop_dims(map->dim, type, first, n);
4357 if (!map->dim)
4358 goto error;
4360 for (i = 0; i < map->n; ++i) {
4361 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4362 if (!map->p[i])
4363 goto error;
4366 return map;
4367 error:
4368 isl_map_free(map);
4369 return NULL;
4372 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4373 * into existentially quantified variables.
4375 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4376 enum isl_dim_type type, unsigned first, unsigned n)
4378 isl_size dim;
4380 dim = isl_map_dim(map, type);
4381 if (isl_map_check_range(map, type, first, n) < 0 || dim < 0)
4382 return isl_map_free(map);
4383 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4384 map = isl_map_project_out(map, type, 0, first);
4385 return map;
4388 /* Turn the n dimensions of type type, starting at first
4389 * into existentially quantified variables.
4391 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4392 enum isl_dim_type type, unsigned first, unsigned n)
4394 return set_from_map(isl_map_project_out(set_to_map(set),
4395 type, first, n));
4398 /* Return a map that projects the elements in "set" onto their
4399 * "n" set dimensions starting at "first".
4400 * "type" should be equal to isl_dim_set.
4402 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4403 enum isl_dim_type type, unsigned first, unsigned n)
4405 int i;
4406 isl_map *map;
4408 if (type != isl_dim_set)
4409 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4410 "only set dimensions can be projected out", goto error);
4411 if (isl_set_check_range(set, type, first, n) < 0)
4412 return isl_set_free(set);
4414 map = isl_map_from_domain(set);
4415 map = isl_map_add_dims(map, isl_dim_out, n);
4416 for (i = 0; i < n; ++i)
4417 map = isl_map_equate(map, isl_dim_in, first + i,
4418 isl_dim_out, i);
4419 return map;
4420 error:
4421 isl_set_free(set);
4422 return NULL;
4425 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4426 unsigned n)
4428 int i, j;
4429 isl_size total;
4431 total = isl_basic_map_dim(bmap, isl_dim_all);
4432 if (total < 0)
4433 return isl_basic_map_free(bmap);
4434 for (i = 0; i < n; ++i) {
4435 j = isl_basic_map_alloc_div(bmap);
4436 if (j < 0)
4437 goto error;
4438 isl_seq_clr(bmap->div[j], 1 + 1 + total);
4440 return bmap;
4441 error:
4442 isl_basic_map_free(bmap);
4443 return NULL;
4446 struct isl_basic_map *isl_basic_map_apply_range(
4447 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4449 isl_space *space_result = NULL;
4450 struct isl_basic_map *bmap;
4451 isl_size n_in, n_out, n, nparam;
4452 unsigned total, pos;
4453 struct isl_dim_map *dim_map1, *dim_map2;
4455 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4456 goto error;
4457 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4458 bmap2->dim, isl_dim_in))
4459 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4460 "spaces don't match", goto error);
4462 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4463 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4464 n = isl_basic_map_dim(bmap1, isl_dim_out);
4465 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4466 if (n_in < 0 || n_out < 0 || n < 0 || nparam < 0)
4467 goto error;
4469 space_result = isl_space_join(isl_basic_map_get_space(bmap1),
4470 isl_basic_map_get_space(bmap2));
4472 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4473 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4474 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4475 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4476 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4477 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4478 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4479 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4480 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4481 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4482 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4484 bmap = isl_basic_map_alloc_space(space_result,
4485 bmap1->n_div + bmap2->n_div + n,
4486 bmap1->n_eq + bmap2->n_eq,
4487 bmap1->n_ineq + bmap2->n_ineq);
4488 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4489 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4490 bmap = add_divs(bmap, n);
4491 bmap = isl_basic_map_simplify(bmap);
4492 bmap = isl_basic_map_drop_redundant_divs(bmap);
4493 return isl_basic_map_finalize(bmap);
4494 error:
4495 isl_basic_map_free(bmap1);
4496 isl_basic_map_free(bmap2);
4497 return NULL;
4500 struct isl_basic_set *isl_basic_set_apply(
4501 struct isl_basic_set *bset, struct isl_basic_map *bmap)
4503 if (!bset || !bmap)
4504 goto error;
4506 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4507 goto error);
4509 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4510 bmap));
4511 error:
4512 isl_basic_set_free(bset);
4513 isl_basic_map_free(bmap);
4514 return NULL;
4517 struct isl_basic_map *isl_basic_map_apply_domain(
4518 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4520 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4521 goto error;
4522 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4523 bmap2->dim, isl_dim_in))
4524 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4525 "spaces don't match", goto error);
4527 bmap1 = isl_basic_map_reverse(bmap1);
4528 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4529 return isl_basic_map_reverse(bmap1);
4530 error:
4531 isl_basic_map_free(bmap1);
4532 isl_basic_map_free(bmap2);
4533 return NULL;
4536 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4537 * A \cap B -> f(A) + f(B)
4539 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4540 __isl_take isl_basic_map *bmap2)
4542 isl_size n_in, n_out, nparam;
4543 unsigned total, pos;
4544 struct isl_basic_map *bmap = NULL;
4545 struct isl_dim_map *dim_map1, *dim_map2;
4546 int i;
4548 if (!bmap1 || !bmap2)
4549 goto error;
4551 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4552 goto error);
4554 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4555 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4556 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4557 if (nparam < 0 || n_in < 0 || n_out < 0)
4558 goto error;
4560 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4561 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4562 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4563 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4564 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4565 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4566 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4567 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4568 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4569 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4570 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4572 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4573 bmap1->n_div + bmap2->n_div + 2 * n_out,
4574 bmap1->n_eq + bmap2->n_eq + n_out,
4575 bmap1->n_ineq + bmap2->n_ineq);
4576 for (i = 0; i < n_out; ++i) {
4577 int j = isl_basic_map_alloc_equality(bmap);
4578 if (j < 0)
4579 goto error;
4580 isl_seq_clr(bmap->eq[j], 1+total);
4581 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4582 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4583 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4585 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4586 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4587 bmap = add_divs(bmap, 2 * n_out);
4589 bmap = isl_basic_map_simplify(bmap);
4590 return isl_basic_map_finalize(bmap);
4591 error:
4592 isl_basic_map_free(bmap);
4593 isl_basic_map_free(bmap1);
4594 isl_basic_map_free(bmap2);
4595 return NULL;
4598 /* Given two maps A -> f(A) and B -> g(B), construct a map
4599 * A \cap B -> f(A) + f(B)
4601 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4602 __isl_take isl_map *map2)
4604 struct isl_map *result;
4605 int i, j;
4607 if (!map1 || !map2)
4608 goto error;
4610 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4612 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4613 map1->n * map2->n, 0);
4614 if (!result)
4615 goto error;
4616 for (i = 0; i < map1->n; ++i)
4617 for (j = 0; j < map2->n; ++j) {
4618 struct isl_basic_map *part;
4619 part = isl_basic_map_sum(
4620 isl_basic_map_copy(map1->p[i]),
4621 isl_basic_map_copy(map2->p[j]));
4622 if (isl_basic_map_is_empty(part))
4623 isl_basic_map_free(part);
4624 else
4625 result = isl_map_add_basic_map(result, part);
4626 if (!result)
4627 goto error;
4629 isl_map_free(map1);
4630 isl_map_free(map2);
4631 return result;
4632 error:
4633 isl_map_free(map1);
4634 isl_map_free(map2);
4635 return NULL;
4638 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4639 __isl_take isl_set *set2)
4641 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4644 /* Given a basic map A -> f(A), construct A -> -f(A).
4646 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4648 int i, j;
4649 unsigned off;
4650 isl_size n;
4652 bmap = isl_basic_map_cow(bmap);
4653 n = isl_basic_map_dim(bmap, isl_dim_out);
4654 if (n < 0)
4655 return isl_basic_map_free(bmap);
4657 off = isl_basic_map_offset(bmap, isl_dim_out);
4658 for (i = 0; i < bmap->n_eq; ++i)
4659 for (j = 0; j < n; ++j)
4660 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4661 for (i = 0; i < bmap->n_ineq; ++i)
4662 for (j = 0; j < n; ++j)
4663 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4664 for (i = 0; i < bmap->n_div; ++i)
4665 for (j = 0; j < n; ++j)
4666 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4667 bmap = isl_basic_map_gauss(bmap, NULL);
4668 return isl_basic_map_finalize(bmap);
4671 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4673 return isl_basic_map_neg(bset);
4676 /* Given a map A -> f(A), construct A -> -f(A).
4678 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4680 int i;
4682 map = isl_map_cow(map);
4683 if (!map)
4684 return NULL;
4686 for (i = 0; i < map->n; ++i) {
4687 map->p[i] = isl_basic_map_neg(map->p[i]);
4688 if (!map->p[i])
4689 goto error;
4692 return map;
4693 error:
4694 isl_map_free(map);
4695 return NULL;
4698 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4700 return set_from_map(isl_map_neg(set_to_map(set)));
4703 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4704 * A -> floor(f(A)/d).
4706 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4707 isl_int d)
4709 isl_size n_in, n_out, nparam;
4710 unsigned total, pos;
4711 struct isl_basic_map *result = NULL;
4712 struct isl_dim_map *dim_map;
4713 int i;
4715 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4716 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4717 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4718 if (nparam < 0 || n_in < 0 || n_out < 0)
4719 return isl_basic_map_free(bmap);
4721 total = nparam + n_in + n_out + bmap->n_div + n_out;
4722 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4723 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4724 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4725 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4726 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4728 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4729 bmap->n_div + n_out,
4730 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4731 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4732 result = add_divs(result, n_out);
4733 for (i = 0; i < n_out; ++i) {
4734 int j;
4735 j = isl_basic_map_alloc_inequality(result);
4736 if (j < 0)
4737 goto error;
4738 isl_seq_clr(result->ineq[j], 1+total);
4739 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4740 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4741 j = isl_basic_map_alloc_inequality(result);
4742 if (j < 0)
4743 goto error;
4744 isl_seq_clr(result->ineq[j], 1+total);
4745 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4746 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4747 isl_int_sub_ui(result->ineq[j][0], d, 1);
4750 result = isl_basic_map_simplify(result);
4751 return isl_basic_map_finalize(result);
4752 error:
4753 isl_basic_map_free(result);
4754 return NULL;
4757 /* Given a map A -> f(A) and an integer d, construct a map
4758 * A -> floor(f(A)/d).
4760 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4762 int i;
4764 map = isl_map_cow(map);
4765 if (!map)
4766 return NULL;
4768 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4769 for (i = 0; i < map->n; ++i) {
4770 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4771 if (!map->p[i])
4772 goto error;
4774 map = isl_map_unmark_normalized(map);
4776 return map;
4777 error:
4778 isl_map_free(map);
4779 return NULL;
4782 /* Given a map A -> f(A) and an integer d, construct a map
4783 * A -> floor(f(A)/d).
4785 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4786 __isl_take isl_val *d)
4788 if (!map || !d)
4789 goto error;
4790 if (!isl_val_is_int(d))
4791 isl_die(isl_val_get_ctx(d), isl_error_invalid,
4792 "expecting integer denominator", goto error);
4793 map = isl_map_floordiv(map, d->n);
4794 isl_val_free(d);
4795 return map;
4796 error:
4797 isl_map_free(map);
4798 isl_val_free(d);
4799 return NULL;
4802 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
4803 unsigned pos)
4805 int i;
4806 isl_size nparam;
4807 isl_size n_in;
4808 isl_size total;
4810 total = isl_basic_map_dim(bmap, isl_dim_all);
4811 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4812 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4813 if (total < 0 || nparam < 0 || n_in < 0)
4814 return isl_basic_map_free(bmap);
4815 i = isl_basic_map_alloc_equality(bmap);
4816 if (i < 0)
4817 goto error;
4818 isl_seq_clr(bmap->eq[i], 1 + total);
4819 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4820 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4821 return isl_basic_map_finalize(bmap);
4822 error:
4823 isl_basic_map_free(bmap);
4824 return NULL;
4827 /* Add a constraint to "bmap" expressing i_pos < o_pos
4829 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
4830 unsigned pos)
4832 int i;
4833 isl_size nparam;
4834 isl_size n_in;
4835 isl_size total;
4837 total = isl_basic_map_dim(bmap, isl_dim_all);
4838 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4839 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4840 if (total < 0 || nparam < 0 || n_in < 0)
4841 return isl_basic_map_free(bmap);
4842 i = isl_basic_map_alloc_inequality(bmap);
4843 if (i < 0)
4844 goto error;
4845 isl_seq_clr(bmap->ineq[i], 1 + total);
4846 isl_int_set_si(bmap->ineq[i][0], -1);
4847 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4848 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4849 return isl_basic_map_finalize(bmap);
4850 error:
4851 isl_basic_map_free(bmap);
4852 return NULL;
4855 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4857 static __isl_give isl_basic_map *var_less_or_equal(
4858 __isl_take isl_basic_map *bmap, unsigned pos)
4860 int i;
4861 isl_size nparam;
4862 isl_size n_in;
4863 isl_size total;
4865 total = isl_basic_map_dim(bmap, isl_dim_all);
4866 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4867 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4868 if (total < 0 || nparam < 0 || n_in < 0)
4869 return isl_basic_map_free(bmap);
4870 i = isl_basic_map_alloc_inequality(bmap);
4871 if (i < 0)
4872 goto error;
4873 isl_seq_clr(bmap->ineq[i], 1 + total);
4874 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4875 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4876 return isl_basic_map_finalize(bmap);
4877 error:
4878 isl_basic_map_free(bmap);
4879 return NULL;
4882 /* Add a constraint to "bmap" expressing i_pos > o_pos
4884 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
4885 unsigned pos)
4887 int i;
4888 isl_size nparam;
4889 isl_size n_in;
4890 isl_size total;
4892 total = isl_basic_map_dim(bmap, isl_dim_all);
4893 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4894 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4895 if (total < 0 || nparam < 0 || n_in < 0)
4896 return isl_basic_map_free(bmap);
4897 i = isl_basic_map_alloc_inequality(bmap);
4898 if (i < 0)
4899 goto error;
4900 isl_seq_clr(bmap->ineq[i], 1 + total);
4901 isl_int_set_si(bmap->ineq[i][0], -1);
4902 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4903 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4904 return isl_basic_map_finalize(bmap);
4905 error:
4906 isl_basic_map_free(bmap);
4907 return NULL;
4910 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4912 static __isl_give isl_basic_map *var_more_or_equal(
4913 __isl_take isl_basic_map *bmap, unsigned pos)
4915 int i;
4916 isl_size nparam;
4917 isl_size n_in;
4918 isl_size total;
4920 total = isl_basic_map_dim(bmap, isl_dim_all);
4921 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4922 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4923 if (total < 0 || nparam < 0 || n_in < 0)
4924 return isl_basic_map_free(bmap);
4925 i = isl_basic_map_alloc_inequality(bmap);
4926 if (i < 0)
4927 goto error;
4928 isl_seq_clr(bmap->ineq[i], 1 + total);
4929 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4930 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4931 return isl_basic_map_finalize(bmap);
4932 error:
4933 isl_basic_map_free(bmap);
4934 return NULL;
4937 __isl_give isl_basic_map *isl_basic_map_equal(
4938 __isl_take isl_space *space, unsigned n_equal)
4940 int i;
4941 struct isl_basic_map *bmap;
4942 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
4943 if (!bmap)
4944 return NULL;
4945 for (i = 0; i < n_equal && bmap; ++i)
4946 bmap = var_equal(bmap, i);
4947 return isl_basic_map_finalize(bmap);
4950 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
4952 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
4953 unsigned pos)
4955 int i;
4956 struct isl_basic_map *bmap;
4957 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4958 if (!bmap)
4959 return NULL;
4960 for (i = 0; i < pos && bmap; ++i)
4961 bmap = var_equal(bmap, i);
4962 if (bmap)
4963 bmap = var_less(bmap, pos);
4964 return isl_basic_map_finalize(bmap);
4967 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
4969 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4970 __isl_take isl_space *space, unsigned pos)
4972 int i;
4973 isl_basic_map *bmap;
4975 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4976 for (i = 0; i < pos; ++i)
4977 bmap = var_equal(bmap, i);
4978 bmap = var_less_or_equal(bmap, pos);
4979 return isl_basic_map_finalize(bmap);
4982 /* Return a relation on "space" expressing i_pos > o_pos
4984 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
4985 unsigned pos)
4987 int i;
4988 struct isl_basic_map *bmap;
4989 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4990 if (!bmap)
4991 return NULL;
4992 for (i = 0; i < pos && bmap; ++i)
4993 bmap = var_equal(bmap, i);
4994 if (bmap)
4995 bmap = var_more(bmap, pos);
4996 return isl_basic_map_finalize(bmap);
4999 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
5001 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
5002 __isl_take isl_space *space, unsigned pos)
5004 int i;
5005 isl_basic_map *bmap;
5007 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5008 for (i = 0; i < pos; ++i)
5009 bmap = var_equal(bmap, i);
5010 bmap = var_more_or_equal(bmap, pos);
5011 return isl_basic_map_finalize(bmap);
5014 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
5015 unsigned n, int equal)
5017 struct isl_map *map;
5018 int i;
5020 if (n == 0 && equal)
5021 return isl_map_universe(space);
5023 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5025 for (i = 0; i + 1 < n; ++i)
5026 map = isl_map_add_basic_map(map,
5027 isl_basic_map_less_at(isl_space_copy(space), i));
5028 if (n > 0) {
5029 if (equal)
5030 map = isl_map_add_basic_map(map,
5031 isl_basic_map_less_or_equal_at(space, n - 1));
5032 else
5033 map = isl_map_add_basic_map(map,
5034 isl_basic_map_less_at(space, n - 1));
5035 } else
5036 isl_space_free(space);
5038 return map;
5041 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
5043 if (!space)
5044 return NULL;
5045 return map_lex_lte_first(space, space->n_out, equal);
5048 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
5050 return map_lex_lte_first(dim, n, 0);
5053 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
5055 return map_lex_lte_first(dim, n, 1);
5058 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
5060 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
5063 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
5065 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
5068 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5069 unsigned n, int equal)
5071 struct isl_map *map;
5072 int i;
5074 if (n == 0 && equal)
5075 return isl_map_universe(space);
5077 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5079 for (i = 0; i + 1 < n; ++i)
5080 map = isl_map_add_basic_map(map,
5081 isl_basic_map_more_at(isl_space_copy(space), i));
5082 if (n > 0) {
5083 if (equal)
5084 map = isl_map_add_basic_map(map,
5085 isl_basic_map_more_or_equal_at(space, n - 1));
5086 else
5087 map = isl_map_add_basic_map(map,
5088 isl_basic_map_more_at(space, n - 1));
5089 } else
5090 isl_space_free(space);
5092 return map;
5095 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5097 if (!space)
5098 return NULL;
5099 return map_lex_gte_first(space, space->n_out, equal);
5102 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
5104 return map_lex_gte_first(dim, n, 0);
5107 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
5109 return map_lex_gte_first(dim, n, 1);
5112 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
5114 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
5117 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
5119 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
5122 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5123 __isl_take isl_set *set2)
5125 isl_map *map;
5126 map = isl_map_lex_le(isl_set_get_space(set1));
5127 map = isl_map_intersect_domain(map, set1);
5128 map = isl_map_intersect_range(map, set2);
5129 return map;
5132 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5133 __isl_take isl_set *set2)
5135 isl_map *map;
5136 map = isl_map_lex_lt(isl_set_get_space(set1));
5137 map = isl_map_intersect_domain(map, set1);
5138 map = isl_map_intersect_range(map, set2);
5139 return map;
5142 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5143 __isl_take isl_set *set2)
5145 isl_map *map;
5146 map = isl_map_lex_ge(isl_set_get_space(set1));
5147 map = isl_map_intersect_domain(map, set1);
5148 map = isl_map_intersect_range(map, set2);
5149 return map;
5152 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5153 __isl_take isl_set *set2)
5155 isl_map *map;
5156 map = isl_map_lex_gt(isl_set_get_space(set1));
5157 map = isl_map_intersect_domain(map, set1);
5158 map = isl_map_intersect_range(map, set2);
5159 return map;
5162 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5163 __isl_take isl_map *map2)
5165 isl_map *map;
5166 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5167 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5168 map = isl_map_apply_range(map, isl_map_reverse(map2));
5169 return map;
5172 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5173 __isl_take isl_map *map2)
5175 isl_map *map;
5176 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5177 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5178 map = isl_map_apply_range(map, isl_map_reverse(map2));
5179 return map;
5182 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5183 __isl_take isl_map *map2)
5185 isl_map *map;
5186 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5187 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5188 map = isl_map_apply_range(map, isl_map_reverse(map2));
5189 return map;
5192 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5193 __isl_take isl_map *map2)
5195 isl_map *map;
5196 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5197 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5198 map = isl_map_apply_range(map, isl_map_reverse(map2));
5199 return map;
5202 /* For the div d = floor(f/m) at position "div", add the constraint
5204 * f - m d >= 0
5206 static __isl_give isl_basic_map *add_upper_div_constraint(
5207 __isl_take isl_basic_map *bmap, unsigned div)
5209 int i;
5210 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5211 isl_size n_div;
5212 unsigned pos;
5214 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5215 if (v_div < 0 || n_div < 0)
5216 return isl_basic_map_free(bmap);
5217 pos = v_div + div;
5218 i = isl_basic_map_alloc_inequality(bmap);
5219 if (i < 0)
5220 return isl_basic_map_free(bmap);
5221 isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5222 isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5224 return bmap;
5227 /* For the div d = floor(f/m) at position "div", add the constraint
5229 * -(f-(m-1)) + m d >= 0
5231 static __isl_give isl_basic_map *add_lower_div_constraint(
5232 __isl_take isl_basic_map *bmap, unsigned div)
5234 int i;
5235 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5236 isl_size n_div;
5237 unsigned pos;
5239 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5240 if (v_div < 0 || n_div < 0)
5241 return isl_basic_map_free(bmap);
5242 pos = v_div + div;
5243 i = isl_basic_map_alloc_inequality(bmap);
5244 if (i < 0)
5245 return isl_basic_map_free(bmap);
5246 isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5247 isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5248 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5249 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5251 return bmap;
5254 /* For the div d = floor(f/m) at position "pos", add the constraints
5256 * f - m d >= 0
5257 * -(f-(m-1)) + m d >= 0
5259 * Note that the second constraint is the negation of
5261 * f - m d >= m
5263 __isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5264 __isl_take isl_basic_map *bmap, unsigned pos)
5266 bmap = add_upper_div_constraint(bmap, pos);
5267 bmap = add_lower_div_constraint(bmap, pos);
5268 return bmap;
5271 /* For each known div d = floor(f/m), add the constraints
5273 * f - m d >= 0
5274 * -(f-(m-1)) + m d >= 0
5276 * Remove duplicate constraints in case of some these div constraints
5277 * already appear in "bmap".
5279 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5280 __isl_take isl_basic_map *bmap)
5282 isl_size n_div;
5284 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5285 if (n_div < 0)
5286 return isl_basic_map_free(bmap);
5287 if (n_div == 0)
5288 return bmap;
5290 bmap = add_known_div_constraints(bmap);
5291 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5292 bmap = isl_basic_map_finalize(bmap);
5293 return bmap;
5296 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5298 * In particular, if this div is of the form d = floor(f/m),
5299 * then add the constraint
5301 * f - m d >= 0
5303 * if sign < 0 or the constraint
5305 * -(f-(m-1)) + m d >= 0
5307 * if sign > 0.
5309 __isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5310 __isl_take isl_basic_map *bmap, unsigned div, int sign)
5312 if (sign < 0)
5313 return add_upper_div_constraint(bmap, div);
5314 else
5315 return add_lower_div_constraint(bmap, div);
5318 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5319 __isl_take isl_basic_map *bmap)
5321 if (!bmap)
5322 goto error;
5323 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5324 bmap->n_div == 0 &&
5325 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5326 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5327 return bset_from_bmap(bmap);
5328 bmap = isl_basic_map_cow(bmap);
5329 if (!bmap)
5330 goto error;
5331 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
5332 if (!bmap->dim)
5333 goto error;
5334 bmap->extra -= bmap->n_div;
5335 bmap->n_div = 0;
5336 bmap = isl_basic_map_finalize(bmap);
5337 return bset_from_bmap(bmap);
5338 error:
5339 isl_basic_map_free(bmap);
5340 return NULL;
5343 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5344 __isl_take isl_basic_set *bset)
5346 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5349 /* Replace each element in "list" by the result of applying
5350 * isl_basic_map_underlying_set to the element.
5352 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5353 __isl_take isl_basic_map_list *list)
5355 int i;
5356 isl_size n;
5358 n = isl_basic_map_list_n_basic_map(list);
5359 if (n < 0)
5360 goto error;
5362 for (i = 0; i < n; ++i) {
5363 isl_basic_map *bmap;
5364 isl_basic_set *bset;
5366 bmap = isl_basic_map_list_get_basic_map(list, i);
5367 bset = isl_basic_set_underlying_set(bmap);
5368 list = isl_basic_set_list_set_basic_set(list, i, bset);
5371 return list;
5372 error:
5373 isl_basic_map_list_free(list);
5374 return NULL;
5377 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5378 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5380 struct isl_basic_map *bmap;
5381 struct isl_ctx *ctx;
5382 isl_size dim, bmap_total;
5383 unsigned total;
5384 int i;
5386 if (!bset || !like)
5387 goto error;
5388 ctx = bset->ctx;
5389 if (isl_basic_set_check_no_params(bset) < 0 ||
5390 isl_basic_set_check_no_locals(bset) < 0)
5391 goto error;
5392 dim = isl_basic_set_dim(bset, isl_dim_set);
5393 bmap_total = isl_basic_map_dim(like, isl_dim_all);
5394 if (dim < 0 || bmap_total < 0)
5395 goto error;
5396 isl_assert(ctx, dim == bmap_total, goto error);
5397 if (like->n_div == 0) {
5398 isl_space *space = isl_basic_map_get_space(like);
5399 isl_basic_map_free(like);
5400 return isl_basic_map_reset_space(bset, space);
5402 bset = isl_basic_set_cow(bset);
5403 if (!bset)
5404 goto error;
5405 total = dim + bset->extra;
5406 bmap = bset_to_bmap(bset);
5407 isl_space_free(bmap->dim);
5408 bmap->dim = isl_space_copy(like->dim);
5409 if (!bmap->dim)
5410 goto error;
5411 bmap->n_div = like->n_div;
5412 bmap->extra += like->n_div;
5413 if (bmap->extra) {
5414 unsigned ltotal;
5415 isl_int **div;
5416 ltotal = total - bmap->extra + like->extra;
5417 if (ltotal > total)
5418 ltotal = total;
5419 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5420 bmap->extra * (1 + 1 + total));
5421 if (isl_blk_is_error(bmap->block2))
5422 goto error;
5423 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5424 if (!div)
5425 goto error;
5426 bmap->div = div;
5427 for (i = 0; i < bmap->extra; ++i)
5428 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5429 for (i = 0; i < like->n_div; ++i) {
5430 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5431 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5433 bmap = isl_basic_map_add_known_div_constraints(bmap);
5435 isl_basic_map_free(like);
5436 bmap = isl_basic_map_simplify(bmap);
5437 bmap = isl_basic_map_finalize(bmap);
5438 return bmap;
5439 error:
5440 isl_basic_map_free(like);
5441 isl_basic_set_free(bset);
5442 return NULL;
5445 struct isl_basic_set *isl_basic_set_from_underlying_set(
5446 struct isl_basic_set *bset, struct isl_basic_set *like)
5448 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5449 bset_to_bmap(like)));
5452 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5454 int i;
5456 map = isl_map_cow(map);
5457 if (!map)
5458 return NULL;
5459 map->dim = isl_space_cow(map->dim);
5460 if (!map->dim)
5461 goto error;
5463 for (i = 1; i < map->n; ++i)
5464 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5465 goto error);
5466 for (i = 0; i < map->n; ++i) {
5467 map->p[i] = bset_to_bmap(
5468 isl_basic_map_underlying_set(map->p[i]));
5469 if (!map->p[i])
5470 goto error;
5472 if (map->n == 0)
5473 map->dim = isl_space_underlying(map->dim, 0);
5474 else {
5475 isl_space_free(map->dim);
5476 map->dim = isl_space_copy(map->p[0]->dim);
5478 if (!map->dim)
5479 goto error;
5480 return set_from_map(map);
5481 error:
5482 isl_map_free(map);
5483 return NULL;
5486 /* Replace the space of "bmap" by "space".
5488 * If the space of "bmap" is identical to "space" (including the identifiers
5489 * of the input and output dimensions), then simply return the original input.
5491 __isl_give isl_basic_map *isl_basic_map_reset_space(
5492 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5494 isl_bool equal;
5495 isl_space *bmap_space;
5497 bmap_space = isl_basic_map_peek_space(bmap);
5498 equal = isl_space_is_equal(bmap_space, space);
5499 if (equal >= 0 && equal)
5500 equal = isl_space_has_equal_ids(bmap_space, space);
5501 if (equal < 0)
5502 goto error;
5503 if (equal) {
5504 isl_space_free(space);
5505 return bmap;
5507 bmap = isl_basic_map_cow(bmap);
5508 if (!bmap || !space)
5509 goto error;
5511 isl_space_free(bmap->dim);
5512 bmap->dim = space;
5514 bmap = isl_basic_map_finalize(bmap);
5516 return bmap;
5517 error:
5518 isl_basic_map_free(bmap);
5519 isl_space_free(space);
5520 return NULL;
5523 __isl_give isl_basic_set *isl_basic_set_reset_space(
5524 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5526 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5527 dim));
5530 /* Check that the total dimensions of "map" and "space" are the same.
5532 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5533 __isl_keep isl_space *space)
5535 isl_size dim1, dim2;
5537 dim1 = isl_map_dim(map, isl_dim_all);
5538 dim2 = isl_space_dim(space, isl_dim_all);
5539 if (dim1 < 0 || dim2 < 0)
5540 return isl_stat_error;
5541 if (dim1 == dim2)
5542 return isl_stat_ok;
5543 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5544 "total dimensions do not match", return isl_stat_error);
5547 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5548 __isl_take isl_space *space)
5550 int i;
5552 map = isl_map_cow(map);
5553 if (!map || !space)
5554 goto error;
5556 for (i = 0; i < map->n; ++i) {
5557 map->p[i] = isl_basic_map_reset_space(map->p[i],
5558 isl_space_copy(space));
5559 if (!map->p[i])
5560 goto error;
5562 isl_space_free(map->dim);
5563 map->dim = space;
5565 return map;
5566 error:
5567 isl_map_free(map);
5568 isl_space_free(space);
5569 return NULL;
5572 /* Replace the space of "map" by "space", without modifying
5573 * the dimension of "map".
5575 * If the space of "map" is identical to "space" (including the identifiers
5576 * of the input and output dimensions), then simply return the original input.
5578 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5579 __isl_take isl_space *space)
5581 isl_bool equal;
5582 isl_space *map_space;
5584 map_space = isl_map_peek_space(map);
5585 equal = isl_space_is_equal(map_space, space);
5586 if (equal >= 0 && equal)
5587 equal = isl_space_has_equal_ids(map_space, space);
5588 if (equal < 0)
5589 goto error;
5590 if (equal) {
5591 isl_space_free(space);
5592 return map;
5594 if (check_map_space_equal_total_dim(map, space) < 0)
5595 goto error;
5596 return isl_map_reset_space(map, space);
5597 error:
5598 isl_map_free(map);
5599 isl_space_free(space);
5600 return NULL;
5603 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5604 __isl_take isl_space *dim)
5606 return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5609 /* Compute the parameter domain of the given basic set.
5611 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5613 isl_bool is_params;
5614 isl_space *space;
5615 isl_size n;
5617 is_params = isl_basic_set_is_params(bset);
5618 if (is_params < 0)
5619 return isl_basic_set_free(bset);
5620 if (is_params)
5621 return bset;
5623 n = isl_basic_set_dim(bset, isl_dim_set);
5624 if (n < 0)
5625 return isl_basic_set_free(bset);
5626 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5627 space = isl_basic_set_get_space(bset);
5628 space = isl_space_params(space);
5629 bset = isl_basic_set_reset_space(bset, space);
5630 return bset;
5633 /* Construct a zero-dimensional basic set with the given parameter domain.
5635 __isl_give isl_basic_set *isl_basic_set_from_params(
5636 __isl_take isl_basic_set *bset)
5638 isl_space *space;
5639 space = isl_basic_set_get_space(bset);
5640 space = isl_space_set_from_params(space);
5641 bset = isl_basic_set_reset_space(bset, space);
5642 return bset;
5645 /* Compute the parameter domain of the given set.
5647 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5649 return isl_map_params(set_to_map(set));
5652 /* Construct a zero-dimensional set with the given parameter domain.
5654 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5656 isl_space *space;
5657 space = isl_set_get_space(set);
5658 space = isl_space_set_from_params(space);
5659 set = isl_set_reset_space(set, space);
5660 return set;
5663 /* Compute the parameter domain of the given map.
5665 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5667 isl_space *space;
5668 isl_size n_in, n_out;
5670 n_in = isl_map_dim(map, isl_dim_in);
5671 n_out = isl_map_dim(map, isl_dim_out);
5672 if (n_in < 0 || n_out < 0)
5673 return isl_map_free(map);
5674 map = isl_map_project_out(map, isl_dim_in, 0, n_in);
5675 map = isl_map_project_out(map, isl_dim_out, 0, n_out);
5676 space = isl_map_get_space(map);
5677 space = isl_space_params(space);
5678 map = isl_map_reset_space(map, space);
5679 return map;
5682 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5684 isl_space *space;
5685 isl_size n_out;
5687 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5688 if (n_out < 0)
5689 return isl_basic_map_free(bmap);
5690 space = isl_space_domain(isl_basic_map_get_space(bmap));
5692 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5694 return isl_basic_map_reset_space(bmap, space);
5697 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5699 if (!bmap)
5700 return isl_bool_error;
5701 return isl_space_may_be_set(bmap->dim);
5704 /* Is this basic map actually a set?
5705 * Users should never call this function. Outside of isl,
5706 * the type should indicate whether something is a set or a map.
5708 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5710 if (!bmap)
5711 return isl_bool_error;
5712 return isl_space_is_set(bmap->dim);
5715 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5717 isl_bool is_set;
5719 is_set = isl_basic_map_is_set(bmap);
5720 if (is_set < 0)
5721 goto error;
5722 if (is_set)
5723 return bmap;
5724 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5725 error:
5726 isl_basic_map_free(bmap);
5727 return NULL;
5730 __isl_give isl_basic_map *isl_basic_map_domain_map(
5731 __isl_take isl_basic_map *bmap)
5733 int i;
5734 isl_space *space;
5735 isl_basic_map *domain;
5736 isl_size nparam, n_in, n_out;
5738 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5739 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5740 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5741 if (nparam < 0 || n_in < 0 || n_out < 0)
5742 return isl_basic_map_free(bmap);
5744 space = isl_basic_map_get_space(bmap);
5745 space = isl_space_from_range(isl_space_domain(space));
5746 domain = isl_basic_map_universe(space);
5748 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5749 bmap = isl_basic_map_apply_range(bmap, domain);
5750 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5752 for (i = 0; i < n_in; ++i)
5753 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5754 isl_dim_out, i);
5756 bmap = isl_basic_map_gauss(bmap, NULL);
5757 return isl_basic_map_finalize(bmap);
5760 __isl_give isl_basic_map *isl_basic_map_range_map(
5761 __isl_take isl_basic_map *bmap)
5763 int i;
5764 isl_space *space;
5765 isl_basic_map *range;
5766 isl_size nparam, n_in, n_out;
5768 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5769 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5770 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5771 if (nparam < 0 || n_in < 0 || n_out < 0)
5772 return isl_basic_map_free(bmap);
5774 space = isl_basic_map_get_space(bmap);
5775 space = isl_space_from_range(isl_space_range(space));
5776 range = isl_basic_map_universe(space);
5778 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5779 bmap = isl_basic_map_apply_range(bmap, range);
5780 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5782 for (i = 0; i < n_out; ++i)
5783 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5784 isl_dim_out, i);
5786 bmap = isl_basic_map_gauss(bmap, NULL);
5787 return isl_basic_map_finalize(bmap);
5790 int isl_map_may_be_set(__isl_keep isl_map *map)
5792 if (!map)
5793 return -1;
5794 return isl_space_may_be_set(map->dim);
5797 /* Is this map actually a set?
5798 * Users should never call this function. Outside of isl,
5799 * the type should indicate whether something is a set or a map.
5801 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5803 if (!map)
5804 return isl_bool_error;
5805 return isl_space_is_set(map->dim);
5808 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
5810 int i;
5811 isl_bool is_set;
5812 struct isl_set *set;
5814 is_set = isl_map_is_set(map);
5815 if (is_set < 0)
5816 goto error;
5817 if (is_set)
5818 return set_from_map(map);
5820 map = isl_map_cow(map);
5821 if (!map)
5822 goto error;
5824 set = set_from_map(map);
5825 set->dim = isl_space_range(set->dim);
5826 if (!set->dim)
5827 goto error;
5828 for (i = 0; i < map->n; ++i) {
5829 set->p[i] = isl_basic_map_range(map->p[i]);
5830 if (!set->p[i])
5831 goto error;
5833 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5834 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5835 return set;
5836 error:
5837 isl_map_free(map);
5838 return NULL;
5841 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5843 int i;
5845 map = isl_map_cow(map);
5846 if (!map)
5847 return NULL;
5849 map->dim = isl_space_domain_map(map->dim);
5850 if (!map->dim)
5851 goto error;
5852 for (i = 0; i < map->n; ++i) {
5853 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5854 if (!map->p[i])
5855 goto error;
5857 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5858 map = isl_map_unmark_normalized(map);
5859 return map;
5860 error:
5861 isl_map_free(map);
5862 return NULL;
5865 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5867 int i;
5868 isl_space *range_dim;
5870 map = isl_map_cow(map);
5871 if (!map)
5872 return NULL;
5874 range_dim = isl_space_range(isl_map_get_space(map));
5875 range_dim = isl_space_from_range(range_dim);
5876 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5877 map->dim = isl_space_join(map->dim, range_dim);
5878 if (!map->dim)
5879 goto error;
5880 for (i = 0; i < map->n; ++i) {
5881 map->p[i] = isl_basic_map_range_map(map->p[i]);
5882 if (!map->p[i])
5883 goto error;
5885 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5886 map = isl_map_unmark_normalized(map);
5887 return map;
5888 error:
5889 isl_map_free(map);
5890 return NULL;
5893 /* Given a wrapped map of the form A[B -> C],
5894 * return the map A[B -> C] -> B.
5896 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5898 isl_id *id;
5899 isl_map *map;
5901 if (!set)
5902 return NULL;
5903 if (!isl_set_has_tuple_id(set))
5904 return isl_map_domain_map(isl_set_unwrap(set));
5906 id = isl_set_get_tuple_id(set);
5907 map = isl_map_domain_map(isl_set_unwrap(set));
5908 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5910 return map;
5913 __isl_give isl_basic_map *isl_basic_map_from_domain(
5914 __isl_take isl_basic_set *bset)
5916 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5919 __isl_give isl_basic_map *isl_basic_map_from_range(
5920 __isl_take isl_basic_set *bset)
5922 isl_space *space;
5923 space = isl_basic_set_get_space(bset);
5924 space = isl_space_from_range(space);
5925 bset = isl_basic_set_reset_space(bset, space);
5926 return bset_to_bmap(bset);
5929 /* Create a relation with the given set as range.
5930 * The domain of the created relation is a zero-dimensional
5931 * flat anonymous space.
5933 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5935 isl_space *space;
5936 space = isl_set_get_space(set);
5937 space = isl_space_from_range(space);
5938 set = isl_set_reset_space(set, space);
5939 return set_to_map(set);
5942 /* Create a relation with the given set as domain.
5943 * The range of the created relation is a zero-dimensional
5944 * flat anonymous space.
5946 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5948 return isl_map_reverse(isl_map_from_range(set));
5951 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5952 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5954 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5957 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5958 __isl_take isl_set *range)
5960 return isl_map_apply_range(isl_map_reverse(domain), range);
5963 /* Return a newly allocated isl_map with given space and flags and
5964 * room for "n" basic maps.
5965 * Make sure that all cached information is cleared.
5967 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5968 unsigned flags)
5970 struct isl_map *map;
5972 if (!space)
5973 return NULL;
5974 if (n < 0)
5975 isl_die(space->ctx, isl_error_internal,
5976 "negative number of basic maps", goto error);
5977 map = isl_calloc(space->ctx, struct isl_map,
5978 sizeof(struct isl_map) +
5979 (n - 1) * sizeof(struct isl_basic_map *));
5980 if (!map)
5981 goto error;
5983 map->ctx = space->ctx;
5984 isl_ctx_ref(map->ctx);
5985 map->ref = 1;
5986 map->size = n;
5987 map->n = 0;
5988 map->dim = space;
5989 map->flags = flags;
5990 return map;
5991 error:
5992 isl_space_free(space);
5993 return NULL;
5996 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
5998 struct isl_basic_map *bmap;
5999 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
6000 bmap = isl_basic_map_set_to_empty(bmap);
6001 return bmap;
6004 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
6006 struct isl_basic_set *bset;
6007 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
6008 bset = isl_basic_set_set_to_empty(bset);
6009 return bset;
6012 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6014 struct isl_basic_map *bmap;
6015 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6016 bmap = isl_basic_map_finalize(bmap);
6017 return bmap;
6020 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6022 struct isl_basic_set *bset;
6023 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6024 bset = isl_basic_set_finalize(bset);
6025 return bset;
6028 __isl_give isl_basic_map *isl_basic_map_nat_universe(
6029 __isl_take isl_space *space)
6031 int i;
6032 isl_size total = isl_space_dim(space, isl_dim_all);
6033 isl_basic_map *bmap;
6035 if (total < 0)
6036 space = isl_space_free(space);
6037 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
6038 for (i = 0; i < total; ++i) {
6039 int k = isl_basic_map_alloc_inequality(bmap);
6040 if (k < 0)
6041 goto error;
6042 isl_seq_clr(bmap->ineq[k], 1 + total);
6043 isl_int_set_si(bmap->ineq[k][1 + i], 1);
6045 return bmap;
6046 error:
6047 isl_basic_map_free(bmap);
6048 return NULL;
6051 __isl_give isl_basic_set *isl_basic_set_nat_universe(
6052 __isl_take isl_space *space)
6054 return isl_basic_map_nat_universe(space);
6057 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
6059 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
6062 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
6064 return isl_map_nat_universe(dim);
6067 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6069 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6072 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6074 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6077 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6079 struct isl_map *map;
6080 if (!space)
6081 return NULL;
6082 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6083 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6084 return map;
6087 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6089 struct isl_set *set;
6090 if (!space)
6091 return NULL;
6092 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6093 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6094 return set;
6097 struct isl_map *isl_map_dup(struct isl_map *map)
6099 int i;
6100 struct isl_map *dup;
6102 if (!map)
6103 return NULL;
6104 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6105 for (i = 0; i < map->n; ++i)
6106 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6107 return dup;
6110 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6111 __isl_take isl_basic_map *bmap)
6113 if (!bmap || !map)
6114 goto error;
6115 if (isl_basic_map_plain_is_empty(bmap)) {
6116 isl_basic_map_free(bmap);
6117 return map;
6119 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
6120 isl_assert(map->ctx, map->n < map->size, goto error);
6121 map->p[map->n] = bmap;
6122 map->n++;
6123 map = isl_map_unmark_normalized(map);
6124 return map;
6125 error:
6126 if (map)
6127 isl_map_free(map);
6128 if (bmap)
6129 isl_basic_map_free(bmap);
6130 return NULL;
6133 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6135 int i;
6137 if (!map)
6138 return NULL;
6140 if (--map->ref > 0)
6141 return NULL;
6143 clear_caches(map);
6144 isl_ctx_deref(map->ctx);
6145 for (i = 0; i < map->n; ++i)
6146 isl_basic_map_free(map->p[i]);
6147 isl_space_free(map->dim);
6148 free(map);
6150 return NULL;
6153 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6154 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6156 int j;
6157 isl_size total;
6159 total = isl_basic_map_dim(bmap, isl_dim_all);
6160 if (total < 0)
6161 return isl_basic_map_free(bmap);
6163 bmap = isl_basic_map_cow(bmap);
6164 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6165 j = isl_basic_map_alloc_equality(bmap);
6166 if (j < 0)
6167 goto error;
6168 isl_seq_clr(bmap->eq[j] + 1, total);
6169 isl_int_set_si(bmap->eq[j][pos], -1);
6170 isl_int_set_si(bmap->eq[j][0], value);
6171 bmap = isl_basic_map_simplify(bmap);
6172 return isl_basic_map_finalize(bmap);
6173 error:
6174 isl_basic_map_free(bmap);
6175 return NULL;
6178 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6179 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6181 int j;
6182 isl_size total;
6184 total = isl_basic_map_dim(bmap, isl_dim_all);
6185 if (total < 0)
6186 return isl_basic_map_free(bmap);
6188 bmap = isl_basic_map_cow(bmap);
6189 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6190 j = isl_basic_map_alloc_equality(bmap);
6191 if (j < 0)
6192 goto error;
6193 isl_seq_clr(bmap->eq[j] + 1, total);
6194 isl_int_set_si(bmap->eq[j][pos], -1);
6195 isl_int_set(bmap->eq[j][0], value);
6196 bmap = isl_basic_map_simplify(bmap);
6197 return isl_basic_map_finalize(bmap);
6198 error:
6199 isl_basic_map_free(bmap);
6200 return NULL;
6203 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6204 enum isl_dim_type type, unsigned pos, int value)
6206 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6207 return isl_basic_map_free(bmap);
6208 return isl_basic_map_fix_pos_si(bmap,
6209 isl_basic_map_offset(bmap, type) + pos, value);
6212 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6213 enum isl_dim_type type, unsigned pos, isl_int value)
6215 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6216 return isl_basic_map_free(bmap);
6217 return isl_basic_map_fix_pos(bmap,
6218 isl_basic_map_offset(bmap, type) + pos, value);
6221 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6222 * to be equal to "v".
6224 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6225 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6227 if (!bmap || !v)
6228 goto error;
6229 if (!isl_val_is_int(v))
6230 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6231 "expecting integer value", goto error);
6232 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6233 goto error;
6234 pos += isl_basic_map_offset(bmap, type);
6235 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6236 isl_val_free(v);
6237 return bmap;
6238 error:
6239 isl_basic_map_free(bmap);
6240 isl_val_free(v);
6241 return NULL;
6244 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6245 * to be equal to "v".
6247 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6248 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6250 return isl_basic_map_fix_val(bset, type, pos, v);
6253 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
6254 enum isl_dim_type type, unsigned pos, int value)
6256 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6257 type, pos, value));
6260 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6261 enum isl_dim_type type, unsigned pos, isl_int value)
6263 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6264 type, pos, value));
6267 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
6268 unsigned input, int value)
6270 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
6273 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
6274 unsigned dim, int value)
6276 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6277 isl_dim_set, dim, value));
6280 /* Remove the basic map at position "i" from "map" if this basic map
6281 * is (obviously) empty.
6283 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6285 isl_bool empty;
6287 if (!map)
6288 return NULL;
6290 empty = isl_basic_map_plain_is_empty(map->p[i]);
6291 if (empty < 0)
6292 return isl_map_free(map);
6293 if (!empty)
6294 return map;
6296 isl_basic_map_free(map->p[i]);
6297 map->n--;
6298 if (i != map->n) {
6299 map->p[i] = map->p[map->n];
6300 map = isl_map_unmark_normalized(map);
6304 return map;
6307 /* Perform "fn" on each basic map of "map", where we may not be holding
6308 * the only reference to "map".
6309 * In particular, "fn" should be a semantics preserving operation
6310 * that we want to apply to all copies of "map". We therefore need
6311 * to be careful not to modify "map" in a way that breaks "map"
6312 * in case anything goes wrong.
6314 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6315 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6317 struct isl_basic_map *bmap;
6318 int i;
6320 if (!map)
6321 return NULL;
6323 for (i = map->n - 1; i >= 0; --i) {
6324 bmap = isl_basic_map_copy(map->p[i]);
6325 bmap = fn(bmap);
6326 if (!bmap)
6327 goto error;
6328 isl_basic_map_free(map->p[i]);
6329 map->p[i] = bmap;
6330 map = remove_if_empty(map, i);
6331 if (!map)
6332 return NULL;
6335 return map;
6336 error:
6337 isl_map_free(map);
6338 return NULL;
6341 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6342 enum isl_dim_type type, unsigned pos, int value)
6344 int i;
6346 map = isl_map_cow(map);
6347 if (isl_map_check_range(map, type, pos, 1) < 0)
6348 return isl_map_free(map);
6349 for (i = map->n - 1; i >= 0; --i) {
6350 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6351 map = remove_if_empty(map, i);
6352 if (!map)
6353 return NULL;
6355 map = isl_map_unmark_normalized(map);
6356 return map;
6359 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6360 enum isl_dim_type type, unsigned pos, int value)
6362 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6365 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6366 enum isl_dim_type type, unsigned pos, isl_int value)
6368 int i;
6370 map = isl_map_cow(map);
6371 if (isl_map_check_range(map, type, pos, 1) < 0)
6372 return isl_map_free(map);
6373 for (i = 0; i < map->n; ++i) {
6374 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6375 if (!map->p[i])
6376 goto error;
6378 map = isl_map_unmark_normalized(map);
6379 return map;
6380 error:
6381 isl_map_free(map);
6382 return NULL;
6385 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6386 enum isl_dim_type type, unsigned pos, isl_int value)
6388 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6391 /* Fix the value of the variable at position "pos" of type "type" of "map"
6392 * to be equal to "v".
6394 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6395 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6397 int i;
6399 map = isl_map_cow(map);
6400 if (!map || !v)
6401 goto error;
6403 if (!isl_val_is_int(v))
6404 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6405 "expecting integer value", goto error);
6406 if (isl_map_check_range(map, type, pos, 1) < 0)
6407 goto error;
6408 for (i = map->n - 1; i >= 0; --i) {
6409 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6410 isl_val_copy(v));
6411 map = remove_if_empty(map, i);
6412 if (!map)
6413 goto error;
6415 map = isl_map_unmark_normalized(map);
6416 isl_val_free(v);
6417 return map;
6418 error:
6419 isl_map_free(map);
6420 isl_val_free(v);
6421 return NULL;
6424 /* Fix the value of the variable at position "pos" of type "type" of "set"
6425 * to be equal to "v".
6427 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6428 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6430 return isl_map_fix_val(set, type, pos, v);
6433 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
6434 unsigned input, int value)
6436 return isl_map_fix_si(map, isl_dim_in, input, value);
6439 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
6441 return set_from_map(isl_map_fix_si(set_to_map(set),
6442 isl_dim_set, dim, value));
6445 static __isl_give isl_basic_map *basic_map_bound_si(
6446 __isl_take isl_basic_map *bmap,
6447 enum isl_dim_type type, unsigned pos, int value, int upper)
6449 int j;
6450 isl_size total;
6452 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6453 return isl_basic_map_free(bmap);
6454 total = isl_basic_map_dim(bmap, isl_dim_all);
6455 if (total < 0)
6456 return isl_basic_map_free(bmap);
6457 pos += isl_basic_map_offset(bmap, type);
6458 bmap = isl_basic_map_cow(bmap);
6459 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6460 j = isl_basic_map_alloc_inequality(bmap);
6461 if (j < 0)
6462 goto error;
6463 isl_seq_clr(bmap->ineq[j], 1 + total);
6464 if (upper) {
6465 isl_int_set_si(bmap->ineq[j][pos], -1);
6466 isl_int_set_si(bmap->ineq[j][0], value);
6467 } else {
6468 isl_int_set_si(bmap->ineq[j][pos], 1);
6469 isl_int_set_si(bmap->ineq[j][0], -value);
6471 bmap = isl_basic_map_simplify(bmap);
6472 return isl_basic_map_finalize(bmap);
6473 error:
6474 isl_basic_map_free(bmap);
6475 return NULL;
6478 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6479 __isl_take isl_basic_map *bmap,
6480 enum isl_dim_type type, unsigned pos, int value)
6482 return basic_map_bound_si(bmap, type, pos, value, 0);
6485 /* Constrain the values of the given dimension to be no greater than "value".
6487 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6488 __isl_take isl_basic_map *bmap,
6489 enum isl_dim_type type, unsigned pos, int value)
6491 return basic_map_bound_si(bmap, type, pos, value, 1);
6494 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6495 enum isl_dim_type type, unsigned pos, int value, int upper)
6497 int i;
6499 map = isl_map_cow(map);
6500 if (isl_map_check_range(map, type, pos, 1) < 0)
6501 return isl_map_free(map);
6502 for (i = 0; i < map->n; ++i) {
6503 map->p[i] = basic_map_bound_si(map->p[i],
6504 type, pos, value, upper);
6505 if (!map->p[i])
6506 goto error;
6508 map = isl_map_unmark_normalized(map);
6509 return map;
6510 error:
6511 isl_map_free(map);
6512 return NULL;
6515 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6516 enum isl_dim_type type, unsigned pos, int value)
6518 return map_bound_si(map, type, pos, value, 0);
6521 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6522 enum isl_dim_type type, unsigned pos, int value)
6524 return map_bound_si(map, type, pos, value, 1);
6527 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6528 enum isl_dim_type type, unsigned pos, int value)
6530 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6531 type, pos, value));
6534 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6535 enum isl_dim_type type, unsigned pos, int value)
6537 return isl_map_upper_bound_si(set, type, pos, value);
6540 /* Bound the given variable of "bmap" from below (or above is "upper"
6541 * is set) to "value".
6543 static __isl_give isl_basic_map *basic_map_bound(
6544 __isl_take isl_basic_map *bmap,
6545 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6547 int j;
6548 isl_size total;
6550 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6551 return isl_basic_map_free(bmap);
6552 total = isl_basic_map_dim(bmap, isl_dim_all);
6553 if (total < 0)
6554 return isl_basic_map_free(bmap);
6555 pos += isl_basic_map_offset(bmap, type);
6556 bmap = isl_basic_map_cow(bmap);
6557 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6558 j = isl_basic_map_alloc_inequality(bmap);
6559 if (j < 0)
6560 goto error;
6561 isl_seq_clr(bmap->ineq[j], 1 + total);
6562 if (upper) {
6563 isl_int_set_si(bmap->ineq[j][pos], -1);
6564 isl_int_set(bmap->ineq[j][0], value);
6565 } else {
6566 isl_int_set_si(bmap->ineq[j][pos], 1);
6567 isl_int_neg(bmap->ineq[j][0], value);
6569 bmap = isl_basic_map_simplify(bmap);
6570 return isl_basic_map_finalize(bmap);
6571 error:
6572 isl_basic_map_free(bmap);
6573 return NULL;
6576 /* Bound the given variable of "map" from below (or above is "upper"
6577 * is set) to "value".
6579 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6580 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6582 int i;
6584 map = isl_map_cow(map);
6585 if (isl_map_check_range(map, type, pos, 1) < 0)
6586 return isl_map_free(map);
6587 for (i = map->n - 1; i >= 0; --i) {
6588 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6589 map = remove_if_empty(map, i);
6590 if (!map)
6591 return NULL;
6593 map = isl_map_unmark_normalized(map);
6594 return map;
6597 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6598 enum isl_dim_type type, unsigned pos, isl_int value)
6600 return map_bound(map, type, pos, value, 0);
6603 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6604 enum isl_dim_type type, unsigned pos, isl_int value)
6606 return map_bound(map, type, pos, value, 1);
6609 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6610 enum isl_dim_type type, unsigned pos, isl_int value)
6612 return isl_map_lower_bound(set, type, pos, value);
6615 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6616 enum isl_dim_type type, unsigned pos, isl_int value)
6618 return isl_map_upper_bound(set, type, pos, value);
6621 /* Force the values of the variable at position "pos" of type "type" of "set"
6622 * to be no smaller than "value".
6624 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6625 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6627 if (!value)
6628 goto error;
6629 if (!isl_val_is_int(value))
6630 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6631 "expecting integer value", goto error);
6632 set = isl_set_lower_bound(set, type, pos, value->n);
6633 isl_val_free(value);
6634 return set;
6635 error:
6636 isl_val_free(value);
6637 isl_set_free(set);
6638 return NULL;
6641 /* Force the values of the variable at position "pos" of type "type" of "set"
6642 * to be no greater than "value".
6644 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6645 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6647 if (!value)
6648 goto error;
6649 if (!isl_val_is_int(value))
6650 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6651 "expecting integer value", goto error);
6652 set = isl_set_upper_bound(set, type, pos, value->n);
6653 isl_val_free(value);
6654 return set;
6655 error:
6656 isl_val_free(value);
6657 isl_set_free(set);
6658 return NULL;
6661 /* Bound the given variable of "bset" from below (or above is "upper"
6662 * is set) to "value".
6664 static __isl_give isl_basic_set *isl_basic_set_bound(
6665 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6666 isl_int value, int upper)
6668 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
6669 type, pos, value, upper));
6672 /* Bound the given variable of "bset" from below (or above is "upper"
6673 * is set) to "value".
6675 static __isl_give isl_basic_set *isl_basic_set_bound_val(
6676 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6677 __isl_take isl_val *value, int upper)
6679 if (!value)
6680 goto error;
6681 if (!isl_val_is_int(value))
6682 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
6683 "expecting integer value", goto error);
6684 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
6685 isl_val_free(value);
6686 return bset;
6687 error:
6688 isl_val_free(value);
6689 isl_basic_set_free(bset);
6690 return NULL;
6693 /* Bound the given variable of "bset" from below to "value".
6695 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
6696 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6697 __isl_take isl_val *value)
6699 return isl_basic_set_bound_val(bset, type, pos, value, 0);
6702 /* Bound the given variable of "bset" from above to "value".
6704 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
6705 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6706 __isl_take isl_val *value)
6708 return isl_basic_set_bound_val(bset, type, pos, value, 1);
6711 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
6713 int i;
6715 map = isl_map_cow(map);
6716 if (!map)
6717 return NULL;
6719 map->dim = isl_space_reverse(map->dim);
6720 if (!map->dim)
6721 goto error;
6722 for (i = 0; i < map->n; ++i) {
6723 map->p[i] = isl_basic_map_reverse(map->p[i]);
6724 if (!map->p[i])
6725 goto error;
6727 map = isl_map_unmark_normalized(map);
6728 return map;
6729 error:
6730 isl_map_free(map);
6731 return NULL;
6734 #undef TYPE
6735 #define TYPE isl_pw_multi_aff
6736 #undef SUFFIX
6737 #define SUFFIX _pw_multi_aff
6738 #undef EMPTY
6739 #define EMPTY isl_pw_multi_aff_empty
6740 #undef ADD
6741 #define ADD isl_pw_multi_aff_union_add
6742 #include "isl_map_lexopt_templ.c"
6744 /* Given a map "map", compute the lexicographically minimal
6745 * (or maximal) image element for each domain element in dom,
6746 * in the form of an isl_pw_multi_aff.
6747 * If "empty" is not NULL, then set *empty to those elements in dom that
6748 * do not have an image element.
6749 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6750 * should be computed over the domain of "map". "empty" is also NULL
6751 * in this case.
6753 * We first compute the lexicographically minimal or maximal element
6754 * in the first basic map. This results in a partial solution "res"
6755 * and a subset "todo" of dom that still need to be handled.
6756 * We then consider each of the remaining maps in "map" and successively
6757 * update both "res" and "todo".
6758 * If "empty" is NULL, then the todo sets are not needed and therefore
6759 * also not computed.
6761 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6762 __isl_take isl_map *map, __isl_take isl_set *dom,
6763 __isl_give isl_set **empty, unsigned flags)
6765 int i;
6766 int full;
6767 isl_pw_multi_aff *res;
6768 isl_set *todo;
6770 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6771 if (!map || (!full && !dom))
6772 goto error;
6774 if (isl_map_plain_is_empty(map)) {
6775 if (empty)
6776 *empty = dom;
6777 else
6778 isl_set_free(dom);
6779 return isl_pw_multi_aff_from_map(map);
6782 res = basic_map_partial_lexopt_pw_multi_aff(
6783 isl_basic_map_copy(map->p[0]),
6784 isl_set_copy(dom), empty, flags);
6786 if (empty)
6787 todo = *empty;
6788 for (i = 1; i < map->n; ++i) {
6789 isl_pw_multi_aff *res_i;
6791 res_i = basic_map_partial_lexopt_pw_multi_aff(
6792 isl_basic_map_copy(map->p[i]),
6793 isl_set_copy(dom), empty, flags);
6795 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6796 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6797 else
6798 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6800 if (empty)
6801 todo = isl_set_intersect(todo, *empty);
6804 isl_set_free(dom);
6805 isl_map_free(map);
6807 if (empty)
6808 *empty = todo;
6810 return res;
6811 error:
6812 if (empty)
6813 *empty = NULL;
6814 isl_set_free(dom);
6815 isl_map_free(map);
6816 return NULL;
6819 #undef TYPE
6820 #define TYPE isl_map
6821 #undef SUFFIX
6822 #define SUFFIX
6823 #undef EMPTY
6824 #define EMPTY isl_map_empty
6825 #undef ADD
6826 #define ADD isl_map_union_disjoint
6827 #include "isl_map_lexopt_templ.c"
6829 /* Given a map "map", compute the lexicographically minimal
6830 * (or maximal) image element for each domain element in "dom",
6831 * in the form of an isl_map.
6832 * If "empty" is not NULL, then set *empty to those elements in "dom" that
6833 * do not have an image element.
6834 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6835 * should be computed over the domain of "map". "empty" is also NULL
6836 * in this case.
6838 * If the input consists of more than one disjunct, then first
6839 * compute the desired result in the form of an isl_pw_multi_aff and
6840 * then convert that into an isl_map.
6842 * This function used to have an explicit implementation in terms
6843 * of isl_maps, but it would continually intersect the domains of
6844 * partial results with the complement of the domain of the next
6845 * partial solution, potentially leading to an explosion in the number
6846 * of disjuncts if there are several disjuncts in the input.
6847 * An even earlier implementation of this function would look for
6848 * better results in the domain of the partial result and for extra
6849 * results in the complement of this domain, which would lead to
6850 * even more splintering.
6852 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6853 __isl_take isl_map *map, __isl_take isl_set *dom,
6854 __isl_give isl_set **empty, unsigned flags)
6856 int full;
6857 struct isl_map *res;
6858 isl_pw_multi_aff *pma;
6860 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6861 if (!map || (!full && !dom))
6862 goto error;
6864 if (isl_map_plain_is_empty(map)) {
6865 if (empty)
6866 *empty = dom;
6867 else
6868 isl_set_free(dom);
6869 return map;
6872 if (map->n == 1) {
6873 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6874 dom, empty, flags);
6875 isl_map_free(map);
6876 return res;
6879 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6880 flags);
6881 return isl_map_from_pw_multi_aff(pma);
6882 error:
6883 if (empty)
6884 *empty = NULL;
6885 isl_set_free(dom);
6886 isl_map_free(map);
6887 return NULL;
6890 __isl_give isl_map *isl_map_partial_lexmax(
6891 __isl_take isl_map *map, __isl_take isl_set *dom,
6892 __isl_give isl_set **empty)
6894 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6897 __isl_give isl_map *isl_map_partial_lexmin(
6898 __isl_take isl_map *map, __isl_take isl_set *dom,
6899 __isl_give isl_set **empty)
6901 return isl_map_partial_lexopt(map, dom, empty, 0);
6904 __isl_give isl_set *isl_set_partial_lexmin(
6905 __isl_take isl_set *set, __isl_take isl_set *dom,
6906 __isl_give isl_set **empty)
6908 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6909 dom, empty));
6912 __isl_give isl_set *isl_set_partial_lexmax(
6913 __isl_take isl_set *set, __isl_take isl_set *dom,
6914 __isl_give isl_set **empty)
6916 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6917 dom, empty));
6920 /* Compute the lexicographic minimum (or maximum if "flags" includes
6921 * ISL_OPT_MAX) of "bset" over its parametric domain.
6923 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6924 unsigned flags)
6926 return isl_basic_map_lexopt(bset, flags);
6929 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6931 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6934 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6936 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6939 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6941 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6944 /* Compute the lexicographic minimum of "bset" over its parametric domain
6945 * for the purpose of quantifier elimination.
6946 * That is, find an explicit representation for all the existentially
6947 * quantified variables in "bset" by computing their lexicographic
6948 * minimum.
6950 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6951 __isl_take isl_basic_set *bset)
6953 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6956 /* Given a basic map with one output dimension, compute the minimum or
6957 * maximum of that dimension as an isl_pw_aff.
6959 * Compute the optimum as a lexicographic optimum over the single
6960 * output dimension and extract the single isl_pw_aff from the result.
6962 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6963 int max)
6965 isl_pw_multi_aff *pma;
6966 isl_pw_aff *pwaff;
6968 bmap = isl_basic_map_copy(bmap);
6969 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
6970 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
6971 isl_pw_multi_aff_free(pma);
6973 return pwaff;
6976 /* Compute the minimum or maximum of the given output dimension
6977 * as a function of the parameters and the input dimensions,
6978 * but independently of the other output dimensions.
6980 * We first project out the other output dimension and then compute
6981 * the "lexicographic" maximum in each basic map, combining the results
6982 * using isl_pw_aff_union_max.
6984 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6985 int max)
6987 int i;
6988 isl_pw_aff *pwaff;
6989 isl_size n_out;
6991 n_out = isl_map_dim(map, isl_dim_out);
6992 if (n_out < 0)
6993 map = isl_map_free(map);
6994 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6995 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6996 if (!map)
6997 return NULL;
6999 if (map->n == 0) {
7000 isl_space *space = isl_map_get_space(map);
7001 isl_map_free(map);
7002 return isl_pw_aff_empty(space);
7005 pwaff = basic_map_dim_opt(map->p[0], max);
7006 for (i = 1; i < map->n; ++i) {
7007 isl_pw_aff *pwaff_i;
7009 pwaff_i = basic_map_dim_opt(map->p[i], max);
7010 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7013 isl_map_free(map);
7015 return pwaff;
7018 /* Compute the minimum of the given output dimension as a function of the
7019 * parameters and input dimensions, but independently of
7020 * the other output dimensions.
7022 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7024 return map_dim_opt(map, pos, 0);
7027 /* Compute the maximum of the given output dimension as a function of the
7028 * parameters and input dimensions, but independently of
7029 * the other output dimensions.
7031 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7033 return map_dim_opt(map, pos, 1);
7036 /* Compute the minimum or maximum of the given set dimension
7037 * as a function of the parameters,
7038 * but independently of the other set dimensions.
7040 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7041 int max)
7043 return map_dim_opt(set, pos, max);
7046 /* Compute the maximum of the given set dimension as a function of the
7047 * parameters, but independently of the other set dimensions.
7049 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7051 return set_dim_opt(set, pos, 1);
7054 /* Compute the minimum of the given set dimension as a function of the
7055 * parameters, but independently of the other set dimensions.
7057 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7059 return set_dim_opt(set, pos, 0);
7062 /* Apply a preimage specified by "mat" on the parameters of "bset".
7063 * bset is assumed to have only parameters and divs.
7065 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7066 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7068 isl_size nparam;
7070 nparam = isl_basic_set_dim(bset, isl_dim_param);
7071 if (nparam < 0 || !mat)
7072 goto error;
7074 bset->dim = isl_space_cow(bset->dim);
7075 if (!bset->dim)
7076 goto error;
7078 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7080 bset->dim->nparam = 0;
7081 bset->dim->n_out = nparam;
7082 bset = isl_basic_set_preimage(bset, mat);
7083 if (bset) {
7084 bset->dim->nparam = bset->dim->n_out;
7085 bset->dim->n_out = 0;
7087 return bset;
7088 error:
7089 isl_mat_free(mat);
7090 isl_basic_set_free(bset);
7091 return NULL;
7094 /* Apply a preimage specified by "mat" on the parameters of "set".
7095 * set is assumed to have only parameters and divs.
7097 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7098 __isl_take isl_mat *mat)
7100 isl_space *space;
7101 isl_size nparam;
7103 nparam = isl_set_dim(set, isl_dim_param);
7104 if (nparam < 0 || !mat)
7105 goto error;
7107 if (mat->n_row != 1 + nparam)
7108 isl_die(isl_set_get_ctx(set), isl_error_internal,
7109 "unexpected number of rows", goto error);
7111 space = isl_set_get_space(set);
7112 space = isl_space_move_dims(space, isl_dim_set, 0,
7113 isl_dim_param, 0, nparam);
7114 set = isl_set_reset_space(set, space);
7115 set = isl_set_preimage(set, mat);
7116 nparam = isl_set_dim(set, isl_dim_out);
7117 if (nparam < 0)
7118 set = isl_set_free(set);
7119 space = isl_set_get_space(set);
7120 space = isl_space_move_dims(space, isl_dim_param, 0,
7121 isl_dim_out, 0, nparam);
7122 set = isl_set_reset_space(set, space);
7123 return set;
7124 error:
7125 isl_mat_free(mat);
7126 isl_set_free(set);
7127 return NULL;
7130 /* Intersect the basic set "bset" with the affine space specified by the
7131 * equalities in "eq".
7133 static __isl_give isl_basic_set *basic_set_append_equalities(
7134 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7136 int i, k;
7137 unsigned len;
7139 if (!bset || !eq)
7140 goto error;
7142 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
7143 eq->n_row, 0);
7144 if (!bset)
7145 goto error;
7147 len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7148 for (i = 0; i < eq->n_row; ++i) {
7149 k = isl_basic_set_alloc_equality(bset);
7150 if (k < 0)
7151 goto error;
7152 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7153 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7155 isl_mat_free(eq);
7157 bset = isl_basic_set_gauss(bset, NULL);
7158 bset = isl_basic_set_finalize(bset);
7160 return bset;
7161 error:
7162 isl_mat_free(eq);
7163 isl_basic_set_free(bset);
7164 return NULL;
7167 /* Intersect the set "set" with the affine space specified by the
7168 * equalities in "eq".
7170 static struct isl_set *set_append_equalities(struct isl_set *set,
7171 struct isl_mat *eq)
7173 int i;
7175 if (!set || !eq)
7176 goto error;
7178 for (i = 0; i < set->n; ++i) {
7179 set->p[i] = basic_set_append_equalities(set->p[i],
7180 isl_mat_copy(eq));
7181 if (!set->p[i])
7182 goto error;
7184 isl_mat_free(eq);
7185 return set;
7186 error:
7187 isl_mat_free(eq);
7188 isl_set_free(set);
7189 return NULL;
7192 /* Given a basic set "bset" that only involves parameters and existentially
7193 * quantified variables, return the index of the first equality
7194 * that only involves parameters. If there is no such equality then
7195 * return bset->n_eq.
7197 * This function assumes that isl_basic_set_gauss has been called on "bset".
7199 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7201 int i, j;
7202 isl_size nparam, n_div;
7204 nparam = isl_basic_set_dim(bset, isl_dim_param);
7205 n_div = isl_basic_set_dim(bset, isl_dim_div);
7206 if (nparam < 0 || n_div < 0)
7207 return -1;
7209 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7210 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7211 ++i;
7214 return i;
7217 /* Compute an explicit representation for the existentially quantified
7218 * variables in "bset" by computing the "minimal value" of the set
7219 * variables. Since there are no set variables, the computation of
7220 * the minimal value essentially computes an explicit representation
7221 * of the non-empty part(s) of "bset".
7223 * The input only involves parameters and existentially quantified variables.
7224 * All equalities among parameters have been removed.
7226 * Since the existentially quantified variables in the result are in general
7227 * going to be different from those in the input, we first replace
7228 * them by the minimal number of variables based on their equalities.
7229 * This should simplify the parametric integer programming.
7231 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7233 isl_morph *morph1, *morph2;
7234 isl_set *set;
7235 isl_size n;
7237 if (!bset)
7238 return NULL;
7239 if (bset->n_eq == 0)
7240 return isl_basic_set_lexmin_compute_divs(bset);
7242 morph1 = isl_basic_set_parameter_compression(bset);
7243 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7244 bset = isl_basic_set_lift(bset);
7245 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7246 bset = isl_morph_basic_set(morph2, bset);
7247 n = isl_basic_set_dim(bset, isl_dim_set);
7248 if (n < 0)
7249 bset = isl_basic_set_free(bset);
7250 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7252 set = isl_basic_set_lexmin_compute_divs(bset);
7254 set = isl_morph_set(isl_morph_inverse(morph1), set);
7256 return set;
7259 /* Project the given basic set onto its parameter domain, possibly introducing
7260 * new, explicit, existential variables in the constraints.
7261 * The input has parameters and (possibly implicit) existential variables.
7262 * The output has the same parameters, but only
7263 * explicit existentially quantified variables.
7265 * The actual projection is performed by pip, but pip doesn't seem
7266 * to like equalities very much, so we first remove the equalities
7267 * among the parameters by performing a variable compression on
7268 * the parameters. Afterward, an inverse transformation is performed
7269 * and the equalities among the parameters are inserted back in.
7271 * The variable compression on the parameters may uncover additional
7272 * equalities that were only implicit before. We therefore check
7273 * if there are any new parameter equalities in the result and
7274 * if so recurse. The removal of parameter equalities is required
7275 * for the parameter compression performed by base_compute_divs.
7277 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
7279 int i;
7280 struct isl_mat *eq;
7281 struct isl_mat *T, *T2;
7282 struct isl_set *set;
7283 isl_size nparam;
7285 bset = isl_basic_set_cow(bset);
7286 if (!bset)
7287 return NULL;
7289 if (bset->n_eq == 0)
7290 return base_compute_divs(bset);
7292 bset = isl_basic_set_gauss(bset, NULL);
7293 if (!bset)
7294 return NULL;
7295 if (isl_basic_set_plain_is_empty(bset))
7296 return isl_set_from_basic_set(bset);
7298 i = first_parameter_equality(bset);
7299 if (i == bset->n_eq)
7300 return base_compute_divs(bset);
7302 nparam = isl_basic_set_dim(bset, isl_dim_param);
7303 if (nparam < 0)
7304 return isl_set_from_basic_set(isl_basic_set_free(bset));
7305 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7306 0, 1 + nparam);
7307 eq = isl_mat_cow(eq);
7308 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7309 if (T && T->n_col == 0) {
7310 isl_mat_free(T);
7311 isl_mat_free(T2);
7312 isl_mat_free(eq);
7313 bset = isl_basic_set_set_to_empty(bset);
7314 return isl_set_from_basic_set(bset);
7316 bset = basic_set_parameter_preimage(bset, T);
7318 i = first_parameter_equality(bset);
7319 if (!bset)
7320 set = NULL;
7321 else if (i == bset->n_eq)
7322 set = base_compute_divs(bset);
7323 else
7324 set = parameter_compute_divs(bset);
7325 set = set_parameter_preimage(set, T2);
7326 set = set_append_equalities(set, eq);
7327 return set;
7330 /* Insert the divs from "ls" before those of "bmap".
7332 * The number of columns is not changed, which means that the last
7333 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7334 * The caller is responsible for removing the same number of dimensions
7335 * from the space of "bmap".
7337 static __isl_give isl_basic_map *insert_divs_from_local_space(
7338 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7340 int i;
7341 isl_size n_div;
7342 int old_n_div;
7344 n_div = isl_local_space_dim(ls, isl_dim_div);
7345 if (n_div < 0)
7346 return isl_basic_map_free(bmap);
7347 if (n_div == 0)
7348 return bmap;
7350 old_n_div = bmap->n_div;
7351 bmap = insert_div_rows(bmap, n_div);
7352 if (!bmap)
7353 return NULL;
7355 for (i = 0; i < n_div; ++i) {
7356 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7357 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7360 return bmap;
7363 /* Replace the space of "bmap" by the space and divs of "ls".
7365 * If "ls" has any divs, then we simplify the result since we may
7366 * have discovered some additional equalities that could simplify
7367 * the div expressions.
7369 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7370 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7372 isl_size n_div;
7374 bmap = isl_basic_map_cow(bmap);
7375 n_div = isl_local_space_dim(ls, isl_dim_div);
7376 if (!bmap || n_div < 0)
7377 goto error;
7379 bmap = insert_divs_from_local_space(bmap, ls);
7380 if (!bmap)
7381 goto error;
7383 isl_space_free(bmap->dim);
7384 bmap->dim = isl_local_space_get_space(ls);
7385 if (!bmap->dim)
7386 goto error;
7388 isl_local_space_free(ls);
7389 if (n_div > 0)
7390 bmap = isl_basic_map_simplify(bmap);
7391 bmap = isl_basic_map_finalize(bmap);
7392 return bmap;
7393 error:
7394 isl_basic_map_free(bmap);
7395 isl_local_space_free(ls);
7396 return NULL;
7399 /* Replace the space of "map" by the space and divs of "ls".
7401 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7402 __isl_take isl_local_space *ls)
7404 int i;
7406 map = isl_map_cow(map);
7407 if (!map || !ls)
7408 goto error;
7410 for (i = 0; i < map->n; ++i) {
7411 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7412 isl_local_space_copy(ls));
7413 if (!map->p[i])
7414 goto error;
7416 isl_space_free(map->dim);
7417 map->dim = isl_local_space_get_space(ls);
7418 if (!map->dim)
7419 goto error;
7421 isl_local_space_free(ls);
7422 return map;
7423 error:
7424 isl_local_space_free(ls);
7425 isl_map_free(map);
7426 return NULL;
7429 /* Compute an explicit representation for the existentially
7430 * quantified variables for which do not know any explicit representation yet.
7432 * We first sort the existentially quantified variables so that the
7433 * existentially quantified variables for which we already have an explicit
7434 * representation are placed before those for which we do not.
7435 * The input dimensions, the output dimensions and the existentially
7436 * quantified variables for which we already have an explicit
7437 * representation are then turned into parameters.
7438 * compute_divs returns a map with the same parameters and
7439 * no input or output dimensions and the dimension specification
7440 * is reset to that of the input, including the existentially quantified
7441 * variables for which we already had an explicit representation.
7443 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7445 struct isl_basic_set *bset;
7446 struct isl_set *set;
7447 struct isl_map *map;
7448 isl_space *space;
7449 isl_local_space *ls;
7450 isl_size nparam;
7451 isl_size n_in;
7452 isl_size n_out;
7453 int n_known;
7454 int i;
7456 bmap = isl_basic_map_sort_divs(bmap);
7457 bmap = isl_basic_map_cow(bmap);
7458 if (!bmap)
7459 return NULL;
7461 n_known = isl_basic_map_first_unknown_div(bmap);
7462 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7463 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7464 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7465 if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
7466 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7468 space = isl_space_set_alloc(bmap->ctx,
7469 nparam + n_in + n_out + n_known, 0);
7470 if (!space)
7471 goto error;
7473 ls = isl_basic_map_get_local_space(bmap);
7474 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7475 n_known, bmap->n_div - n_known);
7476 if (n_known > 0) {
7477 for (i = n_known; i < bmap->n_div; ++i)
7478 swap_div(bmap, i - n_known, i);
7479 bmap->n_div -= n_known;
7480 bmap->extra -= n_known;
7482 bmap = isl_basic_map_reset_space(bmap, space);
7483 bset = bset_from_bmap(bmap);
7485 set = parameter_compute_divs(bset);
7486 map = set_to_map(set);
7487 map = replace_space_by_local_space(map, ls);
7489 return map;
7490 error:
7491 isl_basic_map_free(bmap);
7492 return NULL;
7495 /* Remove the explicit representation of local variable "div",
7496 * if there is any.
7498 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7499 __isl_take isl_basic_map *bmap, int div)
7501 isl_bool unknown;
7503 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7504 if (unknown < 0)
7505 return isl_basic_map_free(bmap);
7506 if (unknown)
7507 return bmap;
7509 bmap = isl_basic_map_cow(bmap);
7510 if (!bmap)
7511 return NULL;
7512 isl_int_set_si(bmap->div[div][0], 0);
7513 return bmap;
7516 /* Is local variable "div" of "bmap" marked as not having an explicit
7517 * representation?
7518 * Note that even if "div" is not marked in this way and therefore
7519 * has an explicit representation, this representation may still
7520 * depend (indirectly) on other local variables that do not
7521 * have an explicit representation.
7523 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7524 int div)
7526 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7527 return isl_bool_error;
7528 return isl_int_is_zero(bmap->div[div][0]);
7531 /* Return the position of the first local variable that does not
7532 * have an explicit representation.
7533 * Return the total number of local variables if they all have
7534 * an explicit representation.
7535 * Return -1 on error.
7537 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7539 int i;
7541 if (!bmap)
7542 return -1;
7544 for (i = 0; i < bmap->n_div; ++i) {
7545 if (!isl_basic_map_div_is_known(bmap, i))
7546 return i;
7548 return bmap->n_div;
7551 /* Return the position of the first local variable that does not
7552 * have an explicit representation.
7553 * Return the total number of local variables if they all have
7554 * an explicit representation.
7555 * Return -1 on error.
7557 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7559 return isl_basic_map_first_unknown_div(bset);
7562 /* Does "bmap" have an explicit representation for all local variables?
7564 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7566 int first;
7567 isl_size n;
7569 n = isl_basic_map_dim(bmap, isl_dim_div);
7570 first = isl_basic_map_first_unknown_div(bmap);
7571 if (n < 0 || first < 0)
7572 return isl_bool_error;
7573 return first == n;
7576 /* Do all basic maps in "map" have an explicit representation
7577 * for all local variables?
7579 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7581 int i;
7583 if (!map)
7584 return isl_bool_error;
7586 for (i = 0; i < map->n; ++i) {
7587 int known = isl_basic_map_divs_known(map->p[i]);
7588 if (known <= 0)
7589 return known;
7592 return isl_bool_true;
7595 /* If bmap contains any unknown divs, then compute explicit
7596 * expressions for them. However, this computation may be
7597 * quite expensive, so first try to remove divs that aren't
7598 * strictly needed.
7600 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7602 int known;
7603 struct isl_map *map;
7605 known = isl_basic_map_divs_known(bmap);
7606 if (known < 0)
7607 goto error;
7608 if (known)
7609 return isl_map_from_basic_map(bmap);
7611 bmap = isl_basic_map_drop_redundant_divs(bmap);
7613 known = isl_basic_map_divs_known(bmap);
7614 if (known < 0)
7615 goto error;
7616 if (known)
7617 return isl_map_from_basic_map(bmap);
7619 map = compute_divs(bmap);
7620 return map;
7621 error:
7622 isl_basic_map_free(bmap);
7623 return NULL;
7626 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7628 int i;
7629 int known;
7630 struct isl_map *res;
7632 if (!map)
7633 return NULL;
7634 if (map->n == 0)
7635 return map;
7637 known = isl_map_divs_known(map);
7638 if (known < 0) {
7639 isl_map_free(map);
7640 return NULL;
7642 if (known)
7643 return map;
7645 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7646 for (i = 1 ; i < map->n; ++i) {
7647 struct isl_map *r2;
7648 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7649 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7650 res = isl_map_union_disjoint(res, r2);
7651 else
7652 res = isl_map_union(res, r2);
7654 isl_map_free(map);
7656 return res;
7659 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
7661 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7664 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7666 return set_from_map(isl_map_compute_divs(set_to_map(set)));
7669 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
7671 int i;
7672 struct isl_set *set;
7674 if (!map)
7675 goto error;
7677 map = isl_map_cow(map);
7678 if (!map)
7679 return NULL;
7681 set = set_from_map(map);
7682 set->dim = isl_space_domain(set->dim);
7683 if (!set->dim)
7684 goto error;
7685 for (i = 0; i < map->n; ++i) {
7686 set->p[i] = isl_basic_map_domain(map->p[i]);
7687 if (!set->p[i])
7688 goto error;
7690 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7691 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7692 return set;
7693 error:
7694 isl_map_free(map);
7695 return NULL;
7698 /* Return the union of "map1" and "map2", where we assume for now that
7699 * "map1" and "map2" are disjoint. Note that the basic maps inside
7700 * "map1" or "map2" may not be disjoint from each other.
7701 * Also note that this function is also called from isl_map_union,
7702 * which takes care of handling the situation where "map1" and "map2"
7703 * may not be disjoint.
7705 * If one of the inputs is empty, we can simply return the other input.
7706 * Similarly, if one of the inputs is universal, then it is equal to the union.
7708 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7709 __isl_take isl_map *map2)
7711 int i;
7712 unsigned flags = 0;
7713 struct isl_map *map = NULL;
7714 int is_universe;
7716 if (!map1 || !map2)
7717 goto error;
7719 if (!isl_space_is_equal(map1->dim, map2->dim))
7720 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7721 "spaces don't match", goto error);
7723 if (map1->n == 0) {
7724 isl_map_free(map1);
7725 return map2;
7727 if (map2->n == 0) {
7728 isl_map_free(map2);
7729 return map1;
7732 is_universe = isl_map_plain_is_universe(map1);
7733 if (is_universe < 0)
7734 goto error;
7735 if (is_universe) {
7736 isl_map_free(map2);
7737 return map1;
7740 is_universe = isl_map_plain_is_universe(map2);
7741 if (is_universe < 0)
7742 goto error;
7743 if (is_universe) {
7744 isl_map_free(map1);
7745 return map2;
7748 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7749 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7750 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7752 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7753 map1->n + map2->n, flags);
7754 if (!map)
7755 goto error;
7756 for (i = 0; i < map1->n; ++i) {
7757 map = isl_map_add_basic_map(map,
7758 isl_basic_map_copy(map1->p[i]));
7759 if (!map)
7760 goto error;
7762 for (i = 0; i < map2->n; ++i) {
7763 map = isl_map_add_basic_map(map,
7764 isl_basic_map_copy(map2->p[i]));
7765 if (!map)
7766 goto error;
7768 isl_map_free(map1);
7769 isl_map_free(map2);
7770 return map;
7771 error:
7772 isl_map_free(map);
7773 isl_map_free(map1);
7774 isl_map_free(map2);
7775 return NULL;
7778 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7779 * guaranteed to be disjoint by the caller.
7781 * Note that this functions is called from within isl_map_make_disjoint,
7782 * so we have to be careful not to touch the constraints of the inputs
7783 * in any way.
7785 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7786 __isl_take isl_map *map2)
7788 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7791 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7792 * not be disjoint. The parameters are assumed to have been aligned.
7794 * We currently simply call map_union_disjoint, the internal operation
7795 * of which does not really depend on the inputs being disjoint.
7796 * If the result contains more than one basic map, then we clear
7797 * the disjoint flag since the result may contain basic maps from
7798 * both inputs and these are not guaranteed to be disjoint.
7800 * As a special case, if "map1" and "map2" are obviously equal,
7801 * then we simply return "map1".
7803 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7804 __isl_take isl_map *map2)
7806 int equal;
7808 if (!map1 || !map2)
7809 goto error;
7811 equal = isl_map_plain_is_equal(map1, map2);
7812 if (equal < 0)
7813 goto error;
7814 if (equal) {
7815 isl_map_free(map2);
7816 return map1;
7819 map1 = map_union_disjoint(map1, map2);
7820 if (!map1)
7821 return NULL;
7822 if (map1->n > 1)
7823 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7824 return map1;
7825 error:
7826 isl_map_free(map1);
7827 isl_map_free(map2);
7828 return NULL;
7831 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7832 * not be disjoint.
7834 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7835 __isl_take isl_map *map2)
7837 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7840 __isl_give isl_set *isl_set_union_disjoint(
7841 __isl_take isl_set *set1, __isl_take isl_set *set2)
7843 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7844 set_to_map(set2)));
7847 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7849 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7852 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7853 * the results.
7855 * "map" and "set" are assumed to be compatible and non-NULL.
7857 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7858 __isl_take isl_set *set,
7859 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7860 __isl_take isl_basic_set *bset))
7862 unsigned flags = 0;
7863 struct isl_map *result;
7864 int i, j;
7866 if (isl_set_plain_is_universe(set)) {
7867 isl_set_free(set);
7868 return map;
7871 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7872 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7873 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7875 result = isl_map_alloc_space(isl_space_copy(map->dim),
7876 map->n * set->n, flags);
7877 for (i = 0; result && i < map->n; ++i)
7878 for (j = 0; j < set->n; ++j) {
7879 result = isl_map_add_basic_map(result,
7880 fn(isl_basic_map_copy(map->p[i]),
7881 isl_basic_set_copy(set->p[j])));
7882 if (!result)
7883 break;
7886 isl_map_free(map);
7887 isl_set_free(set);
7888 return result;
7891 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7892 __isl_take isl_set *set)
7894 isl_bool ok;
7896 ok = isl_map_compatible_range(map, set);
7897 if (ok < 0)
7898 goto error;
7899 if (!ok)
7900 isl_die(set->ctx, isl_error_invalid,
7901 "incompatible spaces", goto error);
7903 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7904 error:
7905 isl_map_free(map);
7906 isl_set_free(set);
7907 return NULL;
7910 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7911 __isl_take isl_set *set)
7913 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7916 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7917 __isl_take isl_set *set)
7919 isl_bool ok;
7921 ok = isl_map_compatible_domain(map, set);
7922 if (ok < 0)
7923 goto error;
7924 if (!ok)
7925 isl_die(set->ctx, isl_error_invalid,
7926 "incompatible spaces", goto error);
7928 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7929 error:
7930 isl_map_free(map);
7931 isl_set_free(set);
7932 return NULL;
7935 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7936 __isl_take isl_set *set)
7938 return isl_map_align_params_map_map_and(map, set,
7939 &map_intersect_domain);
7942 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7943 * in the space B -> C, return the intersection.
7944 * The parameters are assumed to have been aligned.
7946 * The map "factor" is first extended to a map living in the space
7947 * [A -> B] -> C and then a regular intersection is computed.
7949 static __isl_give isl_map *map_intersect_domain_factor_range(
7950 __isl_take isl_map *map, __isl_take isl_map *factor)
7952 isl_space *space;
7953 isl_map *ext_factor;
7955 space = isl_space_domain_factor_domain(isl_map_get_space(map));
7956 ext_factor = isl_map_universe(space);
7957 ext_factor = isl_map_domain_product(ext_factor, factor);
7958 return map_intersect(map, ext_factor);
7961 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7962 * in the space B -> C, return the intersection.
7964 __isl_give isl_map *isl_map_intersect_domain_factor_range(
7965 __isl_take isl_map *map, __isl_take isl_map *factor)
7967 return isl_map_align_params_map_map_and(map, factor,
7968 &map_intersect_domain_factor_range);
7971 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7972 * in the space A -> C, return the intersection.
7974 * The map "factor" is first extended to a map living in the space
7975 * A -> [B -> C] and then a regular intersection is computed.
7977 static __isl_give isl_map *map_intersect_range_factor_range(
7978 __isl_take isl_map *map, __isl_take isl_map *factor)
7980 isl_space *space;
7981 isl_map *ext_factor;
7983 space = isl_space_range_factor_domain(isl_map_get_space(map));
7984 ext_factor = isl_map_universe(space);
7985 ext_factor = isl_map_range_product(ext_factor, factor);
7986 return isl_map_intersect(map, ext_factor);
7989 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7990 * in the space A -> C, return the intersection.
7992 __isl_give isl_map *isl_map_intersect_range_factor_range(
7993 __isl_take isl_map *map, __isl_take isl_map *factor)
7995 return isl_map_align_params_map_map_and(map, factor,
7996 &map_intersect_range_factor_range);
7999 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
8000 __isl_take isl_map *map2)
8002 if (!map1 || !map2)
8003 goto error;
8004 map1 = isl_map_reverse(map1);
8005 map1 = isl_map_apply_range(map1, map2);
8006 return isl_map_reverse(map1);
8007 error:
8008 isl_map_free(map1);
8009 isl_map_free(map2);
8010 return NULL;
8013 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8014 __isl_take isl_map *map2)
8016 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
8019 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
8020 __isl_take isl_map *map2)
8022 isl_space *space;
8023 struct isl_map *result;
8024 int i, j;
8026 if (!map1 || !map2)
8027 goto error;
8029 space = isl_space_join(isl_space_copy(map1->dim),
8030 isl_space_copy(map2->dim));
8032 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
8033 if (!result)
8034 goto error;
8035 for (i = 0; i < map1->n; ++i)
8036 for (j = 0; j < map2->n; ++j) {
8037 result = isl_map_add_basic_map(result,
8038 isl_basic_map_apply_range(
8039 isl_basic_map_copy(map1->p[i]),
8040 isl_basic_map_copy(map2->p[j])));
8041 if (!result)
8042 goto error;
8044 isl_map_free(map1);
8045 isl_map_free(map2);
8046 if (result && result->n <= 1)
8047 ISL_F_SET(result, ISL_MAP_DISJOINT);
8048 return result;
8049 error:
8050 isl_map_free(map1);
8051 isl_map_free(map2);
8052 return NULL;
8055 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8056 __isl_take isl_map *map2)
8058 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
8062 * returns range - domain
8064 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8066 isl_space *target_space;
8067 struct isl_basic_set *bset;
8068 isl_size dim;
8069 isl_size nparam;
8070 isl_size total;
8071 int i;
8073 if (!bmap)
8074 goto error;
8075 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8076 bmap->dim, isl_dim_out),
8077 goto error);
8078 dim = isl_basic_map_dim(bmap, isl_dim_in);
8079 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8080 if (dim < 0 || nparam < 0)
8081 goto error;
8082 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8083 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8084 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8085 total = isl_basic_map_dim(bmap, isl_dim_all);
8086 if (total < 0)
8087 bmap = isl_basic_map_free(bmap);
8088 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8089 for (i = 0; i < dim; ++i) {
8090 int j = isl_basic_map_alloc_equality(bmap);
8091 if (j < 0) {
8092 bmap = isl_basic_map_free(bmap);
8093 break;
8095 isl_seq_clr(bmap->eq[j], 1 + total);
8096 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8097 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8098 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8100 bset = isl_basic_map_domain(bmap);
8101 bset = isl_basic_set_reset_space(bset, target_space);
8102 return bset;
8103 error:
8104 isl_basic_map_free(bmap);
8105 return NULL;
8108 /* Check that domain and range of "map" are the same.
8110 isl_stat isl_map_check_equal_tuples(__isl_keep isl_map *map)
8112 isl_space *space;
8113 isl_bool equal;
8115 space = isl_map_peek_space(map);
8116 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8117 if (equal < 0)
8118 return isl_stat_error;
8119 if (!equal)
8120 isl_die(isl_map_get_ctx(map), isl_error_invalid,
8121 "domain and range don't match", return isl_stat_error);
8122 return isl_stat_ok;
8126 * returns range - domain
8128 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8130 int i;
8131 isl_space *dim;
8132 struct isl_set *result;
8134 if (!map)
8135 return NULL;
8137 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
8138 map->dim, isl_dim_out),
8139 goto error);
8140 dim = isl_map_get_space(map);
8141 dim = isl_space_domain(dim);
8142 result = isl_set_alloc_space(dim, map->n, 0);
8143 if (!result)
8144 goto error;
8145 for (i = 0; i < map->n; ++i)
8146 result = isl_set_add_basic_set(result,
8147 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8148 isl_map_free(map);
8149 return result;
8150 error:
8151 isl_map_free(map);
8152 return NULL;
8156 * returns [domain -> range] -> range - domain
8158 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8159 __isl_take isl_basic_map *bmap)
8161 int i, k;
8162 isl_space *space;
8163 isl_basic_map *domain;
8164 isl_size nparam, n;
8165 isl_size total;
8167 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8168 bmap->dim, isl_dim_out))
8169 isl_die(bmap->ctx, isl_error_invalid,
8170 "domain and range don't match", goto error);
8172 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8173 n = isl_basic_map_dim(bmap, isl_dim_in);
8174 if (nparam < 0 || n < 0)
8175 return isl_basic_map_free(bmap);
8177 space = isl_basic_map_get_space(bmap);
8178 space = isl_space_from_range(isl_space_domain(space));
8179 domain = isl_basic_map_universe(space);
8181 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8182 bmap = isl_basic_map_apply_range(bmap, domain);
8183 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8185 total = isl_basic_map_dim(bmap, isl_dim_all);
8186 if (total < 0)
8187 return isl_basic_map_free(bmap);
8189 for (i = 0; i < n; ++i) {
8190 k = isl_basic_map_alloc_equality(bmap);
8191 if (k < 0)
8192 goto error;
8193 isl_seq_clr(bmap->eq[k], 1 + total);
8194 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8195 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8196 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8199 bmap = isl_basic_map_gauss(bmap, NULL);
8200 return isl_basic_map_finalize(bmap);
8201 error:
8202 isl_basic_map_free(bmap);
8203 return NULL;
8207 * returns [domain -> range] -> range - domain
8209 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8211 int i;
8212 isl_space *domain_space;
8214 if (isl_map_check_equal_tuples(map) < 0)
8215 return isl_map_free(map);
8217 map = isl_map_cow(map);
8218 if (!map)
8219 return NULL;
8221 domain_space = isl_space_domain(isl_map_get_space(map));
8222 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
8223 map->dim = isl_space_join(map->dim, isl_space_from_range(domain_space));
8224 if (!map->dim)
8225 goto error;
8226 for (i = 0; i < map->n; ++i) {
8227 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
8228 if (!map->p[i])
8229 goto error;
8231 map = isl_map_unmark_normalized(map);
8232 return map;
8233 error:
8234 isl_map_free(map);
8235 return NULL;
8238 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8240 isl_size n_in, n_out;
8242 n_in = isl_space_dim(space, isl_dim_in);
8243 n_out = isl_space_dim(space, isl_dim_out);
8244 if (n_in < 0 || n_out < 0)
8245 goto error;
8246 if (n_in != n_out)
8247 isl_die(space->ctx, isl_error_invalid,
8248 "number of input and output dimensions needs to be "
8249 "the same", goto error);
8250 return isl_basic_map_equal(space, n_in);
8251 error:
8252 isl_space_free(space);
8253 return NULL;
8256 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
8258 return isl_map_from_basic_map(isl_basic_map_identity(dim));
8261 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8263 isl_space *dim = isl_set_get_space(set);
8264 isl_map *id;
8265 id = isl_map_identity(isl_space_map_from_set(dim));
8266 return isl_map_intersect_range(id, set);
8269 /* Construct a basic set with all set dimensions having only non-negative
8270 * values.
8272 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8273 __isl_take isl_space *space)
8275 int i;
8276 isl_size nparam;
8277 isl_size dim;
8278 isl_size total;
8279 struct isl_basic_set *bset;
8281 nparam = isl_space_dim(space, isl_dim_param);
8282 dim = isl_space_dim(space, isl_dim_set);
8283 total = isl_space_dim(space, isl_dim_all);
8284 if (nparam < 0 || dim < 0 || total < 0)
8285 space = isl_space_free(space);
8286 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8287 if (!bset)
8288 return NULL;
8289 for (i = 0; i < dim; ++i) {
8290 int k = isl_basic_set_alloc_inequality(bset);
8291 if (k < 0)
8292 goto error;
8293 isl_seq_clr(bset->ineq[k], 1 + total);
8294 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8296 return bset;
8297 error:
8298 isl_basic_set_free(bset);
8299 return NULL;
8302 /* Construct the half-space x_pos >= 0.
8304 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8305 int pos)
8307 int k;
8308 isl_size total;
8309 isl_basic_set *nonneg;
8311 total = isl_space_dim(space, isl_dim_all);
8312 if (total < 0)
8313 space = isl_space_free(space);
8314 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8315 k = isl_basic_set_alloc_inequality(nonneg);
8316 if (k < 0)
8317 goto error;
8318 isl_seq_clr(nonneg->ineq[k], 1 + total);
8319 isl_int_set_si(nonneg->ineq[k][pos], 1);
8321 return isl_basic_set_finalize(nonneg);
8322 error:
8323 isl_basic_set_free(nonneg);
8324 return NULL;
8327 /* Construct the half-space x_pos <= -1.
8329 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8330 int pos)
8332 int k;
8333 isl_size total;
8334 isl_basic_set *neg;
8336 total = isl_space_dim(space, isl_dim_all);
8337 if (total < 0)
8338 space = isl_space_free(space);
8339 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8340 k = isl_basic_set_alloc_inequality(neg);
8341 if (k < 0)
8342 goto error;
8343 isl_seq_clr(neg->ineq[k], 1 + total);
8344 isl_int_set_si(neg->ineq[k][0], -1);
8345 isl_int_set_si(neg->ineq[k][pos], -1);
8347 return isl_basic_set_finalize(neg);
8348 error:
8349 isl_basic_set_free(neg);
8350 return NULL;
8353 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8354 enum isl_dim_type type, unsigned first, unsigned n)
8356 int i;
8357 unsigned offset;
8358 isl_basic_set *nonneg;
8359 isl_basic_set *neg;
8361 if (n == 0)
8362 return set;
8364 if (isl_set_check_range(set, type, first, n) < 0)
8365 return isl_set_free(set);
8367 offset = pos(set->dim, type);
8368 for (i = 0; i < n; ++i) {
8369 nonneg = nonneg_halfspace(isl_set_get_space(set),
8370 offset + first + i);
8371 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8373 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8376 return set;
8379 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8380 int len,
8381 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8382 void *user)
8384 isl_set *half;
8386 if (!set)
8387 return isl_stat_error;
8388 if (isl_set_plain_is_empty(set)) {
8389 isl_set_free(set);
8390 return isl_stat_ok;
8392 if (first == len)
8393 return fn(set, signs, user);
8395 signs[first] = 1;
8396 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8397 1 + first));
8398 half = isl_set_intersect(half, isl_set_copy(set));
8399 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8400 goto error;
8402 signs[first] = -1;
8403 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8404 1 + first));
8405 half = isl_set_intersect(half, set);
8406 return foreach_orthant(half, signs, first + 1, len, fn, user);
8407 error:
8408 isl_set_free(set);
8409 return isl_stat_error;
8412 /* Call "fn" on the intersections of "set" with each of the orthants
8413 * (except for obviously empty intersections). The orthant is identified
8414 * by the signs array, with each entry having value 1 or -1 according
8415 * to the sign of the corresponding variable.
8417 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8418 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8419 void *user)
8421 isl_size nparam;
8422 isl_size nvar;
8423 int *signs;
8424 isl_stat r;
8426 if (!set)
8427 return isl_stat_error;
8428 if (isl_set_plain_is_empty(set))
8429 return isl_stat_ok;
8431 nparam = isl_set_dim(set, isl_dim_param);
8432 nvar = isl_set_dim(set, isl_dim_set);
8433 if (nparam < 0 || nvar < 0)
8434 return isl_stat_error;
8436 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8438 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8439 fn, user);
8441 free(signs);
8443 return r;
8446 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8448 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8451 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8452 __isl_keep isl_basic_map *bmap2)
8454 isl_bool is_subset;
8455 struct isl_map *map1;
8456 struct isl_map *map2;
8458 if (!bmap1 || !bmap2)
8459 return isl_bool_error;
8461 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8462 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8464 is_subset = isl_map_is_subset(map1, map2);
8466 isl_map_free(map1);
8467 isl_map_free(map2);
8469 return is_subset;
8472 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8473 __isl_keep isl_basic_set *bset2)
8475 return isl_basic_map_is_subset(bset1, bset2);
8478 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8479 __isl_keep isl_basic_map *bmap2)
8481 isl_bool is_subset;
8483 if (!bmap1 || !bmap2)
8484 return isl_bool_error;
8485 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8486 if (is_subset != isl_bool_true)
8487 return is_subset;
8488 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8489 return is_subset;
8492 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8493 __isl_keep isl_basic_set *bset2)
8495 return isl_basic_map_is_equal(
8496 bset_to_bmap(bset1), bset_to_bmap(bset2));
8499 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8501 int i;
8502 int is_empty;
8504 if (!map)
8505 return isl_bool_error;
8506 for (i = 0; i < map->n; ++i) {
8507 is_empty = isl_basic_map_is_empty(map->p[i]);
8508 if (is_empty < 0)
8509 return isl_bool_error;
8510 if (!is_empty)
8511 return isl_bool_false;
8513 return isl_bool_true;
8516 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8518 return map ? map->n == 0 : isl_bool_error;
8521 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8523 return set ? set->n == 0 : isl_bool_error;
8526 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8528 return isl_map_is_empty(set_to_map(set));
8531 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
8532 __isl_keep isl_map *map2)
8534 if (!map1 || !map2)
8535 return isl_bool_error;
8537 return isl_space_is_equal(map1->dim, map2->dim);
8540 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
8541 __isl_keep isl_set *set2)
8543 if (!set1 || !set2)
8544 return isl_bool_error;
8546 return isl_space_is_equal(set1->dim, set2->dim);
8549 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8551 isl_bool is_subset;
8553 if (!map1 || !map2)
8554 return isl_bool_error;
8555 is_subset = isl_map_is_subset(map1, map2);
8556 if (is_subset != isl_bool_true)
8557 return is_subset;
8558 is_subset = isl_map_is_subset(map2, map1);
8559 return is_subset;
8562 /* Is "map1" equal to "map2"?
8564 * First check if they are obviously equal.
8565 * If not, then perform a more detailed analysis.
8567 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8569 isl_bool equal;
8571 equal = isl_map_plain_is_equal(map1, map2);
8572 if (equal < 0 || equal)
8573 return equal;
8574 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8577 isl_bool isl_basic_map_is_strict_subset(
8578 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8580 isl_bool is_subset;
8582 if (!bmap1 || !bmap2)
8583 return isl_bool_error;
8584 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8585 if (is_subset != isl_bool_true)
8586 return is_subset;
8587 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8588 return isl_bool_not(is_subset);
8591 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8592 __isl_keep isl_map *map2)
8594 isl_bool is_subset;
8596 if (!map1 || !map2)
8597 return isl_bool_error;
8598 is_subset = isl_map_is_subset(map1, map2);
8599 if (is_subset != isl_bool_true)
8600 return is_subset;
8601 is_subset = isl_map_is_subset(map2, map1);
8602 return isl_bool_not(is_subset);
8605 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8606 __isl_keep isl_set *set2)
8608 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8611 /* Is "bmap" obviously equal to the universe with the same space?
8613 * That is, does it not have any constraints?
8615 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8617 if (!bmap)
8618 return isl_bool_error;
8619 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8622 /* Is "bset" obviously equal to the universe with the same space?
8624 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8626 return isl_basic_map_plain_is_universe(bset);
8629 /* If "c" does not involve any existentially quantified variables,
8630 * then set *univ to false and abort
8632 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8634 isl_bool *univ = user;
8635 isl_size n;
8637 n = isl_constraint_dim(c, isl_dim_div);
8638 if (n < 0)
8639 c = isl_constraint_free(c);
8640 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8641 isl_constraint_free(c);
8642 if (*univ < 0 || !*univ)
8643 return isl_stat_error;
8644 return isl_stat_ok;
8647 /* Is "bmap" equal to the universe with the same space?
8649 * First check if it is obviously equal to the universe.
8650 * If not and if there are any constraints not involving
8651 * existentially quantified variables, then it is certainly
8652 * not equal to the universe.
8653 * Otherwise, check if the universe is a subset of "bmap".
8655 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8657 isl_size n_div;
8658 isl_bool univ;
8659 isl_basic_map *test;
8661 univ = isl_basic_map_plain_is_universe(bmap);
8662 if (univ < 0 || univ)
8663 return univ;
8664 n_div = isl_basic_map_dim(bmap, isl_dim_div);
8665 if (n_div < 0)
8666 return isl_bool_error;
8667 if (n_div == 0)
8668 return isl_bool_false;
8669 univ = isl_bool_true;
8670 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8671 univ)
8672 return isl_bool_error;
8673 if (univ < 0 || !univ)
8674 return univ;
8675 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8676 univ = isl_basic_map_is_subset(test, bmap);
8677 isl_basic_map_free(test);
8678 return univ;
8681 /* Is "bset" equal to the universe with the same space?
8683 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8685 return isl_basic_map_is_universe(bset);
8688 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8690 int i;
8692 if (!map)
8693 return isl_bool_error;
8695 for (i = 0; i < map->n; ++i) {
8696 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8697 if (r < 0 || r)
8698 return r;
8701 return isl_bool_false;
8704 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8706 return isl_map_plain_is_universe(set_to_map(set));
8709 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8711 struct isl_basic_set *bset = NULL;
8712 struct isl_vec *sample = NULL;
8713 isl_bool empty, non_empty;
8715 if (!bmap)
8716 return isl_bool_error;
8718 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8719 return isl_bool_true;
8721 if (isl_basic_map_plain_is_universe(bmap))
8722 return isl_bool_false;
8724 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8725 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8726 copy = isl_basic_map_remove_redundancies(copy);
8727 empty = isl_basic_map_plain_is_empty(copy);
8728 isl_basic_map_free(copy);
8729 return empty;
8732 non_empty = isl_basic_map_plain_is_non_empty(bmap);
8733 if (non_empty < 0)
8734 return isl_bool_error;
8735 if (non_empty)
8736 return isl_bool_false;
8737 isl_vec_free(bmap->sample);
8738 bmap->sample = NULL;
8739 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8740 if (!bset)
8741 return isl_bool_error;
8742 sample = isl_basic_set_sample_vec(bset);
8743 if (!sample)
8744 return isl_bool_error;
8745 empty = sample->size == 0;
8746 isl_vec_free(bmap->sample);
8747 bmap->sample = sample;
8748 if (empty)
8749 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8751 return empty;
8754 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8756 if (!bmap)
8757 return isl_bool_error;
8758 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8761 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8763 if (!bset)
8764 return isl_bool_error;
8765 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8768 /* Is "bmap" known to be non-empty?
8770 * That is, is the cached sample still valid?
8772 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8774 isl_size total;
8776 if (!bmap)
8777 return isl_bool_error;
8778 if (!bmap->sample)
8779 return isl_bool_false;
8780 total = isl_basic_map_dim(bmap, isl_dim_all);
8781 if (total < 0)
8782 return isl_bool_error;
8783 if (bmap->sample->size != 1 + total)
8784 return isl_bool_false;
8785 return isl_basic_map_contains(bmap, bmap->sample);
8788 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8790 return isl_basic_map_is_empty(bset_to_bmap(bset));
8793 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
8794 __isl_take isl_basic_map *bmap2)
8796 struct isl_map *map;
8797 if (!bmap1 || !bmap2)
8798 goto error;
8800 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8802 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8803 if (!map)
8804 goto error;
8805 map = isl_map_add_basic_map(map, bmap1);
8806 map = isl_map_add_basic_map(map, bmap2);
8807 return map;
8808 error:
8809 isl_basic_map_free(bmap1);
8810 isl_basic_map_free(bmap2);
8811 return NULL;
8814 struct isl_set *isl_basic_set_union(
8815 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8817 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8818 bset_to_bmap(bset2)));
8821 /* Order divs such that any div only depends on previous divs */
8822 __isl_give isl_basic_map *isl_basic_map_order_divs(
8823 __isl_take isl_basic_map *bmap)
8825 int i;
8826 isl_size off;
8828 off = isl_basic_map_var_offset(bmap, isl_dim_div);
8829 if (off < 0)
8830 return isl_basic_map_free(bmap);
8832 for (i = 0; i < bmap->n_div; ++i) {
8833 int pos;
8834 if (isl_int_is_zero(bmap->div[i][0]))
8835 continue;
8836 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8837 bmap->n_div-i);
8838 if (pos == -1)
8839 continue;
8840 if (pos == 0)
8841 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8842 "integer division depends on itself",
8843 return isl_basic_map_free(bmap));
8844 bmap = isl_basic_map_swap_div(bmap, i, i + pos);
8845 if (!bmap)
8846 return NULL;
8847 --i;
8849 return bmap;
8852 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8854 return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8857 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8859 int i;
8861 if (!map)
8862 return 0;
8864 for (i = 0; i < map->n; ++i) {
8865 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8866 if (!map->p[i])
8867 goto error;
8870 return map;
8871 error:
8872 isl_map_free(map);
8873 return NULL;
8876 /* Sort the local variables of "bset".
8878 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8879 __isl_take isl_basic_set *bset)
8881 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8884 /* Apply the expansion computed by isl_merge_divs.
8885 * The expansion itself is given by "exp" while the resulting
8886 * list of divs is given by "div".
8888 * Move the integer divisions of "bmap" into the right position
8889 * according to "exp" and then introduce the additional integer
8890 * divisions, adding div constraints.
8891 * The moving should be done first to avoid moving coefficients
8892 * in the definitions of the extra integer divisions.
8894 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8895 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8897 int i, j;
8898 int n_div;
8900 bmap = isl_basic_map_cow(bmap);
8901 if (!bmap || !div)
8902 goto error;
8904 if (div->n_row < bmap->n_div)
8905 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8906 "not an expansion", goto error);
8908 n_div = bmap->n_div;
8909 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8910 div->n_row - n_div, 0,
8911 2 * (div->n_row - n_div));
8913 for (i = n_div; i < div->n_row; ++i)
8914 if (isl_basic_map_alloc_div(bmap) < 0)
8915 goto error;
8917 for (j = n_div - 1; j >= 0; --j) {
8918 if (exp[j] == j)
8919 break;
8920 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
8921 if (!bmap)
8922 goto error;
8924 j = 0;
8925 for (i = 0; i < div->n_row; ++i) {
8926 if (j < n_div && exp[j] == i) {
8927 j++;
8928 } else {
8929 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8930 if (isl_basic_map_div_is_marked_unknown(bmap, i))
8931 continue;
8932 bmap = isl_basic_map_add_div_constraints(bmap, i);
8933 if (!bmap)
8934 goto error;
8938 isl_mat_free(div);
8939 return bmap;
8940 error:
8941 isl_basic_map_free(bmap);
8942 isl_mat_free(div);
8943 return NULL;
8946 /* Apply the expansion computed by isl_merge_divs.
8947 * The expansion itself is given by "exp" while the resulting
8948 * list of divs is given by "div".
8950 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8951 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8953 return isl_basic_map_expand_divs(bset, div, exp);
8956 /* Look for a div in dst that corresponds to the div "div" in src.
8957 * The divs before "div" in src and dst are assumed to be the same.
8959 * Return the position of the corresponding div in dst
8960 * if there is one. Otherwise, return a position beyond the integer divisions.
8961 * Return -1 on error.
8963 static int find_div(__isl_keep isl_basic_map *dst,
8964 __isl_keep isl_basic_map *src, unsigned div)
8966 int i;
8967 isl_size n_div;
8968 isl_size v_div;
8970 v_div = isl_basic_map_var_offset(src, isl_dim_div);
8971 n_div = isl_basic_map_dim(dst, isl_dim_div);
8972 if (n_div < 0 || v_div < 0)
8973 return -1;
8974 isl_assert(dst->ctx, div <= n_div, return -1);
8975 for (i = div; i < n_div; ++i)
8976 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
8977 isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
8978 n_div - div) == -1)
8979 return i;
8980 return n_div;
8983 /* Align the divs of "dst" to those of "src", adding divs from "src"
8984 * if needed. That is, make sure that the first src->n_div divs
8985 * of the result are equal to those of src.
8987 * The result is not finalized as by design it will have redundant
8988 * divs if any divs from "src" were copied.
8990 __isl_give isl_basic_map *isl_basic_map_align_divs(
8991 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8993 int i;
8994 isl_bool known;
8995 int extended;
8996 isl_size v_div;
8997 isl_size dst_n_div;
8999 if (!dst || !src)
9000 return isl_basic_map_free(dst);
9002 if (src->n_div == 0)
9003 return dst;
9005 known = isl_basic_map_divs_known(src);
9006 if (known < 0)
9007 return isl_basic_map_free(dst);
9008 if (!known)
9009 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9010 "some src divs are unknown",
9011 return isl_basic_map_free(dst));
9013 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9014 if (v_div < 0)
9015 return isl_basic_map_free(dst);
9017 src = isl_basic_map_order_divs(isl_basic_map_copy(src));
9018 if (!src)
9019 return isl_basic_map_free(dst);
9021 extended = 0;
9022 dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
9023 if (dst_n_div < 0)
9024 dst = isl_basic_map_free(dst);
9025 for (i = 0; i < src->n_div; ++i) {
9026 int j = find_div(dst, src, i);
9027 if (j < 0)
9028 dst = isl_basic_map_free(dst);
9029 if (j == dst_n_div) {
9030 if (!extended) {
9031 int extra = src->n_div - i;
9032 dst = isl_basic_map_cow(dst);
9033 if (!dst)
9034 goto error;
9035 dst = isl_basic_map_extend_space(dst,
9036 isl_space_copy(dst->dim),
9037 extra, 0, 2 * extra);
9038 extended = 1;
9040 j = isl_basic_map_alloc_div(dst);
9041 if (j < 0)
9042 goto error;
9043 isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
9044 isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
9045 dst_n_div++;
9046 dst = isl_basic_map_add_div_constraints(dst, j);
9047 if (!dst)
9048 goto error;
9050 if (j != i)
9051 dst = isl_basic_map_swap_div(dst, i, j);
9052 if (!dst)
9053 goto error;
9055 isl_basic_map_free(src);
9056 return dst;
9057 error:
9058 isl_basic_map_free(src);
9059 isl_basic_map_free(dst);
9060 return NULL;
9063 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9065 int i;
9067 if (!map)
9068 return NULL;
9069 if (map->n == 0)
9070 return map;
9071 map = isl_map_compute_divs(map);
9072 map = isl_map_cow(map);
9073 if (!map)
9074 return NULL;
9076 for (i = 1; i < map->n; ++i)
9077 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9078 for (i = 1; i < map->n; ++i) {
9079 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9080 if (!map->p[i])
9081 return isl_map_free(map);
9084 map = isl_map_unmark_normalized(map);
9085 return map;
9088 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9090 return isl_map_align_divs_internal(map);
9093 struct isl_set *isl_set_align_divs(struct isl_set *set)
9095 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9098 /* Align the divs of the basic maps in "map" to those
9099 * of the basic maps in "list", as well as to the other basic maps in "map".
9100 * The elements in "list" are assumed to have known divs.
9102 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9103 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9105 int i;
9106 isl_size n;
9108 n = isl_basic_map_list_n_basic_map(list);
9109 map = isl_map_compute_divs(map);
9110 map = isl_map_cow(map);
9111 if (!map || n < 0)
9112 return isl_map_free(map);
9113 if (map->n == 0)
9114 return map;
9116 for (i = 0; i < n; ++i) {
9117 isl_basic_map *bmap;
9119 bmap = isl_basic_map_list_get_basic_map(list, i);
9120 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9121 isl_basic_map_free(bmap);
9123 if (!map->p[0])
9124 return isl_map_free(map);
9126 return isl_map_align_divs_internal(map);
9129 /* Align the divs of each element of "list" to those of "bmap".
9130 * Both "bmap" and the elements of "list" are assumed to have known divs.
9132 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9133 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9135 int i;
9136 isl_size n;
9138 n = isl_basic_map_list_n_basic_map(list);
9139 if (n < 0 || !bmap)
9140 return isl_basic_map_list_free(list);
9142 for (i = 0; i < n; ++i) {
9143 isl_basic_map *bmap_i;
9145 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9146 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9147 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9150 return list;
9153 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
9154 __isl_take isl_map *map)
9156 isl_bool ok;
9158 ok = isl_map_compatible_domain(map, set);
9159 if (ok < 0)
9160 goto error;
9161 if (!ok)
9162 isl_die(isl_set_get_ctx(set), isl_error_invalid,
9163 "incompatible spaces", goto error);
9164 map = isl_map_intersect_domain(map, set);
9165 set = isl_map_range(map);
9166 return set;
9167 error:
9168 isl_set_free(set);
9169 isl_map_free(map);
9170 return NULL;
9173 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9174 __isl_take isl_map *map)
9176 return isl_map_align_params_map_map_and(set, map, &set_apply);
9179 /* There is no need to cow as removing empty parts doesn't change
9180 * the meaning of the set.
9182 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9184 int i;
9186 if (!map)
9187 return NULL;
9189 for (i = map->n - 1; i >= 0; --i)
9190 map = remove_if_empty(map, i);
9192 return map;
9195 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
9197 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9200 /* Create a binary relation that maps the shared initial "pos" dimensions
9201 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9203 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9204 __isl_keep isl_basic_set *bset2, int pos)
9206 isl_basic_map *bmap1;
9207 isl_basic_map *bmap2;
9209 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9210 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9211 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9212 isl_dim_out, 0, pos);
9213 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9214 isl_dim_out, 0, pos);
9215 return isl_basic_map_range_product(bmap1, bmap2);
9218 /* Given two basic sets bset1 and bset2, compute the maximal difference
9219 * between the values of dimension pos in bset1 and those in bset2
9220 * for any common value of the parameters and dimensions preceding pos.
9222 static enum isl_lp_result basic_set_maximal_difference_at(
9223 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9224 int pos, isl_int *opt)
9226 isl_basic_map *bmap1;
9227 struct isl_ctx *ctx;
9228 struct isl_vec *obj;
9229 isl_size total;
9230 isl_size nparam;
9231 isl_size dim1;
9232 enum isl_lp_result res;
9234 nparam = isl_basic_set_dim(bset1, isl_dim_param);
9235 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9236 if (nparam < 0 || dim1 < 0 || !bset2)
9237 return isl_lp_error;
9239 bmap1 = join_initial(bset1, bset2, pos);
9240 total = isl_basic_map_dim(bmap1, isl_dim_all);
9241 if (total < 0)
9242 return isl_lp_error;
9244 ctx = bmap1->ctx;
9245 obj = isl_vec_alloc(ctx, 1 + total);
9246 if (!obj)
9247 goto error;
9248 isl_seq_clr(obj->block.data, 1 + total);
9249 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9250 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9251 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9252 opt, NULL, NULL);
9253 isl_basic_map_free(bmap1);
9254 isl_vec_free(obj);
9255 return res;
9256 error:
9257 isl_basic_map_free(bmap1);
9258 return isl_lp_error;
9261 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9262 * for any common value of the parameters and dimensions preceding pos
9263 * in both basic sets, the values of dimension pos in bset1 are
9264 * smaller or larger than those in bset2.
9266 * Returns
9267 * 1 if bset1 follows bset2
9268 * -1 if bset1 precedes bset2
9269 * 0 if bset1 and bset2 are incomparable
9270 * -2 if some error occurred.
9272 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9273 __isl_keep isl_basic_set *bset2, int pos)
9275 isl_int opt;
9276 enum isl_lp_result res;
9277 int cmp;
9279 isl_int_init(opt);
9281 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9283 if (res == isl_lp_empty)
9284 cmp = 0;
9285 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9286 res == isl_lp_unbounded)
9287 cmp = 1;
9288 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9289 cmp = -1;
9290 else
9291 cmp = -2;
9293 isl_int_clear(opt);
9294 return cmp;
9297 /* Given two basic sets bset1 and bset2, check whether
9298 * for any common value of the parameters and dimensions preceding pos
9299 * there is a value of dimension pos in bset1 that is larger
9300 * than a value of the same dimension in bset2.
9302 * Return
9303 * 1 if there exists such a pair
9304 * 0 if there is no such pair, but there is a pair of equal values
9305 * -1 otherwise
9306 * -2 if some error occurred.
9308 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9309 __isl_keep isl_basic_set *bset2, int pos)
9311 isl_bool empty;
9312 isl_basic_map *bmap;
9313 isl_size dim1;
9315 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9316 if (dim1 < 0)
9317 return -2;
9318 bmap = join_initial(bset1, bset2, pos);
9319 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9320 isl_dim_out, dim1 - pos);
9321 empty = isl_basic_map_is_empty(bmap);
9322 if (empty < 0)
9323 goto error;
9324 if (empty) {
9325 isl_basic_map_free(bmap);
9326 return -1;
9328 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9329 isl_dim_out, dim1 - pos);
9330 empty = isl_basic_map_is_empty(bmap);
9331 if (empty < 0)
9332 goto error;
9333 isl_basic_map_free(bmap);
9334 if (empty)
9335 return 0;
9336 return 1;
9337 error:
9338 isl_basic_map_free(bmap);
9339 return -2;
9342 /* Given two sets set1 and set2, check whether
9343 * for any common value of the parameters and dimensions preceding pos
9344 * there is a value of dimension pos in set1 that is larger
9345 * than a value of the same dimension in set2.
9347 * Return
9348 * 1 if there exists such a pair
9349 * 0 if there is no such pair, but there is a pair of equal values
9350 * -1 otherwise
9351 * -2 if some error occurred.
9353 int isl_set_follows_at(__isl_keep isl_set *set1,
9354 __isl_keep isl_set *set2, int pos)
9356 int i, j;
9357 int follows = -1;
9359 if (!set1 || !set2)
9360 return -2;
9362 for (i = 0; i < set1->n; ++i)
9363 for (j = 0; j < set2->n; ++j) {
9364 int f;
9365 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9366 if (f == 1 || f == -2)
9367 return f;
9368 if (f > follows)
9369 follows = f;
9372 return follows;
9375 static isl_bool isl_basic_map_plain_has_fixed_var(
9376 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9378 int i;
9379 int d;
9380 isl_size total;
9382 total = isl_basic_map_dim(bmap, isl_dim_all);
9383 if (total < 0)
9384 return isl_bool_error;
9385 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9386 for (; d+1 > pos; --d)
9387 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9388 break;
9389 if (d != pos)
9390 continue;
9391 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9392 return isl_bool_false;
9393 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9394 return isl_bool_false;
9395 if (!isl_int_is_one(bmap->eq[i][1+d]))
9396 return isl_bool_false;
9397 if (val)
9398 isl_int_neg(*val, bmap->eq[i][0]);
9399 return isl_bool_true;
9401 return isl_bool_false;
9404 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9405 unsigned pos, isl_int *val)
9407 int i;
9408 isl_int v;
9409 isl_int tmp;
9410 isl_bool fixed;
9412 if (!map)
9413 return isl_bool_error;
9414 if (map->n == 0)
9415 return isl_bool_false;
9416 if (map->n == 1)
9417 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9418 isl_int_init(v);
9419 isl_int_init(tmp);
9420 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9421 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9422 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9423 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9424 fixed = isl_bool_false;
9426 if (val)
9427 isl_int_set(*val, v);
9428 isl_int_clear(tmp);
9429 isl_int_clear(v);
9430 return fixed;
9433 static isl_bool isl_basic_set_plain_has_fixed_var(
9434 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9436 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9437 pos, val);
9440 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9441 enum isl_dim_type type, unsigned pos, isl_int *val)
9443 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9444 return isl_bool_error;
9445 return isl_basic_map_plain_has_fixed_var(bmap,
9446 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9449 /* If "bmap" obviously lies on a hyperplane where the given dimension
9450 * has a fixed value, then return that value.
9451 * Otherwise return NaN.
9453 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9454 __isl_keep isl_basic_map *bmap,
9455 enum isl_dim_type type, unsigned pos)
9457 isl_ctx *ctx;
9458 isl_val *v;
9459 isl_bool fixed;
9461 if (!bmap)
9462 return NULL;
9463 ctx = isl_basic_map_get_ctx(bmap);
9464 v = isl_val_alloc(ctx);
9465 if (!v)
9466 return NULL;
9467 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9468 if (fixed < 0)
9469 return isl_val_free(v);
9470 if (fixed) {
9471 isl_int_set_si(v->d, 1);
9472 return v;
9474 isl_val_free(v);
9475 return isl_val_nan(ctx);
9478 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9479 enum isl_dim_type type, unsigned pos, isl_int *val)
9481 if (isl_map_check_range(map, type, pos, 1) < 0)
9482 return isl_bool_error;
9483 return isl_map_plain_has_fixed_var(map,
9484 map_offset(map, type) - 1 + pos, val);
9487 /* If "map" obviously lies on a hyperplane where the given dimension
9488 * has a fixed value, then return that value.
9489 * Otherwise return NaN.
9491 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9492 enum isl_dim_type type, unsigned pos)
9494 isl_ctx *ctx;
9495 isl_val *v;
9496 isl_bool fixed;
9498 if (!map)
9499 return NULL;
9500 ctx = isl_map_get_ctx(map);
9501 v = isl_val_alloc(ctx);
9502 if (!v)
9503 return NULL;
9504 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9505 if (fixed < 0)
9506 return isl_val_free(v);
9507 if (fixed) {
9508 isl_int_set_si(v->d, 1);
9509 return v;
9511 isl_val_free(v);
9512 return isl_val_nan(ctx);
9515 /* If "set" obviously lies on a hyperplane where the given dimension
9516 * has a fixed value, then return that value.
9517 * Otherwise return NaN.
9519 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
9520 enum isl_dim_type type, unsigned pos)
9522 return isl_map_plain_get_val_if_fixed(set, type, pos);
9525 /* Check if dimension dim has fixed value and if so and if val is not NULL,
9526 * then return this fixed value in *val.
9528 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
9529 unsigned dim, isl_int *val)
9531 isl_size nparam;
9533 nparam = isl_basic_set_dim(bset, isl_dim_param);
9534 if (nparam < 0)
9535 return isl_bool_error;
9536 return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
9539 /* Return -1 if the constraint "c1" should be sorted before "c2"
9540 * and 1 if it should be sorted after "c2".
9541 * Return 0 if the two constraints are the same (up to the constant term).
9543 * In particular, if a constraint involves later variables than another
9544 * then it is sorted after this other constraint.
9545 * uset_gist depends on constraints without existentially quantified
9546 * variables sorting first.
9548 * For constraints that have the same latest variable, those
9549 * with the same coefficient for this latest variable (first in absolute value
9550 * and then in actual value) are grouped together.
9551 * This is useful for detecting pairs of constraints that can
9552 * be chained in their printed representation.
9554 * Finally, within a group, constraints are sorted according to
9555 * their coefficients (excluding the constant term).
9557 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9559 isl_int **c1 = (isl_int **) p1;
9560 isl_int **c2 = (isl_int **) p2;
9561 int l1, l2;
9562 unsigned size = *(unsigned *) arg;
9563 int cmp;
9565 l1 = isl_seq_last_non_zero(*c1 + 1, size);
9566 l2 = isl_seq_last_non_zero(*c2 + 1, size);
9568 if (l1 != l2)
9569 return l1 - l2;
9571 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9572 if (cmp != 0)
9573 return cmp;
9574 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9575 if (cmp != 0)
9576 return -cmp;
9578 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9581 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
9582 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
9583 * and 0 if the two constraints are the same (up to the constant term).
9585 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
9586 isl_int *c1, isl_int *c2)
9588 isl_size total;
9589 unsigned size;
9591 total = isl_basic_map_dim(bmap, isl_dim_all);
9592 if (total < 0)
9593 return -2;
9594 size = total;
9595 return sort_constraint_cmp(&c1, &c2, &size);
9598 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9599 __isl_take isl_basic_map *bmap)
9601 isl_size total;
9602 unsigned size;
9604 if (!bmap)
9605 return NULL;
9606 if (bmap->n_ineq == 0)
9607 return bmap;
9608 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
9609 return bmap;
9610 total = isl_basic_map_dim(bmap, isl_dim_all);
9611 if (total < 0)
9612 return isl_basic_map_free(bmap);
9613 size = total;
9614 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9615 &sort_constraint_cmp, &size) < 0)
9616 return isl_basic_map_free(bmap);
9617 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
9618 return bmap;
9621 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9622 __isl_take isl_basic_set *bset)
9624 isl_basic_map *bmap = bset_to_bmap(bset);
9625 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9628 __isl_give isl_basic_map *isl_basic_map_normalize(
9629 __isl_take isl_basic_map *bmap)
9631 bmap = isl_basic_map_remove_redundancies(bmap);
9632 bmap = isl_basic_map_sort_constraints(bmap);
9633 return bmap;
9635 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9636 __isl_keep isl_basic_map *bmap2)
9638 int i, cmp;
9639 isl_size total;
9640 isl_space *space1, *space2;
9642 if (!bmap1 || !bmap2)
9643 return -1;
9645 if (bmap1 == bmap2)
9646 return 0;
9647 space1 = isl_basic_map_peek_space(bmap1);
9648 space2 = isl_basic_map_peek_space(bmap2);
9649 cmp = isl_space_cmp(space1, space2);
9650 if (cmp)
9651 return cmp;
9652 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9653 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9654 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9655 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9656 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9657 return 0;
9658 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9659 return 1;
9660 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9661 return -1;
9662 if (bmap1->n_eq != bmap2->n_eq)
9663 return bmap1->n_eq - bmap2->n_eq;
9664 if (bmap1->n_ineq != bmap2->n_ineq)
9665 return bmap1->n_ineq - bmap2->n_ineq;
9666 if (bmap1->n_div != bmap2->n_div)
9667 return bmap1->n_div - bmap2->n_div;
9668 total = isl_basic_map_dim(bmap1, isl_dim_all);
9669 if (total < 0)
9670 return -1;
9671 for (i = 0; i < bmap1->n_eq; ++i) {
9672 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9673 if (cmp)
9674 return cmp;
9676 for (i = 0; i < bmap1->n_ineq; ++i) {
9677 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9678 if (cmp)
9679 return cmp;
9681 for (i = 0; i < bmap1->n_div; ++i) {
9682 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9683 if (cmp)
9684 return cmp;
9686 return 0;
9689 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9690 __isl_keep isl_basic_set *bset2)
9692 return isl_basic_map_plain_cmp(bset1, bset2);
9695 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9697 int i, cmp;
9699 if (set1 == set2)
9700 return 0;
9701 if (set1->n != set2->n)
9702 return set1->n - set2->n;
9704 for (i = 0; i < set1->n; ++i) {
9705 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9706 if (cmp)
9707 return cmp;
9710 return 0;
9713 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9714 __isl_keep isl_basic_map *bmap2)
9716 if (!bmap1 || !bmap2)
9717 return isl_bool_error;
9718 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9721 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9722 __isl_keep isl_basic_set *bset2)
9724 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9725 bset_to_bmap(bset2));
9728 static int qsort_bmap_cmp(const void *p1, const void *p2)
9730 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9731 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9733 return isl_basic_map_plain_cmp(bmap1, bmap2);
9736 /* Sort the basic maps of "map" and remove duplicate basic maps.
9738 * While removing basic maps, we make sure that the basic maps remain
9739 * sorted because isl_map_normalize expects the basic maps of the result
9740 * to be sorted.
9742 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9744 int i, j;
9746 map = isl_map_remove_empty_parts(map);
9747 if (!map)
9748 return NULL;
9749 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9750 for (i = map->n - 1; i >= 1; --i) {
9751 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9752 continue;
9753 isl_basic_map_free(map->p[i-1]);
9754 for (j = i; j < map->n; ++j)
9755 map->p[j - 1] = map->p[j];
9756 map->n--;
9759 return map;
9762 /* Remove obvious duplicates among the basic maps of "map".
9764 * Unlike isl_map_normalize, this function does not remove redundant
9765 * constraints and only removes duplicates that have exactly the same
9766 * constraints in the input. It does sort the constraints and
9767 * the basic maps to ease the detection of duplicates.
9769 * If "map" has already been normalized or if the basic maps are
9770 * disjoint, then there can be no duplicates.
9772 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9774 int i;
9775 isl_basic_map *bmap;
9777 if (!map)
9778 return NULL;
9779 if (map->n <= 1)
9780 return map;
9781 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9782 return map;
9783 for (i = 0; i < map->n; ++i) {
9784 bmap = isl_basic_map_copy(map->p[i]);
9785 bmap = isl_basic_map_sort_constraints(bmap);
9786 if (!bmap)
9787 return isl_map_free(map);
9788 isl_basic_map_free(map->p[i]);
9789 map->p[i] = bmap;
9792 map = sort_and_remove_duplicates(map);
9793 return map;
9796 /* We normalize in place, but if anything goes wrong we need
9797 * to return NULL, so we need to make sure we don't change the
9798 * meaning of any possible other copies of map.
9800 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9802 int i;
9803 struct isl_basic_map *bmap;
9805 if (!map)
9806 return NULL;
9807 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9808 return map;
9809 for (i = 0; i < map->n; ++i) {
9810 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9811 if (!bmap)
9812 goto error;
9813 isl_basic_map_free(map->p[i]);
9814 map->p[i] = bmap;
9817 map = sort_and_remove_duplicates(map);
9818 if (map)
9819 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9820 return map;
9821 error:
9822 isl_map_free(map);
9823 return NULL;
9826 struct isl_set *isl_set_normalize(struct isl_set *set)
9828 return set_from_map(isl_map_normalize(set_to_map(set)));
9831 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9832 __isl_keep isl_map *map2)
9834 int i;
9835 isl_bool equal;
9837 if (!map1 || !map2)
9838 return isl_bool_error;
9840 if (map1 == map2)
9841 return isl_bool_true;
9842 if (!isl_space_is_equal(map1->dim, map2->dim))
9843 return isl_bool_false;
9845 map1 = isl_map_copy(map1);
9846 map2 = isl_map_copy(map2);
9847 map1 = isl_map_normalize(map1);
9848 map2 = isl_map_normalize(map2);
9849 if (!map1 || !map2)
9850 goto error;
9851 equal = map1->n == map2->n;
9852 for (i = 0; equal && i < map1->n; ++i) {
9853 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9854 if (equal < 0)
9855 goto error;
9857 isl_map_free(map1);
9858 isl_map_free(map2);
9859 return equal;
9860 error:
9861 isl_map_free(map1);
9862 isl_map_free(map2);
9863 return isl_bool_error;
9866 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9867 __isl_keep isl_set *set2)
9869 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9872 /* Return the basic maps in "map" as a list.
9874 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9875 __isl_keep isl_map *map)
9877 int i;
9878 isl_ctx *ctx;
9879 isl_basic_map_list *list;
9881 if (!map)
9882 return NULL;
9883 ctx = isl_map_get_ctx(map);
9884 list = isl_basic_map_list_alloc(ctx, map->n);
9886 for (i = 0; i < map->n; ++i) {
9887 isl_basic_map *bmap;
9889 bmap = isl_basic_map_copy(map->p[i]);
9890 list = isl_basic_map_list_add(list, bmap);
9893 return list;
9896 /* Return the intersection of the elements in the non-empty list "list".
9897 * All elements are assumed to live in the same space.
9899 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9900 __isl_take isl_basic_map_list *list)
9902 int i;
9903 isl_size n;
9904 isl_basic_map *bmap;
9906 n = isl_basic_map_list_n_basic_map(list);
9907 if (n < 0)
9908 goto error;
9909 if (n < 1)
9910 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9911 "expecting non-empty list", goto error);
9913 bmap = isl_basic_map_list_get_basic_map(list, 0);
9914 for (i = 1; i < n; ++i) {
9915 isl_basic_map *bmap_i;
9917 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9918 bmap = isl_basic_map_intersect(bmap, bmap_i);
9921 isl_basic_map_list_free(list);
9922 return bmap;
9923 error:
9924 isl_basic_map_list_free(list);
9925 return NULL;
9928 /* Return the intersection of the elements in the non-empty list "list".
9929 * All elements are assumed to live in the same space.
9931 __isl_give isl_basic_set *isl_basic_set_list_intersect(
9932 __isl_take isl_basic_set_list *list)
9934 return isl_basic_map_list_intersect(list);
9937 /* Return the union of the elements of "list".
9938 * The list is required to have at least one element.
9940 __isl_give isl_set *isl_basic_set_list_union(
9941 __isl_take isl_basic_set_list *list)
9943 int i;
9944 isl_size n;
9945 isl_space *space;
9946 isl_basic_set *bset;
9947 isl_set *set;
9949 n = isl_basic_set_list_n_basic_set(list);
9950 if (n < 0)
9951 goto error;
9952 if (n < 1)
9953 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9954 "expecting non-empty list", goto error);
9956 bset = isl_basic_set_list_get_basic_set(list, 0);
9957 space = isl_basic_set_get_space(bset);
9958 isl_basic_set_free(bset);
9960 set = isl_set_alloc_space(space, n, 0);
9961 for (i = 0; i < n; ++i) {
9962 bset = isl_basic_set_list_get_basic_set(list, i);
9963 set = isl_set_add_basic_set(set, bset);
9966 isl_basic_set_list_free(list);
9967 return set;
9968 error:
9969 isl_basic_set_list_free(list);
9970 return NULL;
9973 /* Return the union of the elements in the non-empty list "list".
9974 * All elements are assumed to live in the same space.
9976 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9978 int i;
9979 isl_size n;
9980 isl_set *set;
9982 n = isl_set_list_n_set(list);
9983 if (n < 0)
9984 goto error;
9985 if (n < 1)
9986 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9987 "expecting non-empty list", goto error);
9989 set = isl_set_list_get_set(list, 0);
9990 for (i = 1; i < n; ++i) {
9991 isl_set *set_i;
9993 set_i = isl_set_list_get_set(list, i);
9994 set = isl_set_union(set, set_i);
9997 isl_set_list_free(list);
9998 return set;
9999 error:
10000 isl_set_list_free(list);
10001 return NULL;
10004 __isl_give isl_basic_map *isl_basic_map_product(
10005 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10007 isl_space *space_result = NULL;
10008 struct isl_basic_map *bmap;
10009 unsigned in1, in2, out1, out2, nparam, total, pos;
10010 struct isl_dim_map *dim_map1, *dim_map2;
10012 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10013 goto error;
10014 space_result = isl_space_product(isl_space_copy(bmap1->dim),
10015 isl_space_copy(bmap2->dim));
10017 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10018 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10019 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10020 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10021 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10023 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
10024 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10025 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10026 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10027 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10028 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10029 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10030 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10031 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10032 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10033 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10035 bmap = isl_basic_map_alloc_space(space_result,
10036 bmap1->n_div + bmap2->n_div,
10037 bmap1->n_eq + bmap2->n_eq,
10038 bmap1->n_ineq + bmap2->n_ineq);
10039 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10040 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10041 bmap = isl_basic_map_simplify(bmap);
10042 return isl_basic_map_finalize(bmap);
10043 error:
10044 isl_basic_map_free(bmap1);
10045 isl_basic_map_free(bmap2);
10046 return NULL;
10049 __isl_give isl_basic_map *isl_basic_map_flat_product(
10050 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10052 isl_basic_map *prod;
10054 prod = isl_basic_map_product(bmap1, bmap2);
10055 prod = isl_basic_map_flatten(prod);
10056 return prod;
10059 __isl_give isl_basic_set *isl_basic_set_flat_product(
10060 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10062 return isl_basic_map_flat_range_product(bset1, bset2);
10065 __isl_give isl_basic_map *isl_basic_map_domain_product(
10066 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10068 isl_space *space1, *space2;
10069 isl_space *space_result = NULL;
10070 isl_basic_map *bmap;
10071 isl_size in1, in2, out, nparam;
10072 unsigned total, pos;
10073 struct isl_dim_map *dim_map1, *dim_map2;
10075 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10076 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10077 out = isl_basic_map_dim(bmap1, isl_dim_out);
10078 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10079 if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
10080 goto error;
10082 space1 = isl_basic_map_get_space(bmap1);
10083 space2 = isl_basic_map_get_space(bmap2);
10084 space_result = isl_space_domain_product(space1, space2);
10086 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10087 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10088 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10089 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10090 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10091 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10092 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10093 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10094 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10095 isl_dim_map_div(dim_map1, bmap1, pos += out);
10096 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10098 bmap = isl_basic_map_alloc_space(space_result,
10099 bmap1->n_div + bmap2->n_div,
10100 bmap1->n_eq + bmap2->n_eq,
10101 bmap1->n_ineq + bmap2->n_ineq);
10102 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10103 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10104 bmap = isl_basic_map_simplify(bmap);
10105 return isl_basic_map_finalize(bmap);
10106 error:
10107 isl_basic_map_free(bmap1);
10108 isl_basic_map_free(bmap2);
10109 return NULL;
10112 __isl_give isl_basic_map *isl_basic_map_range_product(
10113 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10115 isl_bool rational;
10116 isl_space *space_result = NULL;
10117 isl_basic_map *bmap;
10118 isl_size in, out1, out2, nparam;
10119 unsigned total, pos;
10120 struct isl_dim_map *dim_map1, *dim_map2;
10122 rational = isl_basic_map_is_rational(bmap1);
10123 if (rational >= 0 && rational)
10124 rational = isl_basic_map_is_rational(bmap2);
10125 in = isl_basic_map_dim(bmap1, isl_dim_in);
10126 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10127 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10128 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10129 if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
10130 goto error;
10132 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10133 goto error;
10135 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10136 isl_space_copy(bmap2->dim));
10138 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10139 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10140 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10141 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10142 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10143 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10144 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10145 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10146 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10147 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10148 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10150 bmap = isl_basic_map_alloc_space(space_result,
10151 bmap1->n_div + bmap2->n_div,
10152 bmap1->n_eq + bmap2->n_eq,
10153 bmap1->n_ineq + bmap2->n_ineq);
10154 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10155 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10156 if (rational)
10157 bmap = isl_basic_map_set_rational(bmap);
10158 bmap = isl_basic_map_simplify(bmap);
10159 return isl_basic_map_finalize(bmap);
10160 error:
10161 isl_basic_map_free(bmap1);
10162 isl_basic_map_free(bmap2);
10163 return NULL;
10166 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10167 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10169 isl_basic_map *prod;
10171 prod = isl_basic_map_range_product(bmap1, bmap2);
10172 prod = isl_basic_map_flatten_range(prod);
10173 return prod;
10176 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10177 * and collect the results.
10178 * The result live in the space obtained by calling "space_product"
10179 * on the spaces of "map1" and "map2".
10180 * If "remove_duplicates" is set then the result may contain duplicates
10181 * (even if the inputs do not) and so we try and remove the obvious
10182 * duplicates.
10184 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10185 __isl_take isl_map *map2,
10186 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10187 __isl_take isl_space *right),
10188 __isl_give isl_basic_map *(*basic_map_product)(
10189 __isl_take isl_basic_map *left,
10190 __isl_take isl_basic_map *right),
10191 int remove_duplicates)
10193 unsigned flags = 0;
10194 struct isl_map *result;
10195 int i, j;
10196 isl_bool m;
10198 m = isl_map_has_equal_params(map1, map2);
10199 if (m < 0)
10200 goto error;
10201 if (!m)
10202 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10203 "parameters don't match", goto error);
10205 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10206 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10207 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10209 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10210 isl_space_copy(map2->dim)),
10211 map1->n * map2->n, flags);
10212 if (!result)
10213 goto error;
10214 for (i = 0; i < map1->n; ++i)
10215 for (j = 0; j < map2->n; ++j) {
10216 struct isl_basic_map *part;
10217 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10218 isl_basic_map_copy(map2->p[j]));
10219 if (isl_basic_map_is_empty(part))
10220 isl_basic_map_free(part);
10221 else
10222 result = isl_map_add_basic_map(result, part);
10223 if (!result)
10224 goto error;
10226 if (remove_duplicates)
10227 result = isl_map_remove_obvious_duplicates(result);
10228 isl_map_free(map1);
10229 isl_map_free(map2);
10230 return result;
10231 error:
10232 isl_map_free(map1);
10233 isl_map_free(map2);
10234 return NULL;
10237 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10239 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
10240 __isl_take isl_map *map2)
10242 return map_product(map1, map2, &isl_space_product,
10243 &isl_basic_map_product, 0);
10246 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10247 __isl_take isl_map *map2)
10249 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
10252 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10254 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10255 __isl_take isl_map *map2)
10257 isl_map *prod;
10259 prod = isl_map_product(map1, map2);
10260 prod = isl_map_flatten(prod);
10261 return prod;
10264 /* Given two set A and B, construct its Cartesian product A x B.
10266 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
10268 return isl_map_range_product(set1, set2);
10271 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10272 __isl_take isl_set *set2)
10274 return isl_map_flat_range_product(set1, set2);
10277 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10279 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
10280 __isl_take isl_map *map2)
10282 return map_product(map1, map2, &isl_space_domain_product,
10283 &isl_basic_map_domain_product, 1);
10286 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10288 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
10289 __isl_take isl_map *map2)
10291 return map_product(map1, map2, &isl_space_range_product,
10292 &isl_basic_map_range_product, 1);
10295 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10296 __isl_take isl_map *map2)
10298 return isl_map_align_params_map_map_and(map1, map2,
10299 &map_domain_product_aligned);
10302 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10303 __isl_take isl_map *map2)
10305 return isl_map_align_params_map_map_and(map1, map2,
10306 &map_range_product_aligned);
10309 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10311 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10313 isl_space *space;
10314 isl_size total1, keep1, total2, keep2;
10316 total1 = isl_map_dim(map, isl_dim_in);
10317 total2 = isl_map_dim(map, isl_dim_out);
10318 if (total1 < 0 || total2 < 0)
10319 return isl_map_free(map);
10320 if (!isl_space_domain_is_wrapping(map->dim) ||
10321 !isl_space_range_is_wrapping(map->dim))
10322 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10323 "not a product", return isl_map_free(map));
10325 space = isl_map_get_space(map);
10326 space = isl_space_factor_domain(space);
10327 keep1 = isl_space_dim(space, isl_dim_in);
10328 keep2 = isl_space_dim(space, isl_dim_out);
10329 if (keep1 < 0 || keep2 < 0)
10330 map = isl_map_free(map);
10331 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10332 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10333 map = isl_map_reset_space(map, space);
10335 return map;
10338 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10340 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10342 isl_space *space;
10343 isl_size total1, keep1, total2, keep2;
10345 total1 = isl_map_dim(map, isl_dim_in);
10346 total2 = isl_map_dim(map, isl_dim_out);
10347 if (total1 < 0 || total2 < 0)
10348 return isl_map_free(map);
10349 if (!isl_space_domain_is_wrapping(map->dim) ||
10350 !isl_space_range_is_wrapping(map->dim))
10351 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10352 "not a product", return isl_map_free(map));
10354 space = isl_map_get_space(map);
10355 space = isl_space_factor_range(space);
10356 keep1 = isl_space_dim(space, isl_dim_in);
10357 keep2 = isl_space_dim(space, isl_dim_out);
10358 if (keep1 < 0 || keep2 < 0)
10359 map = isl_map_free(map);
10360 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10361 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10362 map = isl_map_reset_space(map, space);
10364 return map;
10367 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10369 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10371 isl_space *space;
10372 isl_size total, keep;
10374 total = isl_map_dim(map, isl_dim_in);
10375 if (total < 0)
10376 return isl_map_free(map);
10377 if (!isl_space_domain_is_wrapping(map->dim))
10378 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10379 "domain is not a product", return isl_map_free(map));
10381 space = isl_map_get_space(map);
10382 space = isl_space_domain_factor_domain(space);
10383 keep = isl_space_dim(space, isl_dim_in);
10384 if (keep < 0)
10385 map = isl_map_free(map);
10386 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10387 map = isl_map_reset_space(map, space);
10389 return map;
10392 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10394 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10396 isl_space *space;
10397 isl_size total, keep;
10399 total = isl_map_dim(map, isl_dim_in);
10400 if (total < 0)
10401 return isl_map_free(map);
10402 if (!isl_space_domain_is_wrapping(map->dim))
10403 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10404 "domain is not a product", return isl_map_free(map));
10406 space = isl_map_get_space(map);
10407 space = isl_space_domain_factor_range(space);
10408 keep = isl_space_dim(space, isl_dim_in);
10409 if (keep < 0)
10410 map = isl_map_free(map);
10411 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10412 map = isl_map_reset_space(map, space);
10414 return map;
10417 /* Given a map A -> [B -> C], extract the map A -> B.
10419 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10421 isl_space *space;
10422 isl_size total, keep;
10424 total = isl_map_dim(map, isl_dim_out);
10425 if (total < 0)
10426 return isl_map_free(map);
10427 if (!isl_space_range_is_wrapping(map->dim))
10428 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10429 "range is not a product", return isl_map_free(map));
10431 space = isl_map_get_space(map);
10432 space = isl_space_range_factor_domain(space);
10433 keep = isl_space_dim(space, isl_dim_out);
10434 if (keep < 0)
10435 map = isl_map_free(map);
10436 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10437 map = isl_map_reset_space(map, space);
10439 return map;
10442 /* Given a map A -> [B -> C], extract the map A -> C.
10444 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10446 isl_space *space;
10447 isl_size total, keep;
10449 total = isl_map_dim(map, isl_dim_out);
10450 if (total < 0)
10451 return isl_map_free(map);
10452 if (!isl_space_range_is_wrapping(map->dim))
10453 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10454 "range is not a product", return isl_map_free(map));
10456 space = isl_map_get_space(map);
10457 space = isl_space_range_factor_range(space);
10458 keep = isl_space_dim(space, isl_dim_out);
10459 if (keep < 0)
10460 map = isl_map_free(map);
10461 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10462 map = isl_map_reset_space(map, space);
10464 return map;
10467 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10469 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10470 __isl_take isl_map *map2)
10472 isl_map *prod;
10474 prod = isl_map_domain_product(map1, map2);
10475 prod = isl_map_flatten_domain(prod);
10476 return prod;
10479 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10481 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10482 __isl_take isl_map *map2)
10484 isl_map *prod;
10486 prod = isl_map_range_product(map1, map2);
10487 prod = isl_map_flatten_range(prod);
10488 return prod;
10491 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10493 int i;
10494 uint32_t hash = isl_hash_init();
10495 isl_size total;
10497 if (!bmap)
10498 return 0;
10499 bmap = isl_basic_map_copy(bmap);
10500 bmap = isl_basic_map_normalize(bmap);
10501 total = isl_basic_map_dim(bmap, isl_dim_all);
10502 if (total < 0)
10503 return 0;
10504 isl_hash_byte(hash, bmap->n_eq & 0xFF);
10505 for (i = 0; i < bmap->n_eq; ++i) {
10506 uint32_t c_hash;
10507 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
10508 isl_hash_hash(hash, c_hash);
10510 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
10511 for (i = 0; i < bmap->n_ineq; ++i) {
10512 uint32_t c_hash;
10513 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
10514 isl_hash_hash(hash, c_hash);
10516 isl_hash_byte(hash, bmap->n_div & 0xFF);
10517 for (i = 0; i < bmap->n_div; ++i) {
10518 uint32_t c_hash;
10519 if (isl_int_is_zero(bmap->div[i][0]))
10520 continue;
10521 isl_hash_byte(hash, i & 0xFF);
10522 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
10523 isl_hash_hash(hash, c_hash);
10525 isl_basic_map_free(bmap);
10526 return hash;
10529 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
10531 return isl_basic_map_get_hash(bset_to_bmap(bset));
10534 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
10536 int i;
10537 uint32_t hash;
10539 if (!map)
10540 return 0;
10541 map = isl_map_copy(map);
10542 map = isl_map_normalize(map);
10543 if (!map)
10544 return 0;
10546 hash = isl_hash_init();
10547 for (i = 0; i < map->n; ++i) {
10548 uint32_t bmap_hash;
10549 bmap_hash = isl_basic_map_get_hash(map->p[i]);
10550 isl_hash_hash(hash, bmap_hash);
10553 isl_map_free(map);
10555 return hash;
10558 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
10560 return isl_map_get_hash(set_to_map(set));
10563 /* Return the number of basic maps in the (current) representation of "map".
10565 isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
10567 return map ? map->n : isl_size_error;
10570 isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
10572 return set ? set->n : isl_size_error;
10575 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
10576 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10578 int i;
10580 if (!map)
10581 return isl_stat_error;
10583 for (i = 0; i < map->n; ++i)
10584 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10585 return isl_stat_error;
10587 return isl_stat_ok;
10590 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10591 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10593 int i;
10595 if (!set)
10596 return isl_stat_error;
10598 for (i = 0; i < set->n; ++i)
10599 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10600 return isl_stat_error;
10602 return isl_stat_ok;
10605 /* Return a list of basic sets, the union of which is equal to "set".
10607 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10608 __isl_keep isl_set *set)
10610 int i;
10611 isl_basic_set_list *list;
10613 if (!set)
10614 return NULL;
10616 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10617 for (i = 0; i < set->n; ++i) {
10618 isl_basic_set *bset;
10620 bset = isl_basic_set_copy(set->p[i]);
10621 list = isl_basic_set_list_add(list, bset);
10624 return list;
10627 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10629 isl_space *space;
10631 if (!bset)
10632 return NULL;
10634 bset = isl_basic_set_cow(bset);
10635 if (!bset)
10636 return NULL;
10638 space = isl_basic_set_get_space(bset);
10639 space = isl_space_lift(space, bset->n_div);
10640 if (!space)
10641 goto error;
10642 isl_space_free(bset->dim);
10643 bset->dim = space;
10644 bset->extra -= bset->n_div;
10645 bset->n_div = 0;
10647 bset = isl_basic_set_finalize(bset);
10649 return bset;
10650 error:
10651 isl_basic_set_free(bset);
10652 return NULL;
10655 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10657 int i;
10658 isl_space *space;
10659 unsigned n_div;
10661 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10663 if (!set)
10664 return NULL;
10666 set = isl_set_cow(set);
10667 if (!set)
10668 return NULL;
10670 n_div = set->p[0]->n_div;
10671 space = isl_set_get_space(set);
10672 space = isl_space_lift(space, n_div);
10673 if (!space)
10674 goto error;
10675 isl_space_free(set->dim);
10676 set->dim = space;
10678 for (i = 0; i < set->n; ++i) {
10679 set->p[i] = isl_basic_set_lift(set->p[i]);
10680 if (!set->p[i])
10681 goto error;
10684 return set;
10685 error:
10686 isl_set_free(set);
10687 return NULL;
10690 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10692 isl_size dim;
10693 int size = 0;
10695 dim = isl_basic_set_dim(bset, isl_dim_all);
10696 if (dim < 0)
10697 return -1;
10698 size += bset->n_eq * (1 + dim);
10699 size += bset->n_ineq * (1 + dim);
10700 size += bset->n_div * (2 + dim);
10702 return size;
10705 int isl_set_size(__isl_keep isl_set *set)
10707 int i;
10708 int size = 0;
10710 if (!set)
10711 return -1;
10713 for (i = 0; i < set->n; ++i)
10714 size += isl_basic_set_size(set->p[i]);
10716 return size;
10719 /* Check if there is any lower bound (if lower == 0) and/or upper
10720 * bound (if upper == 0) on the specified dim.
10722 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10723 enum isl_dim_type type, unsigned pos, int lower, int upper)
10725 int i;
10727 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10728 return isl_bool_error;
10730 pos += isl_basic_map_offset(bmap, type);
10732 for (i = 0; i < bmap->n_div; ++i) {
10733 if (isl_int_is_zero(bmap->div[i][0]))
10734 continue;
10735 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10736 return isl_bool_true;
10739 for (i = 0; i < bmap->n_eq; ++i)
10740 if (!isl_int_is_zero(bmap->eq[i][pos]))
10741 return isl_bool_true;
10743 for (i = 0; i < bmap->n_ineq; ++i) {
10744 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10745 if (sgn > 0)
10746 lower = 1;
10747 if (sgn < 0)
10748 upper = 1;
10751 return lower && upper;
10754 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10755 enum isl_dim_type type, unsigned pos)
10757 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10760 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10761 enum isl_dim_type type, unsigned pos)
10763 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10766 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10767 enum isl_dim_type type, unsigned pos)
10769 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10772 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10773 enum isl_dim_type type, unsigned pos)
10775 int i;
10777 if (!map)
10778 return isl_bool_error;
10780 for (i = 0; i < map->n; ++i) {
10781 isl_bool bounded;
10782 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10783 if (bounded < 0 || !bounded)
10784 return bounded;
10787 return isl_bool_true;
10790 /* Return true if the specified dim is involved in both an upper bound
10791 * and a lower bound.
10793 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10794 enum isl_dim_type type, unsigned pos)
10796 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10799 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10801 static isl_bool has_any_bound(__isl_keep isl_map *map,
10802 enum isl_dim_type type, unsigned pos,
10803 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10804 enum isl_dim_type type, unsigned pos))
10806 int i;
10808 if (!map)
10809 return isl_bool_error;
10811 for (i = 0; i < map->n; ++i) {
10812 isl_bool bounded;
10813 bounded = fn(map->p[i], type, pos);
10814 if (bounded < 0 || bounded)
10815 return bounded;
10818 return isl_bool_false;
10821 /* Return 1 if the specified dim is involved in any lower bound.
10823 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10824 enum isl_dim_type type, unsigned pos)
10826 return has_any_bound(set, type, pos,
10827 &isl_basic_map_dim_has_lower_bound);
10830 /* Return 1 if the specified dim is involved in any upper bound.
10832 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10833 enum isl_dim_type type, unsigned pos)
10835 return has_any_bound(set, type, pos,
10836 &isl_basic_map_dim_has_upper_bound);
10839 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10841 static isl_bool has_bound(__isl_keep isl_map *map,
10842 enum isl_dim_type type, unsigned pos,
10843 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10844 enum isl_dim_type type, unsigned pos))
10846 int i;
10848 if (!map)
10849 return isl_bool_error;
10851 for (i = 0; i < map->n; ++i) {
10852 isl_bool bounded;
10853 bounded = fn(map->p[i], type, pos);
10854 if (bounded < 0 || !bounded)
10855 return bounded;
10858 return isl_bool_true;
10861 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10863 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10864 enum isl_dim_type type, unsigned pos)
10866 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10869 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10871 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10872 enum isl_dim_type type, unsigned pos)
10874 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10877 /* For each of the "n" variables starting at "first", determine
10878 * the sign of the variable and put the results in the first "n"
10879 * elements of the array "signs".
10880 * Sign
10881 * 1 means that the variable is non-negative
10882 * -1 means that the variable is non-positive
10883 * 0 means the variable attains both positive and negative values.
10885 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10886 unsigned first, unsigned n, int *signs)
10888 isl_vec *bound = NULL;
10889 struct isl_tab *tab = NULL;
10890 struct isl_tab_undo *snap;
10891 int i;
10892 isl_size total;
10894 total = isl_basic_set_dim(bset, isl_dim_all);
10895 if (total < 0 || !signs)
10896 return isl_stat_error;
10898 bound = isl_vec_alloc(bset->ctx, 1 + total);
10899 tab = isl_tab_from_basic_set(bset, 0);
10900 if (!bound || !tab)
10901 goto error;
10903 isl_seq_clr(bound->el, bound->size);
10904 isl_int_set_si(bound->el[0], -1);
10906 snap = isl_tab_snap(tab);
10907 for (i = 0; i < n; ++i) {
10908 int empty;
10910 isl_int_set_si(bound->el[1 + first + i], -1);
10911 if (isl_tab_add_ineq(tab, bound->el) < 0)
10912 goto error;
10913 empty = tab->empty;
10914 isl_int_set_si(bound->el[1 + first + i], 0);
10915 if (isl_tab_rollback(tab, snap) < 0)
10916 goto error;
10918 if (empty) {
10919 signs[i] = 1;
10920 continue;
10923 isl_int_set_si(bound->el[1 + first + i], 1);
10924 if (isl_tab_add_ineq(tab, bound->el) < 0)
10925 goto error;
10926 empty = tab->empty;
10927 isl_int_set_si(bound->el[1 + first + i], 0);
10928 if (isl_tab_rollback(tab, snap) < 0)
10929 goto error;
10931 signs[i] = empty ? -1 : 0;
10934 isl_tab_free(tab);
10935 isl_vec_free(bound);
10936 return isl_stat_ok;
10937 error:
10938 isl_tab_free(tab);
10939 isl_vec_free(bound);
10940 return isl_stat_error;
10943 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10944 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10946 if (!bset || !signs)
10947 return isl_stat_error;
10948 if (isl_basic_set_check_range(bset, type, first, n) < 0)
10949 return isl_stat_error;
10951 first += pos(bset->dim, type) - 1;
10952 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10955 /* Is it possible for the integer division "div" to depend (possibly
10956 * indirectly) on any output dimensions?
10958 * If the div is undefined, then we conservatively assume that it
10959 * may depend on them.
10960 * Otherwise, we check if it actually depends on them or on any integer
10961 * divisions that may depend on them.
10963 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10965 int i;
10966 isl_size n_out, n_div;
10967 unsigned o_out, o_div;
10969 if (isl_int_is_zero(bmap->div[div][0]))
10970 return isl_bool_true;
10972 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10973 if (n_out < 0)
10974 return isl_bool_error;
10975 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10977 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10978 return isl_bool_true;
10980 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10981 if (n_div < 0)
10982 return isl_bool_error;
10983 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10985 for (i = 0; i < n_div; ++i) {
10986 isl_bool may_involve;
10988 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10989 continue;
10990 may_involve = div_may_involve_output(bmap, i);
10991 if (may_involve < 0 || may_involve)
10992 return may_involve;
10995 return isl_bool_false;
10998 /* Return the first integer division of "bmap" in the range
10999 * [first, first + n[ that may depend on any output dimensions and
11000 * that has a non-zero coefficient in "c" (where the first coefficient
11001 * in "c" corresponds to integer division "first").
11003 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
11004 isl_int *c, int first, int n)
11006 int k;
11008 if (!bmap)
11009 return -1;
11011 for (k = first; k < first + n; ++k) {
11012 isl_bool may_involve;
11014 if (isl_int_is_zero(c[k]))
11015 continue;
11016 may_involve = div_may_involve_output(bmap, k);
11017 if (may_involve < 0)
11018 return -1;
11019 if (may_involve)
11020 return k;
11023 return first + n;
11026 /* Look for a pair of inequality constraints in "bmap" of the form
11028 * -l + i >= 0 or i >= l
11029 * and
11030 * n + l - i >= 0 or i <= l + n
11032 * with n < "m" and i the output dimension at position "pos".
11033 * (Note that n >= 0 as otherwise the two constraints would conflict.)
11034 * Furthermore, "l" is only allowed to involve parameters, input dimensions
11035 * and earlier output dimensions, as well as integer divisions that do
11036 * not involve any of the output dimensions.
11038 * Return the index of the first inequality constraint or bmap->n_ineq
11039 * if no such pair can be found.
11041 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
11042 int pos, isl_int m)
11044 int i, j;
11045 isl_ctx *ctx;
11046 isl_size total;
11047 isl_size n_div, n_out;
11048 unsigned o_div, o_out;
11049 int less;
11051 total = isl_basic_map_dim(bmap, isl_dim_all);
11052 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11053 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11054 if (total < 0 || n_out < 0 || n_div < 0)
11055 return -1;
11057 ctx = isl_basic_map_get_ctx(bmap);
11058 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11059 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11060 for (i = 0; i < bmap->n_ineq; ++i) {
11061 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
11062 continue;
11063 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
11064 n_out - (pos + 1)) != -1)
11065 continue;
11066 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11067 0, n_div) < n_div)
11068 continue;
11069 for (j = i + 1; j < bmap->n_ineq; ++j) {
11070 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11071 ctx->one))
11072 continue;
11073 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11074 bmap->ineq[j] + 1, total))
11075 continue;
11076 break;
11078 if (j >= bmap->n_ineq)
11079 continue;
11080 isl_int_add(bmap->ineq[i][0],
11081 bmap->ineq[i][0], bmap->ineq[j][0]);
11082 less = isl_int_abs_lt(bmap->ineq[i][0], m);
11083 isl_int_sub(bmap->ineq[i][0],
11084 bmap->ineq[i][0], bmap->ineq[j][0]);
11085 if (!less)
11086 continue;
11087 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11088 return i;
11089 else
11090 return j;
11093 return bmap->n_ineq;
11096 /* Return the index of the equality of "bmap" that defines
11097 * the output dimension "pos" in terms of earlier dimensions.
11098 * The equality may also involve integer divisions, as long
11099 * as those integer divisions are defined in terms of
11100 * parameters or input dimensions.
11101 * In this case, *div is set to the number of integer divisions and
11102 * *ineq is set to the number of inequality constraints (provided
11103 * div and ineq are not NULL).
11105 * The equality may also involve a single integer division involving
11106 * the output dimensions (typically only output dimension "pos") as
11107 * long as the coefficient of output dimension "pos" is 1 or -1 and
11108 * there is a pair of constraints i >= l and i <= l + n, with i referring
11109 * to output dimension "pos", l an expression involving only earlier
11110 * dimensions and n smaller than the coefficient of the integer division
11111 * in the equality. In this case, the output dimension can be defined
11112 * in terms of a modulo expression that does not involve the integer division.
11113 * *div is then set to this single integer division and
11114 * *ineq is set to the index of constraint i >= l.
11116 * Return bmap->n_eq if there is no such equality.
11117 * Return -1 on error.
11119 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11120 int pos, int *div, int *ineq)
11122 int j, k, l;
11123 isl_size n_div, n_out;
11124 unsigned o_div, o_out;
11126 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11127 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11128 if (n_out < 0 || n_div < 0)
11129 return -1;
11131 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11132 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11134 if (ineq)
11135 *ineq = bmap->n_ineq;
11136 if (div)
11137 *div = n_div;
11138 for (j = 0; j < bmap->n_eq; ++j) {
11139 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11140 continue;
11141 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11142 n_out - (pos + 1)) != -1)
11143 continue;
11144 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11145 0, n_div);
11146 if (k >= n_div)
11147 return j;
11148 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11149 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11150 continue;
11151 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11152 k + 1, n_div - (k+1)) < n_div)
11153 continue;
11154 l = find_modulo_constraint_pair(bmap, pos,
11155 bmap->eq[j][o_div + k]);
11156 if (l < 0)
11157 return -1;
11158 if (l >= bmap->n_ineq)
11159 continue;
11160 if (div)
11161 *div = k;
11162 if (ineq)
11163 *ineq = l;
11164 return j;
11167 return bmap->n_eq;
11170 /* Check if the given basic map is obviously single-valued.
11171 * In particular, for each output dimension, check that there is
11172 * an equality that defines the output dimension in terms of
11173 * earlier dimensions.
11175 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11177 int i;
11178 isl_size n_out;
11180 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11181 if (n_out < 0)
11182 return isl_bool_error;
11184 for (i = 0; i < n_out; ++i) {
11185 int eq;
11187 eq = isl_basic_map_output_defining_equality(bmap, i,
11188 NULL, NULL);
11189 if (eq < 0)
11190 return isl_bool_error;
11191 if (eq >= bmap->n_eq)
11192 return isl_bool_false;
11195 return isl_bool_true;
11198 /* Check if the given basic map is single-valued.
11199 * We simply compute
11201 * M \circ M^-1
11203 * and check if the result is a subset of the identity mapping.
11205 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11207 isl_space *space;
11208 isl_basic_map *test;
11209 isl_basic_map *id;
11210 isl_bool sv;
11212 sv = isl_basic_map_plain_is_single_valued(bmap);
11213 if (sv < 0 || sv)
11214 return sv;
11216 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11217 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11219 space = isl_basic_map_get_space(bmap);
11220 space = isl_space_map_from_set(isl_space_range(space));
11221 id = isl_basic_map_identity(space);
11223 sv = isl_basic_map_is_subset(test, id);
11225 isl_basic_map_free(test);
11226 isl_basic_map_free(id);
11228 return sv;
11231 /* Check if the given map is obviously single-valued.
11233 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11235 if (!map)
11236 return isl_bool_error;
11237 if (map->n == 0)
11238 return isl_bool_true;
11239 if (map->n >= 2)
11240 return isl_bool_false;
11242 return isl_basic_map_plain_is_single_valued(map->p[0]);
11245 /* Check if the given map is single-valued.
11246 * We simply compute
11248 * M \circ M^-1
11250 * and check if the result is a subset of the identity mapping.
11252 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11254 isl_space *dim;
11255 isl_map *test;
11256 isl_map *id;
11257 isl_bool sv;
11259 sv = isl_map_plain_is_single_valued(map);
11260 if (sv < 0 || sv)
11261 return sv;
11263 test = isl_map_reverse(isl_map_copy(map));
11264 test = isl_map_apply_range(test, isl_map_copy(map));
11266 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11267 id = isl_map_identity(dim);
11269 sv = isl_map_is_subset(test, id);
11271 isl_map_free(test);
11272 isl_map_free(id);
11274 return sv;
11277 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11279 isl_bool in;
11281 map = isl_map_copy(map);
11282 map = isl_map_reverse(map);
11283 in = isl_map_is_single_valued(map);
11284 isl_map_free(map);
11286 return in;
11289 /* Check if the given map is obviously injective.
11291 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11293 isl_bool in;
11295 map = isl_map_copy(map);
11296 map = isl_map_reverse(map);
11297 in = isl_map_plain_is_single_valued(map);
11298 isl_map_free(map);
11300 return in;
11303 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11305 isl_bool sv;
11307 sv = isl_map_is_single_valued(map);
11308 if (sv < 0 || !sv)
11309 return sv;
11311 return isl_map_is_injective(map);
11314 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11316 return isl_map_is_single_valued(set_to_map(set));
11319 /* Does "map" only map elements to themselves?
11321 * If the domain and range spaces are different, then "map"
11322 * is considered not to be an identity relation, even if it is empty.
11323 * Otherwise, construct the maximal identity relation and
11324 * check whether "map" is a subset of this relation.
11326 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11328 isl_space *space;
11329 isl_map *id;
11330 isl_bool equal, is_identity;
11332 space = isl_map_get_space(map);
11333 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
11334 isl_space_free(space);
11335 if (equal < 0 || !equal)
11336 return equal;
11338 id = isl_map_identity(isl_map_get_space(map));
11339 is_identity = isl_map_is_subset(map, id);
11340 isl_map_free(id);
11342 return is_identity;
11345 int isl_map_is_translation(__isl_keep isl_map *map)
11347 int ok;
11348 isl_set *delta;
11350 delta = isl_map_deltas(isl_map_copy(map));
11351 ok = isl_set_is_singleton(delta);
11352 isl_set_free(delta);
11354 return ok;
11357 static int unique(isl_int *p, unsigned pos, unsigned len)
11359 if (isl_seq_first_non_zero(p, pos) != -1)
11360 return 0;
11361 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11362 return 0;
11363 return 1;
11366 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11368 int i, j;
11369 isl_size nvar, n_div;
11370 unsigned ovar;
11372 n_div = isl_basic_set_dim(bset, isl_dim_div);
11373 if (n_div < 0)
11374 return isl_bool_error;
11375 if (n_div != 0)
11376 return isl_bool_false;
11378 nvar = isl_basic_set_dim(bset, isl_dim_set);
11379 if (nvar < 0)
11380 return isl_bool_error;
11381 ovar = isl_space_offset(bset->dim, isl_dim_set);
11382 for (j = 0; j < nvar; ++j) {
11383 int lower = 0, upper = 0;
11384 for (i = 0; i < bset->n_eq; ++i) {
11385 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11386 continue;
11387 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11388 return isl_bool_false;
11389 break;
11391 if (i < bset->n_eq)
11392 continue;
11393 for (i = 0; i < bset->n_ineq; ++i) {
11394 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11395 continue;
11396 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11397 return isl_bool_false;
11398 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11399 lower = 1;
11400 else
11401 upper = 1;
11403 if (!lower || !upper)
11404 return isl_bool_false;
11407 return isl_bool_true;
11410 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11412 if (!set)
11413 return isl_bool_error;
11414 if (set->n != 1)
11415 return isl_bool_false;
11417 return isl_basic_set_is_box(set->p[0]);
11420 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11422 if (!bset)
11423 return isl_bool_error;
11425 return isl_space_is_wrapping(bset->dim);
11428 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11430 if (!set)
11431 return isl_bool_error;
11433 return isl_space_is_wrapping(set->dim);
11436 /* Modify the space of "map" through a call to "change".
11437 * If "can_change" is set (not NULL), then first call it to check
11438 * if the modification is allowed, printing the error message "cannot_change"
11439 * if it is not.
11441 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11442 isl_bool (*can_change)(__isl_keep isl_map *map),
11443 const char *cannot_change,
11444 __isl_give isl_space *(*change)(__isl_take isl_space *space))
11446 isl_bool ok;
11447 isl_space *space;
11449 if (!map)
11450 return NULL;
11452 ok = can_change ? can_change(map) : isl_bool_true;
11453 if (ok < 0)
11454 return isl_map_free(map);
11455 if (!ok)
11456 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11457 return isl_map_free(map));
11459 space = change(isl_map_get_space(map));
11460 map = isl_map_reset_space(map, space);
11462 return map;
11465 /* Is the domain of "map" a wrapped relation?
11467 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11469 if (!map)
11470 return isl_bool_error;
11472 return isl_space_domain_is_wrapping(map->dim);
11475 /* Does "map" have a wrapped relation in both domain and range?
11477 isl_bool isl_map_is_product(__isl_keep isl_map *map)
11479 return isl_space_is_product(isl_map_peek_space(map));
11482 /* Is the range of "map" a wrapped relation?
11484 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
11486 if (!map)
11487 return isl_bool_error;
11489 return isl_space_range_is_wrapping(map->dim);
11492 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
11494 bmap = isl_basic_map_cow(bmap);
11495 if (!bmap)
11496 return NULL;
11498 bmap->dim = isl_space_wrap(bmap->dim);
11499 if (!bmap->dim)
11500 goto error;
11502 bmap = isl_basic_map_finalize(bmap);
11504 return bset_from_bmap(bmap);
11505 error:
11506 isl_basic_map_free(bmap);
11507 return NULL;
11510 /* Given a map A -> B, return the set (A -> B).
11512 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
11514 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
11517 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
11519 bset = isl_basic_set_cow(bset);
11520 if (!bset)
11521 return NULL;
11523 bset->dim = isl_space_unwrap(bset->dim);
11524 if (!bset->dim)
11525 goto error;
11527 bset = isl_basic_set_finalize(bset);
11529 return bset_to_bmap(bset);
11530 error:
11531 isl_basic_set_free(bset);
11532 return NULL;
11535 /* Given a set (A -> B), return the map A -> B.
11536 * Error out if "set" is not of the form (A -> B).
11538 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
11540 return isl_map_change_space(set, &isl_set_is_wrapping,
11541 "not a wrapping set", &isl_space_unwrap);
11544 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
11545 enum isl_dim_type type)
11547 if (!bmap)
11548 return NULL;
11550 if (!isl_space_is_named_or_nested(bmap->dim, type))
11551 return bmap;
11553 bmap = isl_basic_map_cow(bmap);
11554 if (!bmap)
11555 return NULL;
11557 bmap->dim = isl_space_reset(bmap->dim, type);
11558 if (!bmap->dim)
11559 goto error;
11561 bmap = isl_basic_map_finalize(bmap);
11563 return bmap;
11564 error:
11565 isl_basic_map_free(bmap);
11566 return NULL;
11569 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
11570 enum isl_dim_type type)
11572 int i;
11574 if (!map)
11575 return NULL;
11577 if (!isl_space_is_named_or_nested(map->dim, type))
11578 return map;
11580 map = isl_map_cow(map);
11581 if (!map)
11582 return NULL;
11584 for (i = 0; i < map->n; ++i) {
11585 map->p[i] = isl_basic_map_reset(map->p[i], type);
11586 if (!map->p[i])
11587 goto error;
11589 map->dim = isl_space_reset(map->dim, type);
11590 if (!map->dim)
11591 goto error;
11593 return map;
11594 error:
11595 isl_map_free(map);
11596 return NULL;
11599 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11601 if (!bmap)
11602 return NULL;
11604 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11605 return bmap;
11607 bmap = isl_basic_map_cow(bmap);
11608 if (!bmap)
11609 return NULL;
11611 bmap->dim = isl_space_flatten(bmap->dim);
11612 if (!bmap->dim)
11613 goto error;
11615 bmap = isl_basic_map_finalize(bmap);
11617 return bmap;
11618 error:
11619 isl_basic_map_free(bmap);
11620 return NULL;
11623 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11625 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11628 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11629 __isl_take isl_basic_map *bmap)
11631 if (!bmap)
11632 return NULL;
11634 if (!bmap->dim->nested[0])
11635 return bmap;
11637 bmap = isl_basic_map_cow(bmap);
11638 if (!bmap)
11639 return NULL;
11641 bmap->dim = isl_space_flatten_domain(bmap->dim);
11642 if (!bmap->dim)
11643 goto error;
11645 bmap = isl_basic_map_finalize(bmap);
11647 return bmap;
11648 error:
11649 isl_basic_map_free(bmap);
11650 return NULL;
11653 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11654 __isl_take isl_basic_map *bmap)
11656 if (!bmap)
11657 return NULL;
11659 if (!bmap->dim->nested[1])
11660 return bmap;
11662 bmap = isl_basic_map_cow(bmap);
11663 if (!bmap)
11664 return NULL;
11666 bmap->dim = isl_space_flatten_range(bmap->dim);
11667 if (!bmap->dim)
11668 goto error;
11670 bmap = isl_basic_map_finalize(bmap);
11672 return bmap;
11673 error:
11674 isl_basic_map_free(bmap);
11675 return NULL;
11678 /* Remove any internal structure from the spaces of domain and range of "map".
11680 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11682 if (!map)
11683 return NULL;
11685 if (!map->dim->nested[0] && !map->dim->nested[1])
11686 return map;
11688 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11691 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11693 return set_from_map(isl_map_flatten(set_to_map(set)));
11696 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11698 isl_space *space, *flat_space;
11699 isl_map *map;
11701 space = isl_set_get_space(set);
11702 flat_space = isl_space_flatten(isl_space_copy(space));
11703 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
11704 flat_space));
11705 map = isl_map_intersect_domain(map, set);
11707 return map;
11710 /* Remove any internal structure from the space of the domain of "map".
11712 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11714 if (!map)
11715 return NULL;
11717 if (!map->dim->nested[0])
11718 return map;
11720 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11723 /* Remove any internal structure from the space of the range of "map".
11725 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11727 if (!map)
11728 return NULL;
11730 if (!map->dim->nested[1])
11731 return map;
11733 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11736 /* Reorder the dimensions of "bmap" according to the given dim_map
11737 * and set the dimension specification to "space" and
11738 * perform Gaussian elimination on the result.
11740 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11741 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
11743 isl_basic_map *res;
11744 unsigned flags;
11745 isl_size n_div;
11747 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11748 if (n_div < 0 || !space || !dim_map)
11749 goto error;
11751 flags = bmap->flags;
11752 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11753 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
11754 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11755 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
11756 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11757 if (res)
11758 res->flags = flags;
11759 res = isl_basic_map_gauss(res, NULL);
11760 res = isl_basic_map_finalize(res);
11761 return res;
11762 error:
11763 isl_dim_map_free(dim_map);
11764 isl_basic_map_free(bmap);
11765 isl_space_free(space);
11766 return NULL;
11769 /* Reorder the dimensions of "map" according to given reordering.
11771 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11772 __isl_take isl_reordering *r)
11774 int i;
11775 struct isl_dim_map *dim_map;
11777 map = isl_map_cow(map);
11778 dim_map = isl_dim_map_from_reordering(r);
11779 if (!map || !r || !dim_map)
11780 goto error;
11782 for (i = 0; i < map->n; ++i) {
11783 struct isl_dim_map *dim_map_i;
11784 isl_space *space;
11786 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11788 space = isl_reordering_get_space(r);
11789 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
11791 if (!map->p[i])
11792 goto error;
11795 map = isl_map_reset_space(map, isl_reordering_get_space(r));
11796 map = isl_map_unmark_normalized(map);
11798 isl_reordering_free(r);
11799 isl_dim_map_free(dim_map);
11800 return map;
11801 error:
11802 isl_dim_map_free(dim_map);
11803 isl_map_free(map);
11804 isl_reordering_free(r);
11805 return NULL;
11808 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11809 __isl_take isl_reordering *r)
11811 return set_from_map(isl_map_realign(set_to_map(set), r));
11814 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11815 __isl_take isl_space *model)
11817 isl_ctx *ctx;
11818 isl_bool aligned;
11820 if (!map || !model)
11821 goto error;
11823 ctx = isl_space_get_ctx(model);
11824 if (!isl_space_has_named_params(model))
11825 isl_die(ctx, isl_error_invalid,
11826 "model has unnamed parameters", goto error);
11827 if (isl_map_check_named_params(map) < 0)
11828 goto error;
11829 aligned = isl_map_space_has_equal_params(map, model);
11830 if (aligned < 0)
11831 goto error;
11832 if (!aligned) {
11833 isl_reordering *exp;
11835 exp = isl_parameter_alignment_reordering(map->dim, model);
11836 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11837 map = isl_map_realign(map, exp);
11840 isl_space_free(model);
11841 return map;
11842 error:
11843 isl_space_free(model);
11844 isl_map_free(map);
11845 return NULL;
11848 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11849 __isl_take isl_space *model)
11851 return isl_map_align_params(set, model);
11854 /* Align the parameters of "bmap" to those of "model", introducing
11855 * additional parameters if needed.
11857 __isl_give isl_basic_map *isl_basic_map_align_params(
11858 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11860 isl_ctx *ctx;
11861 isl_bool equal_params;
11863 if (!bmap || !model)
11864 goto error;
11866 ctx = isl_space_get_ctx(model);
11867 if (!isl_space_has_named_params(model))
11868 isl_die(ctx, isl_error_invalid,
11869 "model has unnamed parameters", goto error);
11870 if (isl_basic_map_check_named_params(bmap) < 0)
11871 goto error;
11872 equal_params = isl_space_has_equal_params(bmap->dim, model);
11873 if (equal_params < 0)
11874 goto error;
11875 if (!equal_params) {
11876 isl_reordering *exp;
11877 struct isl_dim_map *dim_map;
11879 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11880 exp = isl_reordering_extend_space(exp,
11881 isl_basic_map_get_space(bmap));
11882 dim_map = isl_dim_map_from_reordering(exp);
11883 bmap = isl_basic_map_realign(bmap,
11884 isl_reordering_get_space(exp),
11885 isl_dim_map_extend(dim_map, bmap));
11886 isl_reordering_free(exp);
11887 isl_dim_map_free(dim_map);
11890 isl_space_free(model);
11891 return bmap;
11892 error:
11893 isl_space_free(model);
11894 isl_basic_map_free(bmap);
11895 return NULL;
11898 /* Do "bset" and "space" have the same parameters?
11900 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
11901 __isl_keep isl_space *space)
11903 isl_space *bset_space;
11905 bset_space = isl_basic_set_peek_space(bset);
11906 return isl_space_has_equal_params(bset_space, space);
11909 /* Do "map" and "space" have the same parameters?
11911 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
11912 __isl_keep isl_space *space)
11914 isl_space *map_space;
11916 map_space = isl_map_peek_space(map);
11917 return isl_space_has_equal_params(map_space, space);
11920 /* Do "set" and "space" have the same parameters?
11922 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
11923 __isl_keep isl_space *space)
11925 return isl_map_space_has_equal_params(set_to_map(set), space);
11928 /* Align the parameters of "bset" to those of "model", introducing
11929 * additional parameters if needed.
11931 __isl_give isl_basic_set *isl_basic_set_align_params(
11932 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11934 return isl_basic_map_align_params(bset, model);
11937 /* Drop all parameters not referenced by "map".
11939 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
11941 int i;
11942 isl_size n;
11944 n = isl_map_dim(map, isl_dim_param);
11945 if (isl_map_check_named_params(map) < 0 || n < 0)
11946 return isl_map_free(map);
11948 for (i = n - 1; i >= 0; i--) {
11949 isl_bool involves;
11951 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
11952 if (involves < 0)
11953 return isl_map_free(map);
11954 if (!involves)
11955 map = isl_map_project_out(map, isl_dim_param, i, 1);
11958 return map;
11961 /* Drop all parameters not referenced by "set".
11963 __isl_give isl_set *isl_set_drop_unused_params(
11964 __isl_take isl_set *set)
11966 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
11969 /* Drop all parameters not referenced by "bmap".
11971 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
11972 __isl_take isl_basic_map *bmap)
11974 isl_size nparam;
11975 int i;
11977 nparam = isl_basic_map_dim(bmap, isl_dim_param);
11978 if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)
11979 return isl_basic_map_free(bmap);
11981 for (i = nparam - 1; i >= 0; i--) {
11982 isl_bool involves;
11984 involves = isl_basic_map_involves_dims(bmap,
11985 isl_dim_param, i, 1);
11986 if (involves < 0)
11987 return isl_basic_map_free(bmap);
11988 if (!involves)
11989 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
11992 return bmap;
11995 /* Drop all parameters not referenced by "bset".
11997 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
11998 __isl_take isl_basic_set *bset)
12000 return bset_from_bmap(isl_basic_map_drop_unused_params(
12001 bset_to_bmap(bset)));
12004 /* Given a tuple of identifiers "tuple" in a space that corresponds
12005 * to that of "set", if any of those identifiers appear as parameters
12006 * in "set", then equate those parameters with the corresponding
12007 * set dimensions and project out the parameters.
12008 * The result therefore has no such parameters.
12010 static __isl_give isl_set *equate_params(__isl_take isl_set *set,
12011 __isl_keep isl_multi_id *tuple)
12013 int i;
12014 isl_size n;
12015 isl_space *set_space, *tuple_space;
12017 set_space = isl_set_peek_space(set);
12018 tuple_space = isl_multi_id_peek_space(tuple);
12019 if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
12020 return isl_set_free(set);
12021 n = isl_multi_id_size(tuple);
12022 if (n < 0)
12023 return isl_set_free(set);
12024 for (i = 0; i < n; ++i) {
12025 isl_id *id;
12026 int pos;
12028 id = isl_multi_id_get_at(tuple, i);
12029 if (!id)
12030 return isl_set_free(set);
12031 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
12032 isl_id_free(id);
12033 if (pos < 0)
12034 continue;
12035 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
12036 set = isl_set_project_out(set, isl_dim_param, pos, 1);
12038 return set;
12041 /* Bind the set dimensions of "set" to parameters with identifiers
12042 * specified by "tuple", living in the same space as "set".
12044 * If no parameters with these identifiers appear in "set" already,
12045 * then the set dimensions are simply reinterpreted as parameters.
12046 * Otherwise, the parameters are first equated to the corresponding
12047 * set dimensions.
12049 __isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
12050 __isl_take isl_multi_id *tuple)
12052 isl_space *space;
12054 set = equate_params(set, tuple);
12055 space = isl_set_get_space(set);
12056 space = isl_space_bind_set(space, tuple);
12057 isl_multi_id_free(tuple);
12058 set = isl_set_reset_space(set, space);
12060 return set;
12063 /* Given a tuple of identifiers "tuple" in a space that corresponds
12064 * to the domain of "map", if any of those identifiers appear as parameters
12065 * in "map", then equate those parameters with the corresponding
12066 * input dimensions and project out the parameters.
12067 * The result therefore has no such parameters.
12069 static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
12070 __isl_keep isl_multi_id *tuple)
12072 int i;
12073 isl_size n;
12074 isl_space *map_space, *tuple_space;
12076 map_space = isl_map_peek_space(map);
12077 tuple_space = isl_multi_id_peek_space(tuple);
12078 if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
12079 return isl_map_free(map);
12080 n = isl_multi_id_size(tuple);
12081 if (n < 0)
12082 return isl_map_free(map);
12083 for (i = 0; i < n; ++i) {
12084 isl_id *id;
12085 int pos;
12087 id = isl_multi_id_get_at(tuple, i);
12088 if (!id)
12089 return isl_map_free(map);
12090 pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
12091 isl_id_free(id);
12092 if (pos < 0)
12093 continue;
12094 map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
12095 map = isl_map_project_out(map, isl_dim_param, pos, 1);
12097 return map;
12100 /* Bind the input dimensions of "map" to parameters with identifiers
12101 * specified by "tuple", living in the domain space of "map".
12103 * If no parameters with these identifiers appear in "map" already,
12104 * then the input dimensions are simply reinterpreted as parameters.
12105 * Otherwise, the parameters are first equated to the corresponding
12106 * input dimensions.
12108 __isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
12109 __isl_take isl_multi_id *tuple)
12111 isl_space *space;
12112 isl_set *set;
12114 map = map_equate_params(map, tuple);
12115 space = isl_map_get_space(map);
12116 space = isl_space_bind_map_domain(space, tuple);
12117 isl_multi_id_free(tuple);
12118 set = set_from_map(isl_map_reset_space(map, space));
12120 return set;
12123 /* Bind the output dimensions of "map" to parameters with identifiers
12124 * specified by "tuple", living in the range space of "map".
12126 * Since binding is more easily implemented on the domain,
12127 * bind the input dimensions of the inverse of "map".
12129 __isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
12130 __isl_take isl_multi_id *tuple)
12132 return isl_map_bind_domain(isl_map_reverse(map), tuple);
12135 /* Insert a domain corresponding to "tuple"
12136 * into the nullary or unary relation "set".
12137 * The result has an extra initial tuple and is therefore
12138 * either a unary or binary relation.
12139 * Any parameters with identifiers in "tuple" are reinterpreted
12140 * as the corresponding domain dimensions.
12142 static __isl_give isl_map *unbind_params_insert_domain(
12143 __isl_take isl_set *set, __isl_take isl_multi_id *tuple)
12145 isl_space *space;
12146 isl_reordering *r;
12148 space = isl_set_peek_space(set);
12149 r = isl_reordering_unbind_params_insert_domain(space, tuple);
12150 isl_multi_id_free(tuple);
12152 return isl_map_realign(set_to_map(set), r);
12155 /* Construct a set with "tuple" as domain from the parameter domain "set".
12156 * Any parameters with identifiers in "tuple" are reinterpreted
12157 * as the corresponding set dimensions.
12159 __isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
12160 __isl_take isl_multi_id *tuple)
12162 isl_bool is_params;
12164 is_params = isl_set_is_params(set);
12165 if (is_params < 0)
12166 set = isl_set_free(set);
12167 else if (!is_params)
12168 isl_die(isl_set_get_ctx(set), isl_error_invalid,
12169 "expecting parameter domain", set = isl_set_free(set));
12170 return set_from_map(unbind_params_insert_domain(set, tuple));
12173 /* Construct a map with "domain" as domain and "set" as range.
12174 * Any parameters with identifiers in "domain" are reinterpreted
12175 * as the corresponding domain dimensions.
12177 __isl_give isl_map *isl_set_unbind_params_insert_domain(
12178 __isl_take isl_set *set, __isl_take isl_multi_id *domain)
12180 isl_bool is_params;
12182 is_params = isl_set_is_params(set);
12183 if (is_params < 0)
12184 set = isl_set_free(set);
12185 else if (is_params)
12186 isl_die(isl_set_get_ctx(set), isl_error_invalid,
12187 "expecting proper set", set = isl_set_free(set));
12188 return unbind_params_insert_domain(set, domain);
12191 __isl_give isl_mat *isl_basic_map_equalities_matrix(
12192 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12193 enum isl_dim_type c2, enum isl_dim_type c3,
12194 enum isl_dim_type c4, enum isl_dim_type c5)
12196 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12197 struct isl_mat *mat;
12198 int i, j, k;
12199 int pos;
12200 isl_size total;
12202 total = isl_basic_map_dim(bmap, isl_dim_all);
12203 if (total < 0)
12204 return NULL;
12205 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
12206 if (!mat)
12207 return NULL;
12208 for (i = 0; i < bmap->n_eq; ++i)
12209 for (j = 0, pos = 0; j < 5; ++j) {
12210 int off = isl_basic_map_offset(bmap, c[j]);
12211 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12212 if (dim < 0)
12213 return isl_mat_free(mat);
12214 for (k = 0; k < dim; ++k) {
12215 isl_int_set(mat->row[i][pos],
12216 bmap->eq[i][off + k]);
12217 ++pos;
12221 return mat;
12224 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
12225 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12226 enum isl_dim_type c2, enum isl_dim_type c3,
12227 enum isl_dim_type c4, enum isl_dim_type c5)
12229 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12230 struct isl_mat *mat;
12231 int i, j, k;
12232 int pos;
12233 isl_size total;
12235 total = isl_basic_map_dim(bmap, isl_dim_all);
12236 if (total < 0)
12237 return NULL;
12238 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
12239 if (!mat)
12240 return NULL;
12241 for (i = 0; i < bmap->n_ineq; ++i)
12242 for (j = 0, pos = 0; j < 5; ++j) {
12243 int off = isl_basic_map_offset(bmap, c[j]);
12244 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12245 if (dim < 0)
12246 return isl_mat_free(mat);
12247 for (k = 0; k < dim; ++k) {
12248 isl_int_set(mat->row[i][pos],
12249 bmap->ineq[i][off + k]);
12250 ++pos;
12254 return mat;
12257 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
12258 __isl_take isl_space *space,
12259 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12260 enum isl_dim_type c2, enum isl_dim_type c3,
12261 enum isl_dim_type c4, enum isl_dim_type c5)
12263 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12264 isl_basic_map *bmap = NULL;
12265 isl_size dim;
12266 unsigned total;
12267 unsigned extra;
12268 int i, j, k, l;
12269 int pos;
12271 dim = isl_space_dim(space, isl_dim_all);
12272 if (dim < 0 || !eq || !ineq)
12273 goto error;
12275 if (eq->n_col != ineq->n_col)
12276 isl_die(space->ctx, isl_error_invalid,
12277 "equalities and inequalities matrices should have "
12278 "same number of columns", goto error);
12280 total = 1 + dim;
12282 if (eq->n_col < total)
12283 isl_die(space->ctx, isl_error_invalid,
12284 "number of columns too small", goto error);
12286 extra = eq->n_col - total;
12288 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
12289 eq->n_row, ineq->n_row);
12290 if (!bmap)
12291 goto error;
12292 for (i = 0; i < extra; ++i) {
12293 k = isl_basic_map_alloc_div(bmap);
12294 if (k < 0)
12295 goto error;
12296 isl_int_set_si(bmap->div[k][0], 0);
12298 for (i = 0; i < eq->n_row; ++i) {
12299 l = isl_basic_map_alloc_equality(bmap);
12300 if (l < 0)
12301 goto error;
12302 for (j = 0, pos = 0; j < 5; ++j) {
12303 int off = isl_basic_map_offset(bmap, c[j]);
12304 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12305 if (dim < 0)
12306 goto error;
12307 for (k = 0; k < dim; ++k) {
12308 isl_int_set(bmap->eq[l][off + k],
12309 eq->row[i][pos]);
12310 ++pos;
12314 for (i = 0; i < ineq->n_row; ++i) {
12315 l = isl_basic_map_alloc_inequality(bmap);
12316 if (l < 0)
12317 goto error;
12318 for (j = 0, pos = 0; j < 5; ++j) {
12319 int off = isl_basic_map_offset(bmap, c[j]);
12320 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12321 if (dim < 0)
12322 goto error;
12323 for (k = 0; k < dim; ++k) {
12324 isl_int_set(bmap->ineq[l][off + k],
12325 ineq->row[i][pos]);
12326 ++pos;
12331 isl_space_free(space);
12332 isl_mat_free(eq);
12333 isl_mat_free(ineq);
12335 bmap = isl_basic_map_simplify(bmap);
12336 return isl_basic_map_finalize(bmap);
12337 error:
12338 isl_space_free(space);
12339 isl_mat_free(eq);
12340 isl_mat_free(ineq);
12341 isl_basic_map_free(bmap);
12342 return NULL;
12345 __isl_give isl_mat *isl_basic_set_equalities_matrix(
12346 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12347 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12349 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12350 c1, c2, c3, c4, isl_dim_in);
12353 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12354 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12355 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12357 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12358 c1, c2, c3, c4, isl_dim_in);
12361 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12362 __isl_take isl_space *dim,
12363 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12364 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12366 isl_basic_map *bmap;
12367 bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
12368 c1, c2, c3, c4, isl_dim_in);
12369 return bset_from_bmap(bmap);
12372 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12374 if (!bmap)
12375 return isl_bool_error;
12377 return isl_space_can_zip(bmap->dim);
12380 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12382 if (!map)
12383 return isl_bool_error;
12385 return isl_space_can_zip(map->dim);
12388 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12389 * (A -> C) -> (B -> D).
12391 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12393 unsigned pos;
12394 isl_size n_in;
12395 isl_size n1;
12396 isl_size n2;
12398 if (!bmap)
12399 return NULL;
12401 if (!isl_basic_map_can_zip(bmap))
12402 isl_die(bmap->ctx, isl_error_invalid,
12403 "basic map cannot be zipped", goto error);
12404 n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12405 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12406 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12407 if (n_in < 0 || n1 < 0 || n2 < 0)
12408 return isl_basic_map_free(bmap);
12409 pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
12410 bmap = isl_basic_map_cow(bmap);
12411 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12412 if (!bmap)
12413 return NULL;
12414 bmap->dim = isl_space_zip(bmap->dim);
12415 if (!bmap->dim)
12416 goto error;
12417 bmap = isl_basic_map_mark_final(bmap);
12418 return bmap;
12419 error:
12420 isl_basic_map_free(bmap);
12421 return NULL;
12424 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12425 * (A -> C) -> (B -> D).
12427 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12429 int i;
12431 if (!map)
12432 return NULL;
12434 if (!isl_map_can_zip(map))
12435 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12436 goto error);
12438 map = isl_map_cow(map);
12439 if (!map)
12440 return NULL;
12442 for (i = 0; i < map->n; ++i) {
12443 map->p[i] = isl_basic_map_zip(map->p[i]);
12444 if (!map->p[i])
12445 goto error;
12448 map->dim = isl_space_zip(map->dim);
12449 if (!map->dim)
12450 goto error;
12452 return map;
12453 error:
12454 isl_map_free(map);
12455 return NULL;
12458 /* Can we apply isl_basic_map_curry to "bmap"?
12459 * That is, does it have a nested relation in its domain?
12461 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12463 if (!bmap)
12464 return isl_bool_error;
12466 return isl_space_can_curry(bmap->dim);
12469 /* Can we apply isl_map_curry to "map"?
12470 * That is, does it have a nested relation in its domain?
12472 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12474 if (!map)
12475 return isl_bool_error;
12477 return isl_space_can_curry(map->dim);
12480 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12481 * A -> (B -> C).
12483 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12486 if (!bmap)
12487 return NULL;
12489 if (!isl_basic_map_can_curry(bmap))
12490 isl_die(bmap->ctx, isl_error_invalid,
12491 "basic map cannot be curried", goto error);
12492 bmap = isl_basic_map_cow(bmap);
12493 if (!bmap)
12494 return NULL;
12495 bmap->dim = isl_space_curry(bmap->dim);
12496 if (!bmap->dim)
12497 goto error;
12498 bmap = isl_basic_map_mark_final(bmap);
12499 return bmap;
12500 error:
12501 isl_basic_map_free(bmap);
12502 return NULL;
12505 /* Given a map (A -> B) -> C, return the corresponding map
12506 * A -> (B -> C).
12508 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
12510 return isl_map_change_space(map, &isl_map_can_curry,
12511 "map cannot be curried", &isl_space_curry);
12514 /* Can isl_map_range_curry be applied to "map"?
12515 * That is, does it have a nested relation in its range,
12516 * the domain of which is itself a nested relation?
12518 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
12520 if (!map)
12521 return isl_bool_error;
12523 return isl_space_can_range_curry(map->dim);
12526 /* Given a map A -> ((B -> C) -> D), return the corresponding map
12527 * A -> (B -> (C -> D)).
12529 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
12531 return isl_map_change_space(map, &isl_map_can_range_curry,
12532 "map range cannot be curried",
12533 &isl_space_range_curry);
12536 /* Can we apply isl_basic_map_uncurry to "bmap"?
12537 * That is, does it have a nested relation in its domain?
12539 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
12541 if (!bmap)
12542 return isl_bool_error;
12544 return isl_space_can_uncurry(bmap->dim);
12547 /* Can we apply isl_map_uncurry to "map"?
12548 * That is, does it have a nested relation in its domain?
12550 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
12552 if (!map)
12553 return isl_bool_error;
12555 return isl_space_can_uncurry(map->dim);
12558 /* Given a basic map A -> (B -> C), return the corresponding basic map
12559 * (A -> B) -> C.
12561 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
12564 if (!bmap)
12565 return NULL;
12567 if (!isl_basic_map_can_uncurry(bmap))
12568 isl_die(bmap->ctx, isl_error_invalid,
12569 "basic map cannot be uncurried",
12570 return isl_basic_map_free(bmap));
12571 bmap = isl_basic_map_cow(bmap);
12572 if (!bmap)
12573 return NULL;
12574 bmap->dim = isl_space_uncurry(bmap->dim);
12575 if (!bmap->dim)
12576 return isl_basic_map_free(bmap);
12577 bmap = isl_basic_map_mark_final(bmap);
12578 return bmap;
12581 /* Given a map A -> (B -> C), return the corresponding map
12582 * (A -> B) -> C.
12584 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
12586 return isl_map_change_space(map, &isl_map_can_uncurry,
12587 "map cannot be uncurried", &isl_space_uncurry);
12590 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
12591 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12593 return isl_map_equate(set, type1, pos1, type2, pos2);
12596 /* Construct a basic map where the given dimensions are equal to each other.
12598 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
12599 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12601 isl_basic_map *bmap = NULL;
12602 int i;
12603 isl_size total;
12605 total = isl_space_dim(space, isl_dim_all);
12606 if (total < 0 ||
12607 isl_space_check_range(space, type1, pos1, 1) < 0 ||
12608 isl_space_check_range(space, type2, pos2, 1) < 0)
12609 goto error;
12611 if (type1 == type2 && pos1 == pos2)
12612 return isl_basic_map_universe(space);
12614 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
12615 i = isl_basic_map_alloc_equality(bmap);
12616 if (i < 0)
12617 goto error;
12618 isl_seq_clr(bmap->eq[i], 1 + total);
12619 pos1 += isl_basic_map_offset(bmap, type1);
12620 pos2 += isl_basic_map_offset(bmap, type2);
12621 isl_int_set_si(bmap->eq[i][pos1], -1);
12622 isl_int_set_si(bmap->eq[i][pos2], 1);
12623 bmap = isl_basic_map_finalize(bmap);
12624 isl_space_free(space);
12625 return bmap;
12626 error:
12627 isl_space_free(space);
12628 isl_basic_map_free(bmap);
12629 return NULL;
12632 /* Add a constraint imposing that the given two dimensions are equal.
12634 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
12635 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12637 isl_basic_map *eq;
12639 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12641 bmap = isl_basic_map_intersect(bmap, eq);
12643 return bmap;
12646 /* Add a constraint imposing that the given two dimensions are equal.
12648 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
12649 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12651 isl_basic_map *bmap;
12653 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
12655 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12657 return map;
12660 /* Add a constraint imposing that the given two dimensions have opposite values.
12662 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
12663 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12665 isl_basic_map *bmap = NULL;
12666 int i;
12667 isl_size total;
12669 if (isl_map_check_range(map, type1, pos1, 1) < 0)
12670 return isl_map_free(map);
12671 if (isl_map_check_range(map, type2, pos2, 1) < 0)
12672 return isl_map_free(map);
12674 total = isl_map_dim(map, isl_dim_all);
12675 if (total < 0)
12676 return isl_map_free(map);
12677 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
12678 i = isl_basic_map_alloc_equality(bmap);
12679 if (i < 0)
12680 goto error;
12681 isl_seq_clr(bmap->eq[i], 1 + total);
12682 pos1 += isl_basic_map_offset(bmap, type1);
12683 pos2 += isl_basic_map_offset(bmap, type2);
12684 isl_int_set_si(bmap->eq[i][pos1], 1);
12685 isl_int_set_si(bmap->eq[i][pos2], 1);
12686 bmap = isl_basic_map_finalize(bmap);
12688 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12690 return map;
12691 error:
12692 isl_basic_map_free(bmap);
12693 isl_map_free(map);
12694 return NULL;
12697 /* Construct a constraint imposing that the value of the first dimension is
12698 * greater than or equal to that of the second.
12700 static __isl_give isl_constraint *constraint_order_ge(
12701 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
12702 enum isl_dim_type type2, int pos2)
12704 isl_constraint *c;
12706 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12707 isl_space_check_range(space, type2, pos2, 1) < 0)
12708 space = isl_space_free(space);
12709 if (!space)
12710 return NULL;
12712 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
12714 if (type1 == type2 && pos1 == pos2)
12715 return c;
12717 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
12718 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
12720 return c;
12723 /* Add a constraint imposing that the value of the first dimension is
12724 * greater than or equal to that of the second.
12726 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
12727 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12729 isl_constraint *c;
12730 isl_space *space;
12732 if (type1 == type2 && pos1 == pos2)
12733 return bmap;
12734 space = isl_basic_map_get_space(bmap);
12735 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12736 bmap = isl_basic_map_add_constraint(bmap, c);
12738 return bmap;
12741 /* Add a constraint imposing that the value of the first dimension is
12742 * greater than or equal to that of the second.
12744 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12745 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12747 isl_constraint *c;
12748 isl_space *space;
12750 if (type1 == type2 && pos1 == pos2)
12751 return map;
12752 space = isl_map_get_space(map);
12753 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12754 map = isl_map_add_constraint(map, c);
12756 return map;
12759 /* Add a constraint imposing that the value of the first dimension is
12760 * less than or equal to that of the second.
12762 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12763 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12765 return isl_map_order_ge(map, type2, pos2, type1, pos1);
12768 /* Construct a basic map where the value of the first dimension is
12769 * greater than that of the second.
12771 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12772 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12774 isl_basic_map *bmap = NULL;
12775 int i;
12776 isl_size total;
12778 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12779 isl_space_check_range(space, type2, pos2, 1) < 0)
12780 goto error;
12782 if (type1 == type2 && pos1 == pos2)
12783 return isl_basic_map_empty(space);
12785 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12786 total = isl_basic_map_dim(bmap, isl_dim_all);
12787 i = isl_basic_map_alloc_inequality(bmap);
12788 if (total < 0 || i < 0)
12789 return isl_basic_map_free(bmap);
12790 isl_seq_clr(bmap->ineq[i], 1 + total);
12791 pos1 += isl_basic_map_offset(bmap, type1);
12792 pos2 += isl_basic_map_offset(bmap, type2);
12793 isl_int_set_si(bmap->ineq[i][pos1], 1);
12794 isl_int_set_si(bmap->ineq[i][pos2], -1);
12795 isl_int_set_si(bmap->ineq[i][0], -1);
12796 bmap = isl_basic_map_finalize(bmap);
12798 return bmap;
12799 error:
12800 isl_space_free(space);
12801 isl_basic_map_free(bmap);
12802 return NULL;
12805 /* Add a constraint imposing that the value of the first dimension is
12806 * greater than that of the second.
12808 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12809 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12811 isl_basic_map *gt;
12813 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12815 bmap = isl_basic_map_intersect(bmap, gt);
12817 return bmap;
12820 /* Add a constraint imposing that the value of the first dimension is
12821 * greater than that of the second.
12823 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12824 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12826 isl_basic_map *bmap;
12828 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12830 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12832 return map;
12835 /* Add a constraint imposing that the value of the first dimension is
12836 * smaller than that of the second.
12838 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12839 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12841 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12844 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12845 int pos)
12847 isl_aff *div;
12848 isl_local_space *ls;
12850 if (!bmap)
12851 return NULL;
12853 if (!isl_basic_map_divs_known(bmap))
12854 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12855 "some divs are unknown", return NULL);
12857 ls = isl_basic_map_get_local_space(bmap);
12858 div = isl_local_space_get_div(ls, pos);
12859 isl_local_space_free(ls);
12861 return div;
12864 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12865 int pos)
12867 return isl_basic_map_get_div(bset, pos);
12870 /* Plug in "subs" for dimension "type", "pos" of "bset".
12872 * Let i be the dimension to replace and let "subs" be of the form
12874 * f/d
12876 * Any integer division with a non-zero coefficient for i,
12878 * floor((a i + g)/m)
12880 * is replaced by
12882 * floor((a f + d g)/(m d))
12884 * Constraints of the form
12886 * a i + g
12888 * are replaced by
12890 * a f + d g
12892 * We currently require that "subs" is an integral expression.
12893 * Handling rational expressions may require us to add stride constraints
12894 * as we do in isl_basic_set_preimage_multi_aff.
12896 __isl_give isl_basic_set *isl_basic_set_substitute(
12897 __isl_take isl_basic_set *bset,
12898 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12900 int i;
12901 isl_int v;
12902 isl_ctx *ctx;
12903 isl_size n_div;
12905 if (bset && isl_basic_set_plain_is_empty(bset))
12906 return bset;
12908 bset = isl_basic_set_cow(bset);
12909 if (!bset || !subs)
12910 goto error;
12912 ctx = isl_basic_set_get_ctx(bset);
12913 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12914 isl_die(ctx, isl_error_invalid,
12915 "spaces don't match", goto error);
12916 n_div = isl_local_space_dim(subs->ls, isl_dim_div);
12917 if (n_div < 0)
12918 goto error;
12919 if (n_div != 0)
12920 isl_die(ctx, isl_error_unsupported,
12921 "cannot handle divs yet", goto error);
12922 if (!isl_int_is_one(subs->v->el[0]))
12923 isl_die(ctx, isl_error_invalid,
12924 "can only substitute integer expressions", goto error);
12926 pos += isl_basic_set_offset(bset, type);
12928 isl_int_init(v);
12930 for (i = 0; i < bset->n_eq; ++i) {
12931 if (isl_int_is_zero(bset->eq[i][pos]))
12932 continue;
12933 isl_int_set(v, bset->eq[i][pos]);
12934 isl_int_set_si(bset->eq[i][pos], 0);
12935 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12936 v, subs->v->el + 1, subs->v->size - 1);
12939 for (i = 0; i < bset->n_ineq; ++i) {
12940 if (isl_int_is_zero(bset->ineq[i][pos]))
12941 continue;
12942 isl_int_set(v, bset->ineq[i][pos]);
12943 isl_int_set_si(bset->ineq[i][pos], 0);
12944 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12945 v, subs->v->el + 1, subs->v->size - 1);
12948 for (i = 0; i < bset->n_div; ++i) {
12949 if (isl_int_is_zero(bset->div[i][1 + pos]))
12950 continue;
12951 isl_int_set(v, bset->div[i][1 + pos]);
12952 isl_int_set_si(bset->div[i][1 + pos], 0);
12953 isl_seq_combine(bset->div[i] + 1,
12954 subs->v->el[0], bset->div[i] + 1,
12955 v, subs->v->el + 1, subs->v->size - 1);
12956 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12959 isl_int_clear(v);
12961 bset = isl_basic_set_simplify(bset);
12962 return isl_basic_set_finalize(bset);
12963 error:
12964 isl_basic_set_free(bset);
12965 return NULL;
12968 /* Plug in "subs" for dimension "type", "pos" of "set".
12970 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12971 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12973 int i;
12975 if (set && isl_set_plain_is_empty(set))
12976 return set;
12978 set = isl_set_cow(set);
12979 if (!set || !subs)
12980 goto error;
12982 for (i = set->n - 1; i >= 0; --i) {
12983 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12984 set = set_from_map(remove_if_empty(set_to_map(set), i));
12985 if (!set)
12986 return NULL;
12989 return set;
12990 error:
12991 isl_set_free(set);
12992 return NULL;
12995 /* Check if the range of "ma" is compatible with the domain or range
12996 * (depending on "type") of "bmap".
12998 static isl_stat check_basic_map_compatible_range_multi_aff(
12999 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
13000 __isl_keep isl_multi_aff *ma)
13002 isl_bool m;
13003 isl_space *ma_space;
13005 ma_space = isl_multi_aff_get_space(ma);
13007 m = isl_space_has_equal_params(bmap->dim, ma_space);
13008 if (m < 0)
13009 goto error;
13010 if (!m)
13011 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13012 "parameters don't match", goto error);
13013 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
13014 if (m < 0)
13015 goto error;
13016 if (!m)
13017 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13018 "spaces don't match", goto error);
13020 isl_space_free(ma_space);
13021 return isl_stat_ok;
13022 error:
13023 isl_space_free(ma_space);
13024 return isl_stat_error;
13027 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
13028 * coefficients before the transformed range of dimensions,
13029 * the "n_after" coefficients after the transformed range of dimensions
13030 * and the coefficients of the other divs in "bmap".
13032 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
13033 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
13035 int i;
13036 isl_size n_param;
13037 isl_size n_set;
13038 isl_local_space *ls;
13040 if (n_div == 0)
13041 return bmap;
13043 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
13044 n_param = isl_local_space_dim(ls, isl_dim_param);
13045 n_set = isl_local_space_dim(ls, isl_dim_set);
13046 if (n_param < 0 || n_set < 0)
13047 return isl_basic_map_free(bmap);
13049 for (i = 0; i < n_div; ++i) {
13050 int o_bmap = 0, o_ls = 0;
13052 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
13053 o_bmap += 1 + 1 + n_param;
13054 o_ls += 1 + 1 + n_param;
13055 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
13056 o_bmap += n_before;
13057 isl_seq_cpy(bmap->div[i] + o_bmap,
13058 ls->div->row[i] + o_ls, n_set);
13059 o_bmap += n_set;
13060 o_ls += n_set;
13061 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
13062 o_bmap += n_after;
13063 isl_seq_cpy(bmap->div[i] + o_bmap,
13064 ls->div->row[i] + o_ls, n_div);
13065 o_bmap += n_div;
13066 o_ls += n_div;
13067 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
13068 bmap = isl_basic_map_add_div_constraints(bmap, i);
13069 if (!bmap)
13070 goto error;
13073 isl_local_space_free(ls);
13074 return bmap;
13075 error:
13076 isl_local_space_free(ls);
13077 return isl_basic_map_free(bmap);
13080 /* How many stride constraints does "ma" enforce?
13081 * That is, how many of the affine expressions have a denominator
13082 * different from one?
13084 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
13086 int i;
13087 int strides = 0;
13089 for (i = 0; i < ma->n; ++i)
13090 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
13091 strides++;
13093 return strides;
13096 /* For each affine expression in ma of the form
13098 * x_i = (f_i y + h_i)/m_i
13100 * with m_i different from one, add a constraint to "bmap"
13101 * of the form
13103 * f_i y + h_i = m_i alpha_i
13105 * with alpha_i an additional existentially quantified variable.
13107 * The input variables of "ma" correspond to a subset of the variables
13108 * of "bmap". There are "n_before" variables in "bmap" before this
13109 * subset and "n_after" variables after this subset.
13110 * The integer divisions of the affine expressions in "ma" are assumed
13111 * to have been aligned. There are "n_div_ma" of them and
13112 * they appear first in "bmap", straight after the "n_after" variables.
13114 static __isl_give isl_basic_map *add_ma_strides(
13115 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
13116 int n_before, int n_after, int n_div_ma)
13118 int i, k;
13119 int div;
13120 isl_size total;
13121 isl_size n_param;
13122 isl_size n_in;
13124 total = isl_basic_map_dim(bmap, isl_dim_all);
13125 n_param = isl_multi_aff_dim(ma, isl_dim_param);
13126 n_in = isl_multi_aff_dim(ma, isl_dim_in);
13127 if (total < 0 || n_param < 0 || n_in < 0)
13128 return isl_basic_map_free(bmap);
13129 for (i = 0; i < ma->n; ++i) {
13130 int o_bmap = 0, o_ma = 1;
13132 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
13133 continue;
13134 div = isl_basic_map_alloc_div(bmap);
13135 k = isl_basic_map_alloc_equality(bmap);
13136 if (div < 0 || k < 0)
13137 goto error;
13138 isl_int_set_si(bmap->div[div][0], 0);
13139 isl_seq_cpy(bmap->eq[k] + o_bmap,
13140 ma->u.p[i]->v->el + o_ma, 1 + n_param);
13141 o_bmap += 1 + n_param;
13142 o_ma += 1 + n_param;
13143 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
13144 o_bmap += n_before;
13145 isl_seq_cpy(bmap->eq[k] + o_bmap,
13146 ma->u.p[i]->v->el + o_ma, n_in);
13147 o_bmap += n_in;
13148 o_ma += n_in;
13149 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
13150 o_bmap += n_after;
13151 isl_seq_cpy(bmap->eq[k] + o_bmap,
13152 ma->u.p[i]->v->el + o_ma, n_div_ma);
13153 o_bmap += n_div_ma;
13154 o_ma += n_div_ma;
13155 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
13156 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
13157 total++;
13160 return bmap;
13161 error:
13162 isl_basic_map_free(bmap);
13163 return NULL;
13166 /* Replace the domain or range space (depending on "type) of "space" by "set".
13168 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
13169 enum isl_dim_type type, __isl_take isl_space *set)
13171 if (type == isl_dim_in) {
13172 space = isl_space_range(space);
13173 space = isl_space_map_from_domain_and_range(set, space);
13174 } else {
13175 space = isl_space_domain(space);
13176 space = isl_space_map_from_domain_and_range(space, set);
13179 return space;
13182 /* Compute the preimage of the domain or range (depending on "type")
13183 * of "bmap" under the function represented by "ma".
13184 * In other words, plug in "ma" in the domain or range of "bmap".
13185 * The result is a basic map that lives in the same space as "bmap"
13186 * except that the domain or range has been replaced by
13187 * the domain space of "ma".
13189 * If bmap is represented by
13191 * A(p) + S u + B x + T v + C(divs) >= 0,
13193 * where u and x are input and output dimensions if type == isl_dim_out
13194 * while x and v are input and output dimensions if type == isl_dim_in,
13195 * and ma is represented by
13197 * x = D(p) + F(y) + G(divs')
13199 * then the result is
13201 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
13203 * The divs in the input set are similarly adjusted.
13204 * In particular
13206 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
13208 * becomes
13210 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
13211 * B_i G(divs') + c_i(divs))/n_i)
13213 * If bmap is not a rational map and if F(y) involves any denominators
13215 * x_i = (f_i y + h_i)/m_i
13217 * then additional constraints are added to ensure that we only
13218 * map back integer points. That is we enforce
13220 * f_i y + h_i = m_i alpha_i
13222 * with alpha_i an additional existentially quantified variable.
13224 * We first copy over the divs from "ma".
13225 * Then we add the modified constraints and divs from "bmap".
13226 * Finally, we add the stride constraints, if needed.
13228 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
13229 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
13230 __isl_take isl_multi_aff *ma)
13232 int i, k;
13233 isl_space *space;
13234 isl_basic_map *res = NULL;
13235 isl_size n_before, n_after, n_div_bmap, n_div_ma;
13236 isl_int f, c1, c2, g;
13237 isl_bool rational;
13238 int strides;
13240 isl_int_init(f);
13241 isl_int_init(c1);
13242 isl_int_init(c2);
13243 isl_int_init(g);
13245 ma = isl_multi_aff_align_divs(ma);
13246 if (!bmap || !ma)
13247 goto error;
13248 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
13249 goto error;
13251 if (type == isl_dim_in) {
13252 n_before = 0;
13253 n_after = isl_basic_map_dim(bmap, isl_dim_out);
13254 } else {
13255 n_before = isl_basic_map_dim(bmap, isl_dim_in);
13256 n_after = 0;
13258 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
13259 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
13260 if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
13261 goto error;
13263 space = isl_multi_aff_get_domain_space(ma);
13264 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
13265 rational = isl_basic_map_is_rational(bmap);
13266 strides = rational ? 0 : multi_aff_strides(ma);
13267 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
13268 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
13269 if (rational)
13270 res = isl_basic_map_set_rational(res);
13272 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
13273 if (isl_basic_map_alloc_div(res) < 0)
13274 goto error;
13276 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
13277 if (!res)
13278 goto error;
13280 for (i = 0; i < bmap->n_eq; ++i) {
13281 k = isl_basic_map_alloc_equality(res);
13282 if (k < 0)
13283 goto error;
13284 if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13285 n_after, n_div_ma, n_div_bmap,
13286 f, c1, c2, g, 0) < 0)
13287 goto error;
13290 for (i = 0; i < bmap->n_ineq; ++i) {
13291 k = isl_basic_map_alloc_inequality(res);
13292 if (k < 0)
13293 goto error;
13294 if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13295 n_after, n_div_ma, n_div_bmap,
13296 f, c1, c2, g, 0) < 0)
13297 goto error;
13300 for (i = 0; i < bmap->n_div; ++i) {
13301 if (isl_int_is_zero(bmap->div[i][0])) {
13302 isl_int_set_si(res->div[n_div_ma + i][0], 0);
13303 continue;
13305 if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13306 n_before, n_after, n_div_ma, n_div_bmap,
13307 f, c1, c2, g, 1) < 0)
13308 goto error;
13311 if (strides)
13312 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13314 isl_int_clear(f);
13315 isl_int_clear(c1);
13316 isl_int_clear(c2);
13317 isl_int_clear(g);
13318 isl_basic_map_free(bmap);
13319 isl_multi_aff_free(ma);
13320 res = isl_basic_map_simplify(res);
13321 return isl_basic_map_finalize(res);
13322 error:
13323 isl_int_clear(f);
13324 isl_int_clear(c1);
13325 isl_int_clear(c2);
13326 isl_int_clear(g);
13327 isl_basic_map_free(bmap);
13328 isl_multi_aff_free(ma);
13329 isl_basic_map_free(res);
13330 return NULL;
13333 /* Compute the preimage of "bset" under the function represented by "ma".
13334 * In other words, plug in "ma" in "bset". The result is a basic set
13335 * that lives in the domain space of "ma".
13337 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13338 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13340 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13343 /* Compute the preimage of the domain of "bmap" under the function
13344 * represented by "ma".
13345 * In other words, plug in "ma" in the domain of "bmap".
13346 * The result is a basic map that lives in the same space as "bmap"
13347 * except that the domain has been replaced by the domain space of "ma".
13349 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13350 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13352 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13355 /* Compute the preimage of the range of "bmap" under the function
13356 * represented by "ma".
13357 * In other words, plug in "ma" in the range of "bmap".
13358 * The result is a basic map that lives in the same space as "bmap"
13359 * except that the range has been replaced by the domain space of "ma".
13361 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13362 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13364 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13367 /* Check if the range of "ma" is compatible with the domain or range
13368 * (depending on "type") of "map".
13369 * Return isl_stat_error if anything is wrong.
13371 static isl_stat check_map_compatible_range_multi_aff(
13372 __isl_keep isl_map *map, enum isl_dim_type type,
13373 __isl_keep isl_multi_aff *ma)
13375 isl_bool m;
13376 isl_space *ma_space;
13378 ma_space = isl_multi_aff_get_space(ma);
13379 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
13380 isl_space_free(ma_space);
13381 if (m < 0)
13382 return isl_stat_error;
13383 if (!m)
13384 isl_die(isl_map_get_ctx(map), isl_error_invalid,
13385 "spaces don't match", return isl_stat_error);
13386 return isl_stat_ok;
13389 /* Compute the preimage of the domain or range (depending on "type")
13390 * of "map" under the function represented by "ma".
13391 * In other words, plug in "ma" in the domain or range of "map".
13392 * The result is a map that lives in the same space as "map"
13393 * except that the domain or range has been replaced by
13394 * the domain space of "ma".
13396 * The parameters are assumed to have been aligned.
13398 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13399 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13401 int i;
13402 isl_space *space;
13404 map = isl_map_cow(map);
13405 ma = isl_multi_aff_align_divs(ma);
13406 if (!map || !ma)
13407 goto error;
13408 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13409 goto error;
13411 for (i = 0; i < map->n; ++i) {
13412 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13413 isl_multi_aff_copy(ma));
13414 if (!map->p[i])
13415 goto error;
13418 space = isl_multi_aff_get_domain_space(ma);
13419 space = isl_space_set(isl_map_get_space(map), type, space);
13421 isl_space_free(map->dim);
13422 map->dim = space;
13423 if (!map->dim)
13424 goto error;
13426 isl_multi_aff_free(ma);
13427 if (map->n > 1)
13428 ISL_F_CLR(map, ISL_MAP_DISJOINT);
13429 ISL_F_CLR(map, ISL_SET_NORMALIZED);
13430 return map;
13431 error:
13432 isl_multi_aff_free(ma);
13433 isl_map_free(map);
13434 return NULL;
13437 /* Compute the preimage of the domain or range (depending on "type")
13438 * of "map" under the function represented by "ma".
13439 * In other words, plug in "ma" in the domain or range of "map".
13440 * The result is a map that lives in the same space as "map"
13441 * except that the domain or range has been replaced by
13442 * the domain space of "ma".
13444 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13445 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13447 isl_bool aligned;
13449 if (!map || !ma)
13450 goto error;
13452 aligned = isl_map_space_has_equal_params(map, ma->space);
13453 if (aligned < 0)
13454 goto error;
13455 if (aligned)
13456 return map_preimage_multi_aff(map, type, ma);
13458 if (isl_map_check_named_params(map) < 0)
13459 goto error;
13460 if (!isl_space_has_named_params(ma->space))
13461 isl_die(map->ctx, isl_error_invalid,
13462 "unaligned unnamed parameters", goto error);
13463 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13464 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13466 return map_preimage_multi_aff(map, type, ma);
13467 error:
13468 isl_multi_aff_free(ma);
13469 return isl_map_free(map);
13472 /* Compute the preimage of "set" under the function represented by "ma".
13473 * In other words, plug in "ma" in "set". The result is a set
13474 * that lives in the domain space of "ma".
13476 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13477 __isl_take isl_multi_aff *ma)
13479 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13482 /* Compute the preimage of the domain of "map" under the function
13483 * represented by "ma".
13484 * In other words, plug in "ma" in the domain of "map".
13485 * The result is a map that lives in the same space as "map"
13486 * except that the domain has been replaced by the domain space of "ma".
13488 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13489 __isl_take isl_multi_aff *ma)
13491 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13494 /* Compute the preimage of the range of "map" under the function
13495 * represented by "ma".
13496 * In other words, plug in "ma" in the range of "map".
13497 * The result is a map that lives in the same space as "map"
13498 * except that the range has been replaced by the domain space of "ma".
13500 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13501 __isl_take isl_multi_aff *ma)
13503 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
13506 /* Compute the preimage of "map" under the function represented by "pma".
13507 * In other words, plug in "pma" in the domain or range of "map".
13508 * The result is a map that lives in the same space as "map",
13509 * except that the space of type "type" has been replaced by
13510 * the domain space of "pma".
13512 * The parameters of "map" and "pma" are assumed to have been aligned.
13514 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
13515 __isl_take isl_map *map, enum isl_dim_type type,
13516 __isl_take isl_pw_multi_aff *pma)
13518 int i;
13519 isl_map *res;
13521 if (!pma)
13522 goto error;
13524 if (pma->n == 0) {
13525 isl_pw_multi_aff_free(pma);
13526 res = isl_map_empty(isl_map_get_space(map));
13527 isl_map_free(map);
13528 return res;
13531 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13532 isl_multi_aff_copy(pma->p[0].maff));
13533 if (type == isl_dim_in)
13534 res = isl_map_intersect_domain(res,
13535 isl_map_copy(pma->p[0].set));
13536 else
13537 res = isl_map_intersect_range(res,
13538 isl_map_copy(pma->p[0].set));
13540 for (i = 1; i < pma->n; ++i) {
13541 isl_map *res_i;
13543 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13544 isl_multi_aff_copy(pma->p[i].maff));
13545 if (type == isl_dim_in)
13546 res_i = isl_map_intersect_domain(res_i,
13547 isl_map_copy(pma->p[i].set));
13548 else
13549 res_i = isl_map_intersect_range(res_i,
13550 isl_map_copy(pma->p[i].set));
13551 res = isl_map_union(res, res_i);
13554 isl_pw_multi_aff_free(pma);
13555 isl_map_free(map);
13556 return res;
13557 error:
13558 isl_pw_multi_aff_free(pma);
13559 isl_map_free(map);
13560 return NULL;
13563 /* Compute the preimage of "map" under the function represented by "pma".
13564 * In other words, plug in "pma" in the domain or range of "map".
13565 * The result is a map that lives in the same space as "map",
13566 * except that the space of type "type" has been replaced by
13567 * the domain space of "pma".
13569 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
13570 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
13572 isl_bool aligned;
13574 if (!map || !pma)
13575 goto error;
13577 aligned = isl_map_space_has_equal_params(map, pma->dim);
13578 if (aligned < 0)
13579 goto error;
13580 if (aligned)
13581 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13583 if (isl_map_check_named_params(map) < 0)
13584 goto error;
13585 if (isl_pw_multi_aff_check_named_params(pma) < 0)
13586 goto error;
13587 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
13588 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
13590 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13591 error:
13592 isl_pw_multi_aff_free(pma);
13593 return isl_map_free(map);
13596 /* Compute the preimage of "set" under the function represented by "pma".
13597 * In other words, plug in "pma" in "set". The result is a set
13598 * that lives in the domain space of "pma".
13600 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
13601 __isl_take isl_pw_multi_aff *pma)
13603 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
13606 /* Compute the preimage of the domain of "map" under the function
13607 * represented by "pma".
13608 * In other words, plug in "pma" in the domain of "map".
13609 * The result is a map that lives in the same space as "map",
13610 * except that domain space has been replaced by the domain space of "pma".
13612 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
13613 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13615 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
13618 /* Compute the preimage of the range of "map" under the function
13619 * represented by "pma".
13620 * In other words, plug in "pma" in the range of "map".
13621 * The result is a map that lives in the same space as "map",
13622 * except that range space has been replaced by the domain space of "pma".
13624 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
13625 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13627 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
13630 /* Compute the preimage of "map" under the function represented by "mpa".
13631 * In other words, plug in "mpa" in the domain or range of "map".
13632 * The result is a map that lives in the same space as "map",
13633 * except that the space of type "type" has been replaced by
13634 * the domain space of "mpa".
13636 * If the map does not involve any constraints that refer to the
13637 * dimensions of the substituted space, then the only possible
13638 * effect of "mpa" on the map is to map the space to a different space.
13639 * We create a separate isl_multi_aff to effectuate this change
13640 * in order to avoid spurious splitting of the map along the pieces
13641 * of "mpa".
13642 * If "mpa" has a non-trivial explicit domain, however,
13643 * then the full substitution should be performed.
13645 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
13646 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
13648 isl_size n;
13649 isl_bool full;
13650 isl_pw_multi_aff *pma;
13652 n = isl_map_dim(map, type);
13653 if (n < 0 || !mpa)
13654 goto error;
13656 full = isl_map_involves_dims(map, type, 0, n);
13657 if (full >= 0 && !full)
13658 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
13659 if (full < 0)
13660 goto error;
13661 if (!full) {
13662 isl_space *space;
13663 isl_multi_aff *ma;
13665 space = isl_multi_pw_aff_get_space(mpa);
13666 isl_multi_pw_aff_free(mpa);
13667 ma = isl_multi_aff_zero(space);
13668 return isl_map_preimage_multi_aff(map, type, ma);
13671 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
13672 return isl_map_preimage_pw_multi_aff(map, type, pma);
13673 error:
13674 isl_map_free(map);
13675 isl_multi_pw_aff_free(mpa);
13676 return NULL;
13679 /* Compute the preimage of "map" under the function represented by "mpa".
13680 * In other words, plug in "mpa" in the domain "map".
13681 * The result is a map that lives in the same space as "map",
13682 * except that domain space has been replaced by the domain space of "mpa".
13684 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
13685 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
13687 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
13690 /* Compute the preimage of "set" by the function represented by "mpa".
13691 * In other words, plug in "mpa" in "set".
13693 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
13694 __isl_take isl_multi_pw_aff *mpa)
13696 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
13699 /* Return a copy of the equality constraints of "bset" as a matrix.
13701 __isl_give isl_mat *isl_basic_set_extract_equalities(
13702 __isl_keep isl_basic_set *bset)
13704 isl_ctx *ctx;
13705 isl_size total;
13707 total = isl_basic_set_dim(bset, isl_dim_all);
13708 if (total < 0)
13709 return NULL;
13711 ctx = isl_basic_set_get_ctx(bset);
13712 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
13715 /* Are the "n" "coefficients" starting at "first" of the integer division
13716 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
13717 * to each other?
13718 * The "coefficient" at position 0 is the denominator.
13719 * The "coefficient" at position 1 is the constant term.
13721 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
13722 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
13723 unsigned first, unsigned n)
13725 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
13726 return isl_bool_error;
13727 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
13728 return isl_bool_error;
13729 return isl_seq_eq(bmap1->div[pos1] + first,
13730 bmap2->div[pos2] + first, n);
13733 /* Are the integer division expressions at position "pos1" in "bmap1" and
13734 * "pos2" in "bmap2" equal to each other, except that the constant terms
13735 * are different?
13737 isl_bool isl_basic_map_equal_div_expr_except_constant(
13738 __isl_keep isl_basic_map *bmap1, int pos1,
13739 __isl_keep isl_basic_map *bmap2, int pos2)
13741 isl_bool equal;
13742 isl_size total, total2;
13744 total = isl_basic_map_dim(bmap1, isl_dim_all);
13745 total2 = isl_basic_map_dim(bmap2, isl_dim_all);
13746 if (total < 0 || total2 < 0)
13747 return isl_bool_error;
13748 if (total != total2)
13749 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
13750 "incomparable div expressions", return isl_bool_error);
13751 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13752 0, 1);
13753 if (equal < 0 || !equal)
13754 return equal;
13755 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13756 1, 1);
13757 if (equal < 0 || equal)
13758 return isl_bool_not(equal);
13759 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13760 2, total);
13763 /* Replace the numerator of the constant term of the integer division
13764 * expression at position "div" in "bmap" by "value".
13765 * The caller guarantees that this does not change the meaning
13766 * of the input.
13768 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
13769 __isl_take isl_basic_map *bmap, int div, int value)
13771 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
13772 return isl_basic_map_free(bmap);
13774 isl_int_set_si(bmap->div[div][1], value);
13776 return bmap;
13779 /* Is the point "inner" internal to inequality constraint "ineq"
13780 * of "bset"?
13781 * The point is considered to be internal to the inequality constraint,
13782 * if it strictly lies on the positive side of the inequality constraint,
13783 * or if it lies on the constraint and the constraint is lexico-positive.
13785 static isl_bool is_internal(__isl_keep isl_vec *inner,
13786 __isl_keep isl_basic_set *bset, int ineq)
13788 isl_ctx *ctx;
13789 int pos;
13790 isl_size total;
13792 if (!inner || !bset)
13793 return isl_bool_error;
13795 ctx = isl_basic_set_get_ctx(bset);
13796 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13797 &ctx->normalize_gcd);
13798 if (!isl_int_is_zero(ctx->normalize_gcd))
13799 return isl_int_is_nonneg(ctx->normalize_gcd);
13801 total = isl_basic_set_dim(bset, isl_dim_all);
13802 if (total < 0)
13803 return isl_bool_error;
13804 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13805 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13808 /* Tighten the inequality constraints of "bset" that are outward with respect
13809 * to the point "vec".
13810 * That is, tighten the constraints that are not satisfied by "vec".
13812 * "vec" is a point internal to some superset S of "bset" that is used
13813 * to make the subsets of S disjoint, by tightening one half of the constraints
13814 * that separate two subsets. In particular, the constraints of S
13815 * are all satisfied by "vec" and should not be tightened.
13816 * Of the internal constraints, those that have "vec" on the outside
13817 * are tightened. The shared facet is included in the adjacent subset
13818 * with the opposite constraint.
13819 * For constraints that saturate "vec", this criterion cannot be used
13820 * to determine which of the two sides should be tightened.
13821 * Instead, the sign of the first non-zero coefficient is used
13822 * to make this choice. Note that this second criterion is never used
13823 * on the constraints of S since "vec" is interior to "S".
13825 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13826 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13828 int j;
13830 bset = isl_basic_set_cow(bset);
13831 if (!bset)
13832 return NULL;
13833 for (j = 0; j < bset->n_ineq; ++j) {
13834 isl_bool internal;
13836 internal = is_internal(vec, bset, j);
13837 if (internal < 0)
13838 return isl_basic_set_free(bset);
13839 if (internal)
13840 continue;
13841 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13844 return bset;
13847 /* Replace the variables x of type "type" starting at "first" in "bmap"
13848 * by x' with x = M x' with M the matrix trans.
13849 * That is, replace the corresponding coefficients c by c M.
13851 * The transformation matrix should be a square matrix.
13853 __isl_give isl_basic_map *isl_basic_map_transform_dims(
13854 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
13855 __isl_take isl_mat *trans)
13857 unsigned pos;
13859 bmap = isl_basic_map_cow(bmap);
13860 if (!bmap || !trans)
13861 goto error;
13863 if (trans->n_row != trans->n_col)
13864 isl_die(trans->ctx, isl_error_invalid,
13865 "expecting square transformation matrix", goto error);
13866 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
13867 goto error;
13869 pos = isl_basic_map_offset(bmap, type) + first;
13871 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
13872 isl_mat_copy(trans)) < 0)
13873 goto error;
13874 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
13875 isl_mat_copy(trans)) < 0)
13876 goto error;
13877 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
13878 isl_mat_copy(trans)) < 0)
13879 goto error;
13881 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
13882 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
13884 isl_mat_free(trans);
13885 return bmap;
13886 error:
13887 isl_mat_free(trans);
13888 isl_basic_map_free(bmap);
13889 return NULL;
13892 /* Replace the variables x of type "type" starting at "first" in "bset"
13893 * by x' with x = M x' with M the matrix trans.
13894 * That is, replace the corresponding coefficients c by c M.
13896 * The transformation matrix should be a square matrix.
13898 __isl_give isl_basic_set *isl_basic_set_transform_dims(
13899 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
13900 __isl_take isl_mat *trans)
13902 return isl_basic_map_transform_dims(bset, type, first, trans);