sort constraints while looking for pair of opposite constraints
[isl.git] / isl_map.c
blobba9bf0106cd33ab515c7180e59eb35ddbd5ed679
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-2019 Cerebras Systems
9 * Copyright 2022 Cerebras Systems
11 * Use of this software is governed by the MIT license
13 * Written by Sven Verdoolaege, K.U.Leuven, Departement
14 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
15 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
16 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
17 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
18 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
19 * B.P. 105 - 78153 Le Chesnay, France
20 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
21 * CS 42112, 75589 Paris Cedex 12, France
22 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
25 #include <string.h>
26 #include <isl_ctx_private.h>
27 #include <isl_map_private.h>
28 #include <isl_blk.h>
29 #include <isl_id_private.h>
30 #include <isl/constraint.h>
31 #include "isl_space_private.h"
32 #include "isl_equalities.h"
33 #include <isl_lp_private.h>
34 #include <isl_seq.h>
35 #include <isl/set.h>
36 #include <isl/map.h>
37 #include <isl_reordering.h>
38 #include "isl_sample.h"
39 #include <isl_sort.h>
40 #include "isl_tab.h"
41 #include <isl/vec.h>
42 #include <isl_mat_private.h>
43 #include <isl_vec_private.h>
44 #include <isl_dim_map.h>
45 #include <isl_local_space_private.h>
46 #include <isl_aff_private.h>
47 #include <isl_options_private.h>
48 #include <isl_morph.h>
49 #include <isl_val_private.h>
50 #include <isl_printer_private.h>
52 #include <bset_to_bmap.c>
53 #include <bset_from_bmap.c>
54 #include <set_to_map.c>
55 #include <set_from_map.c>
57 /* Treat "bset" as a basic map.
58 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
59 * this function performs a redundant cast.
61 static __isl_keep const isl_basic_map *const_bset_to_bmap(
62 __isl_keep const isl_basic_set *bset)
64 return (const isl_basic_map *) bset;
67 #undef TYPE
68 #define TYPE isl_basic_map
69 #include "has_single_reference_templ.c"
71 static unsigned pos(__isl_keep isl_space *space, enum isl_dim_type type)
73 switch (type) {
74 case isl_dim_param: return 1;
75 case isl_dim_in: return 1 + space->nparam;
76 case isl_dim_out: return 1 + space->nparam + space->n_in;
77 default: return 0;
81 isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
82 enum isl_dim_type type)
84 if (!bmap)
85 return isl_size_error;
86 switch (type) {
87 case isl_dim_cst: return 1;
88 case isl_dim_param:
89 case isl_dim_in:
90 case isl_dim_out: return isl_space_dim(bmap->dim, type);
91 case isl_dim_div: return bmap->n_div;
92 case isl_dim_all: return isl_basic_map_total_dim(bmap);
93 default: return 0;
97 /* Return the space of "map".
99 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
101 return map ? map->dim : NULL;
104 /* Return the space of "set".
106 __isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
108 return isl_map_peek_space(set_to_map(set));
111 isl_size isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
113 return isl_space_dim(isl_map_peek_space(map), type);
116 /* Return the dimensionality of the domain (tuple) of the map.
118 isl_size isl_map_domain_tuple_dim(__isl_keep isl_map *map)
120 return isl_map_dim(map, isl_dim_in);
123 /* Return the dimensionality of the range (tuple) of the map.
125 isl_size isl_map_range_tuple_dim(__isl_keep isl_map *map)
127 return isl_map_dim(map, isl_dim_out);
130 isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
132 return isl_map_dim(set_to_map(set), type);
135 /* Return the dimensionality of the (tuple of the) set.
137 isl_size isl_set_tuple_dim(__isl_keep isl_set *set)
139 return isl_set_dim(set, isl_dim_set);
142 /* Return the position of the variables of the given type
143 * within the sequence of variables of "bmap".
145 isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
146 enum isl_dim_type type)
148 isl_space *space;
150 space = isl_basic_map_peek_space(bmap);
152 switch (type) {
153 case isl_dim_param:
154 case isl_dim_in:
155 case isl_dim_out: return isl_space_offset(space, type);
156 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
157 case isl_dim_cst:
158 default:
159 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
160 "invalid dimension type", return isl_size_error);
164 /* Return the position of the variables of the given type
165 * within the sequence of variables of "bset".
167 isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
168 enum isl_dim_type type)
170 return isl_basic_map_var_offset(bset_to_bmap(bset), type);
173 /* Return the position of the coefficients of the variables of the given type
174 * within the sequence of coefficients of "bmap".
176 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
177 enum isl_dim_type type)
179 switch (type) {
180 case isl_dim_cst: return 0;
181 case isl_dim_param:
182 case isl_dim_in:
183 case isl_dim_out:
184 case isl_dim_div: return 1 + isl_basic_map_var_offset(bmap, type);
185 default: return 0;
189 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
190 enum isl_dim_type type)
192 return isl_basic_map_offset(bset, type);
195 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
197 return pos(map->dim, type);
200 isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,
201 enum isl_dim_type type)
203 return isl_basic_map_dim(bset, type);
206 isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
208 return isl_basic_set_dim(bset, isl_dim_set);
211 isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
213 return isl_basic_set_dim(bset, isl_dim_param);
216 isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
218 return isl_basic_map_total_dim(const_bset_to_bmap(bset));
221 isl_size isl_set_n_dim(__isl_keep isl_set *set)
223 return isl_set_dim(set, isl_dim_set);
226 isl_size isl_set_n_param(__isl_keep isl_set *set)
228 return isl_set_dim(set, isl_dim_param);
231 isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
233 isl_size dim;
235 if (!bmap)
236 return isl_size_error;
237 dim = isl_space_dim(bmap->dim, isl_dim_all);
238 if (dim < 0)
239 return isl_size_error;
240 return dim + bmap->n_div;
243 /* Return the number of equality constraints in the description of "bmap".
244 * Return isl_size_error on error.
246 isl_size isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
248 if (!bmap)
249 return isl_size_error;
250 return bmap->n_eq;
253 /* Return the number of equality constraints in the description of "bset".
254 * Return isl_size_error on error.
256 isl_size isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
258 return isl_basic_map_n_equality(bset_to_bmap(bset));
261 /* Return the number of inequality constraints in the description of "bmap".
262 * Return isl_size_error on error.
264 isl_size isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
266 if (!bmap)
267 return isl_size_error;
268 return bmap->n_ineq;
271 /* Return the number of inequality constraints in the description of "bset".
272 * Return isl_size_error on error.
274 isl_size isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
276 return isl_basic_map_n_inequality(bset_to_bmap(bset));
279 /* Do "bmap1" and "bmap2" have the same parameters?
281 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
282 __isl_keep isl_basic_map *bmap2)
284 isl_space *space1, *space2;
286 space1 = isl_basic_map_peek_space(bmap1);
287 space2 = isl_basic_map_peek_space(bmap2);
288 return isl_space_has_equal_params(space1, space2);
291 /* Do "map1" and "map2" have the same parameters?
293 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
294 __isl_keep isl_map *map2)
296 isl_space *space1, *space2;
298 space1 = isl_map_peek_space(map1);
299 space2 = isl_map_peek_space(map2);
300 return isl_space_has_equal_params(space1, space2);
303 /* Do "map" and "set" have the same parameters?
305 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
306 __isl_keep isl_set *set)
308 return isl_map_has_equal_params(map, set_to_map(set));
311 /* Is the tuple of type "type" of "bmap" the same as the single tuple of "bset"?
313 static isl_bool isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map *bmap,
314 enum isl_dim_type type, __isl_keep isl_basic_set *bset)
316 isl_space *bmap_space, *bset_space;
318 bmap_space = isl_basic_map_peek_space(bmap);
319 bset_space = isl_basic_set_peek_space(bset);
320 return isl_space_tuple_is_equal(bmap_space, type,
321 bset_space, isl_dim_set);
324 /* Is the tuple of type "type" of "map" the same as the single tuple of "set"?
326 static isl_bool isl_map_set_tuple_is_equal(__isl_keep isl_map *map,
327 enum isl_dim_type type, __isl_keep isl_set *set)
329 return isl_map_tuple_is_equal(map, type, set_to_map(set), isl_dim_set);
332 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
333 __isl_keep isl_set *set)
335 isl_bool m;
336 if (!map || !set)
337 return isl_bool_error;
338 m = isl_map_has_equal_params(map, set_to_map(set));
339 if (m < 0 || !m)
340 return m;
341 return isl_map_set_tuple_is_equal(map, isl_dim_in, set);
344 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
345 __isl_keep isl_basic_set *bset)
347 isl_bool m;
348 if (!bmap || !bset)
349 return isl_bool_error;
350 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
351 if (m < 0 || !m)
352 return m;
353 return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_in, bset);
356 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
357 __isl_keep isl_set *set)
359 isl_bool m;
360 if (!map || !set)
361 return isl_bool_error;
362 m = isl_map_has_equal_params(map, set_to_map(set));
363 if (m < 0 || !m)
364 return m;
365 return isl_map_set_tuple_is_equal(map, isl_dim_out, set);
368 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
369 __isl_keep isl_basic_set *bset)
371 isl_bool m;
372 if (!bmap || !bset)
373 return isl_bool_error;
374 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
375 if (m < 0 || !m)
376 return m;
377 return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_out, bset);
380 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
382 return bmap ? bmap->ctx : NULL;
385 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
387 return bset ? bset->ctx : NULL;
390 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
392 return map ? map->ctx : NULL;
395 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
397 return set ? set->ctx : NULL;
400 /* Return the space of "bmap".
402 __isl_keep isl_space *isl_basic_map_peek_space(
403 __isl_keep const isl_basic_map *bmap)
405 return bmap ? bmap->dim : NULL;
408 /* Return the space of "bset".
410 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
412 return isl_basic_map_peek_space(bset_to_bmap(bset));
415 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
417 return isl_space_copy(isl_basic_map_peek_space(bmap));
420 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
422 return isl_basic_map_get_space(bset_to_bmap(bset));
425 /* Return the space of "bmap".
426 * This may be either a copy or the space itself
427 * if there is only one reference to "bmap".
428 * This allows the space to be modified inplace
429 * if both the basic map and its space have only a single reference.
430 * The caller is not allowed to modify "bmap" between this call and
431 * a subsequent call to isl_basic_map_restore_space.
432 * The only exception is that isl_basic_map_free can be called instead.
434 static __isl_give isl_space *isl_basic_map_take_space(
435 __isl_keep isl_basic_map *bmap)
437 isl_space *space;
439 if (!bmap)
440 return NULL;
441 if (bmap->ref != 1)
442 return isl_basic_map_get_space(bmap);
443 space = bmap->dim;
444 bmap->dim = NULL;
445 return space;
448 /* Set the space of "bmap" to "space", where the space of "bmap" may be missing
449 * due to a preceding call to isl_basic_map_take_space.
450 * However, in this case, "bmap" only has a single reference and
451 * then the call to isl_basic_map_cow has no effect.
453 static __isl_give isl_basic_map *isl_basic_map_restore_space(
454 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
456 if (!bmap || !space)
457 goto error;
459 if (bmap->dim == space) {
460 isl_space_free(space);
461 return bmap;
464 bmap = isl_basic_map_cow(bmap);
465 if (!bmap)
466 goto error;
467 isl_space_free(bmap->dim);
468 bmap->dim = space;
470 return bmap;
471 error:
472 isl_basic_map_free(bmap);
473 isl_space_free(space);
474 return NULL;
477 /* Extract the divs in "bmap" as a matrix.
479 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
481 int i;
482 isl_ctx *ctx;
483 isl_mat *div;
484 isl_size v_div;
485 unsigned cols;
487 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
488 if (v_div < 0)
489 return NULL;
491 ctx = isl_basic_map_get_ctx(bmap);
492 cols = 1 + 1 + v_div + bmap->n_div;
493 div = isl_mat_alloc(ctx, bmap->n_div, cols);
494 if (!div)
495 return NULL;
497 for (i = 0; i < bmap->n_div; ++i)
498 isl_seq_cpy(div->row[i], bmap->div[i], cols);
500 return div;
503 /* Extract the divs in "bset" as a matrix.
505 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
507 return isl_basic_map_get_divs(bset);
510 __isl_give isl_local_space *isl_basic_map_get_local_space(
511 __isl_keep isl_basic_map *bmap)
513 isl_mat *div;
515 if (!bmap)
516 return NULL;
518 div = isl_basic_map_get_divs(bmap);
519 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
522 __isl_give isl_local_space *isl_basic_set_get_local_space(
523 __isl_keep isl_basic_set *bset)
525 return isl_basic_map_get_local_space(bset);
528 /* For each known div d = floor(f/m), add the constraints
530 * f - m d >= 0
531 * -(f-(m-1)) + m d >= 0
533 * Do not finalize the result.
535 static __isl_give isl_basic_map *add_known_div_constraints(
536 __isl_take isl_basic_map *bmap)
538 int i;
539 isl_size n_div;
541 n_div = isl_basic_map_dim(bmap, isl_dim_div);
542 if (n_div < 0)
543 return isl_basic_map_free(bmap);
544 if (n_div == 0)
545 return bmap;
546 bmap = isl_basic_map_cow(bmap);
547 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
548 if (!bmap)
549 return NULL;
550 for (i = 0; i < n_div; ++i) {
551 if (isl_int_is_zero(bmap->div[i][0]))
552 continue;
553 bmap = isl_basic_map_add_div_constraints(bmap, i);
556 return bmap;
559 __isl_give isl_basic_map *isl_basic_map_from_local_space(
560 __isl_take isl_local_space *ls)
562 int i;
563 isl_size n_div;
564 isl_basic_map *bmap;
566 n_div = isl_local_space_dim(ls, isl_dim_div);
567 if (n_div < 0)
568 ls = isl_local_space_free(ls);
569 if (!ls)
570 return NULL;
572 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
573 n_div, 0, 2 * n_div);
575 for (i = 0; i < n_div; ++i)
576 if (isl_basic_map_alloc_div(bmap) < 0)
577 goto error;
579 for (i = 0; i < n_div; ++i)
580 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
581 bmap = add_known_div_constraints(bmap);
583 isl_local_space_free(ls);
584 return bmap;
585 error:
586 isl_local_space_free(ls);
587 isl_basic_map_free(bmap);
588 return NULL;
591 __isl_give isl_basic_set *isl_basic_set_from_local_space(
592 __isl_take isl_local_space *ls)
594 return isl_basic_map_from_local_space(ls);
597 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
599 return isl_space_copy(isl_map_peek_space(map));
602 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
604 if (!set)
605 return NULL;
606 return isl_space_copy(set->dim);
609 /* Return the space of "map".
610 * This may be either a copy or the space itself
611 * if there is only one reference to "map".
612 * This allows the space to be modified inplace
613 * if both the map and its space have only a single reference.
614 * The caller is not allowed to modify "map" between this call and
615 * a subsequent call to isl_map_restore_space.
616 * The only exception is that isl_map_free can be called instead.
618 static __isl_give isl_space *isl_map_take_space(__isl_keep isl_map *map)
620 isl_space *space;
622 if (!map)
623 return NULL;
624 if (map->ref != 1)
625 return isl_map_get_space(map);
626 space = map->dim;
627 map->dim = NULL;
628 return space;
631 /* Set the space of "map" to "space", where the space of "map" may be missing
632 * due to a preceding call to isl_map_take_space.
633 * However, in this case, "map" only has a single reference and
634 * then the call to isl_map_cow has no effect.
636 static __isl_give isl_map *isl_map_restore_space(__isl_take isl_map *map,
637 __isl_take isl_space *space)
639 if (!map || !space)
640 goto error;
642 if (map->dim == space) {
643 isl_space_free(space);
644 return map;
647 map = isl_map_cow(map);
648 if (!map)
649 goto error;
650 isl_space_free(map->dim);
651 map->dim = space;
653 return map;
654 error:
655 isl_map_free(map);
656 isl_space_free(space);
657 return NULL;
660 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
661 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
663 isl_space *space;
665 space = isl_basic_map_take_space(bmap);
666 space = isl_space_set_tuple_name(space, type, s);
667 bmap = isl_basic_map_restore_space(bmap, space);
668 bmap = isl_basic_map_finalize(bmap);
669 return bmap;
672 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
673 __isl_take isl_basic_set *bset, const char *s)
675 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
678 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
679 enum isl_dim_type type)
681 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
684 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
685 enum isl_dim_type type, const char *s)
687 int i;
688 isl_space *space;
690 map = isl_map_cow(map);
691 if (!map)
692 return NULL;
694 for (i = 0; i < map->n; ++i) {
695 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
696 if (!map->p[i])
697 goto error;
700 space = isl_map_take_space(map);
701 space = isl_space_set_tuple_name(space, type, s);
702 map = isl_map_restore_space(map, space);
704 return map;
705 error:
706 isl_map_free(map);
707 return NULL;
710 /* Replace the identifier of the tuple of type "type" by "id".
712 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
713 __isl_take isl_basic_map *bmap,
714 enum isl_dim_type type, __isl_take isl_id *id)
716 isl_space *space;
718 space = isl_basic_map_take_space(bmap);
719 space = isl_space_set_tuple_id(space, type, id);
720 bmap = isl_basic_map_restore_space(bmap, space);
721 bmap = isl_basic_map_finalize(bmap);
722 return bmap;
725 /* Replace the identifier of the tuple by "id".
727 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
728 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
730 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
733 /* Does the input or output tuple have a name?
735 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
737 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
740 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
741 enum isl_dim_type type)
743 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
746 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
747 const char *s)
749 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
750 isl_dim_set, s));
753 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
754 enum isl_dim_type type, __isl_take isl_id *id)
756 isl_space *space;
758 space = isl_map_take_space(map);
759 space = isl_space_set_tuple_id(space, type, id);
760 map = isl_map_restore_space(map, space);
762 return isl_map_reset_space(map, isl_map_get_space(map));
765 /* Replace the identifier of the domain tuple of "map" by "id".
767 __isl_give isl_map *isl_map_set_domain_tuple_id(__isl_take isl_map *map,
768 __isl_take isl_id *id)
770 return isl_map_set_tuple_id(map, isl_dim_in, id);
773 /* Replace the identifier of the range tuple of "map" by "id".
775 __isl_give isl_map *isl_map_set_range_tuple_id(__isl_take isl_map *map,
776 __isl_take isl_id *id)
778 return isl_map_set_tuple_id(map, isl_dim_out, id);
781 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
782 __isl_take isl_id *id)
784 return isl_map_set_tuple_id(set, isl_dim_set, id);
787 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
788 enum isl_dim_type type)
790 isl_space *space;
792 space = isl_map_take_space(map);
793 space = isl_space_reset_tuple_id(space, type);
794 map = isl_map_restore_space(map, space);
796 return isl_map_reset_space(map, isl_map_get_space(map));
799 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
801 return isl_map_reset_tuple_id(set, isl_dim_set);
804 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
806 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
809 /* Does the domain tuple of "map" have an identifier?
811 isl_bool isl_map_has_domain_tuple_id(__isl_keep isl_map *map)
813 return isl_map_has_tuple_id(map, isl_dim_in);
816 /* Does the range tuple of "map" have an identifier?
818 isl_bool isl_map_has_range_tuple_id(__isl_keep isl_map *map)
820 return isl_map_has_tuple_id(map, isl_dim_out);
823 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
824 enum isl_dim_type type)
826 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
829 /* Return the identifier of the domain tuple of "map", assuming it has one.
831 __isl_give isl_id *isl_map_get_domain_tuple_id(__isl_keep isl_map *map)
833 return isl_map_get_tuple_id(map, isl_dim_in);
836 /* Return the identifier of the range tuple of "map", assuming it has one.
838 __isl_give isl_id *isl_map_get_range_tuple_id(__isl_keep isl_map *map)
840 return isl_map_get_tuple_id(map, isl_dim_out);
843 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
845 return isl_map_has_tuple_id(set, isl_dim_set);
848 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
850 return isl_map_get_tuple_id(set, isl_dim_set);
853 /* Does the set tuple have a name?
855 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
857 if (!set)
858 return isl_bool_error;
859 return isl_space_has_tuple_name(set->dim, isl_dim_set);
863 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
865 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
868 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
870 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
873 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
874 enum isl_dim_type type, unsigned pos)
876 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
879 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
880 enum isl_dim_type type, unsigned pos)
882 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
885 /* Does the given dimension have a name?
887 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
888 enum isl_dim_type type, unsigned pos)
890 if (!map)
891 return isl_bool_error;
892 return isl_space_has_dim_name(map->dim, type, pos);
895 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
896 enum isl_dim_type type, unsigned pos)
898 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
901 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
902 enum isl_dim_type type, unsigned pos)
904 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
907 /* Does the given dimension have a name?
909 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
910 enum isl_dim_type type, unsigned pos)
912 if (!set)
913 return isl_bool_error;
914 return isl_space_has_dim_name(set->dim, type, pos);
917 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
918 __isl_take isl_basic_map *bmap,
919 enum isl_dim_type type, unsigned pos, const char *s)
921 isl_space *space;
923 space = isl_basic_map_take_space(bmap);
924 space = isl_space_set_dim_name(space, type, pos, s);
925 bmap = isl_basic_map_restore_space(bmap, space);
926 return isl_basic_map_finalize(bmap);
929 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
930 enum isl_dim_type type, unsigned pos, const char *s)
932 int i;
933 isl_space *space;
935 map = isl_map_cow(map);
936 if (!map)
937 return NULL;
939 for (i = 0; i < map->n; ++i) {
940 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
941 if (!map->p[i])
942 goto error;
945 space = isl_map_take_space(map);
946 space = isl_space_set_dim_name(space, type, pos, s);
947 map = isl_map_restore_space(map, space);
949 return map;
950 error:
951 isl_map_free(map);
952 return NULL;
955 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
956 __isl_take isl_basic_set *bset,
957 enum isl_dim_type type, unsigned pos, const char *s)
959 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
960 type, pos, s));
963 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
964 enum isl_dim_type type, unsigned pos, const char *s)
966 return set_from_map(isl_map_set_dim_name(set_to_map(set),
967 type, pos, s));
970 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
971 enum isl_dim_type type, unsigned pos)
973 if (!bmap)
974 return isl_bool_error;
975 return isl_space_has_dim_id(bmap->dim, type, pos);
978 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
979 enum isl_dim_type type, unsigned pos)
981 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
984 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
985 enum isl_dim_type type, unsigned pos)
987 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
990 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
991 enum isl_dim_type type, unsigned pos)
993 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
996 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
997 enum isl_dim_type type, unsigned pos)
999 return isl_map_has_dim_id(set, type, pos);
1002 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
1003 enum isl_dim_type type, unsigned pos)
1005 return isl_map_get_dim_id(set, type, pos);
1008 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
1009 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
1011 isl_space *space;
1013 space = isl_map_take_space(map);
1014 space = isl_space_set_dim_id(space, type, pos, id);
1015 map = isl_map_restore_space(map, space);
1017 return isl_map_reset_space(map, isl_map_get_space(map));
1020 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
1021 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
1023 return isl_map_set_dim_id(set, type, pos, id);
1026 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
1027 __isl_keep isl_id *id)
1029 if (!map)
1030 return -1;
1031 return isl_space_find_dim_by_id(map->dim, type, id);
1034 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
1035 __isl_keep isl_id *id)
1037 return isl_map_find_dim_by_id(set, type, id);
1040 /* Return the position of the dimension of the given type and name
1041 * in "bmap".
1042 * Return -1 if no such dimension can be found.
1044 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
1045 enum isl_dim_type type, const char *name)
1047 if (!bmap)
1048 return -1;
1049 return isl_space_find_dim_by_name(bmap->dim, type, name);
1052 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
1053 const char *name)
1055 if (!map)
1056 return -1;
1057 return isl_space_find_dim_by_name(map->dim, type, name);
1060 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
1061 const char *name)
1063 return isl_map_find_dim_by_name(set, type, name);
1066 /* Check whether equality i of bset is a pure stride constraint
1067 * on a single dimension, i.e., of the form
1069 * v = k e
1071 * with k a constant and e an existentially quantified variable.
1073 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
1075 isl_size nparam;
1076 isl_size d;
1077 isl_size n_div;
1078 int pos1;
1079 int pos2;
1081 nparam = isl_basic_set_dim(bset, isl_dim_param);
1082 d = isl_basic_set_dim(bset, isl_dim_set);
1083 n_div = isl_basic_set_dim(bset, isl_dim_div);
1084 if (nparam < 0 || d < 0 || n_div < 0)
1085 return isl_bool_error;
1087 if (!isl_int_is_zero(bset->eq[i][0]))
1088 return isl_bool_false;
1090 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
1091 return isl_bool_false;
1092 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
1093 if (pos1 == -1)
1094 return isl_bool_false;
1095 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
1096 d - pos1 - 1) != -1)
1097 return isl_bool_false;
1099 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
1100 if (pos2 == -1)
1101 return isl_bool_false;
1102 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
1103 n_div - pos2 - 1) != -1)
1104 return isl_bool_false;
1105 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
1106 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
1107 return isl_bool_false;
1109 return isl_bool_true;
1112 /* Reset the user pointer on all identifiers of parameters and tuples
1113 * of the space of "map".
1115 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
1117 isl_space *space;
1119 space = isl_map_get_space(map);
1120 space = isl_space_reset_user(space);
1121 map = isl_map_reset_space(map, space);
1123 return map;
1126 /* Reset the user pointer on all identifiers of parameters and tuples
1127 * of the space of "set".
1129 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
1131 return isl_map_reset_user(set);
1134 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
1136 if (!bmap)
1137 return isl_bool_error;
1138 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
1141 /* Has "map" been marked as a rational map?
1142 * In particular, have all basic maps in "map" been marked this way?
1143 * An empty map is not considered to be rational.
1144 * Maps where only some of the basic maps are marked rational
1145 * are not allowed.
1147 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
1149 int i;
1150 isl_bool rational;
1152 if (!map)
1153 return isl_bool_error;
1154 if (map->n == 0)
1155 return isl_bool_false;
1156 rational = isl_basic_map_is_rational(map->p[0]);
1157 if (rational < 0)
1158 return rational;
1159 for (i = 1; i < map->n; ++i) {
1160 isl_bool rational_i;
1162 rational_i = isl_basic_map_is_rational(map->p[i]);
1163 if (rational_i < 0)
1164 return rational_i;
1165 if (rational != rational_i)
1166 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1167 "mixed rational and integer basic maps "
1168 "not supported", return isl_bool_error);
1171 return rational;
1174 /* Has "set" been marked as a rational set?
1175 * In particular, have all basic set in "set" been marked this way?
1176 * An empty set is not considered to be rational.
1177 * Sets where only some of the basic sets are marked rational
1178 * are not allowed.
1180 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1182 return isl_map_is_rational(set);
1185 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1187 return isl_basic_map_is_rational(bset);
1190 /* Does "bmap" contain any rational points?
1192 * If "bmap" has an equality for each dimension, equating the dimension
1193 * to an integer constant, then it has no rational points, even if it
1194 * is marked as rational.
1196 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1198 isl_bool has_rational = isl_bool_true;
1199 isl_size total;
1201 if (!bmap)
1202 return isl_bool_error;
1203 if (isl_basic_map_plain_is_empty(bmap))
1204 return isl_bool_false;
1205 if (!isl_basic_map_is_rational(bmap))
1206 return isl_bool_false;
1207 bmap = isl_basic_map_copy(bmap);
1208 bmap = isl_basic_map_implicit_equalities(bmap);
1209 total = isl_basic_map_dim(bmap, isl_dim_all);
1210 if (total < 0)
1211 return isl_bool_error;
1212 if (bmap->n_eq == total) {
1213 int i, j;
1214 for (i = 0; i < bmap->n_eq; ++i) {
1215 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1216 if (j < 0)
1217 break;
1218 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1219 !isl_int_is_negone(bmap->eq[i][1 + j]))
1220 break;
1221 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1222 total - j - 1);
1223 if (j >= 0)
1224 break;
1226 if (i == bmap->n_eq)
1227 has_rational = isl_bool_false;
1229 isl_basic_map_free(bmap);
1231 return has_rational;
1234 /* Does "map" contain any rational points?
1236 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1238 int i;
1239 isl_bool has_rational;
1241 if (!map)
1242 return isl_bool_error;
1243 for (i = 0; i < map->n; ++i) {
1244 has_rational = isl_basic_map_has_rational(map->p[i]);
1245 if (has_rational < 0 || has_rational)
1246 return has_rational;
1248 return isl_bool_false;
1251 /* Does "set" contain any rational points?
1253 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1255 return isl_map_has_rational(set);
1258 /* Is this basic set a parameter domain?
1260 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1262 if (!bset)
1263 return isl_bool_error;
1264 return isl_space_is_params(bset->dim);
1267 /* Is this set a parameter domain?
1269 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1271 if (!set)
1272 return isl_bool_error;
1273 return isl_space_is_params(set->dim);
1276 /* Is this map actually a parameter domain?
1277 * Users should never call this function. Outside of isl,
1278 * a map can never be a parameter domain.
1280 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1282 if (!map)
1283 return isl_bool_error;
1284 return isl_space_is_params(map->dim);
1287 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1288 __isl_take isl_basic_map *bmap, unsigned extra,
1289 unsigned n_eq, unsigned n_ineq)
1291 int i;
1292 isl_space *space = isl_basic_map_peek_space(bmap);
1293 isl_size n_var = isl_space_dim(space, isl_dim_all);
1294 size_t row_size = 1 + n_var + extra;
1296 bmap->ctx = ctx;
1297 isl_ctx_ref(ctx);
1299 if (n_var < 0)
1300 return isl_basic_map_free(bmap);
1302 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1303 if (isl_blk_is_error(bmap->block))
1304 goto error;
1306 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1307 if ((n_ineq + n_eq) && !bmap->ineq)
1308 goto error;
1310 if (extra == 0) {
1311 bmap->block2 = isl_blk_empty();
1312 bmap->div = NULL;
1313 } else {
1314 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1315 if (isl_blk_is_error(bmap->block2))
1316 goto error;
1318 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1319 if (!bmap->div)
1320 goto error;
1323 for (i = 0; i < n_ineq + n_eq; ++i)
1324 bmap->ineq[i] = bmap->block.data + i * row_size;
1326 for (i = 0; i < extra; ++i)
1327 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1329 bmap->ref = 1;
1330 bmap->flags = 0;
1331 bmap->c_size = n_eq + n_ineq;
1332 bmap->eq = bmap->ineq + n_ineq;
1333 bmap->extra = extra;
1334 bmap->n_eq = 0;
1335 bmap->n_ineq = 0;
1336 bmap->n_div = 0;
1337 bmap->sample = NULL;
1339 return bmap;
1340 error:
1341 isl_basic_map_free(bmap);
1342 return NULL;
1345 __isl_give isl_basic_set *isl_basic_set_alloc(isl_ctx *ctx,
1346 unsigned nparam, unsigned dim, unsigned extra,
1347 unsigned n_eq, unsigned n_ineq)
1349 struct isl_basic_map *bmap;
1350 isl_space *space;
1352 space = isl_space_set_alloc(ctx, nparam, dim);
1353 if (!space)
1354 return NULL;
1356 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1357 return bset_from_bmap(bmap);
1360 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *space,
1361 unsigned extra, unsigned n_eq, unsigned n_ineq)
1363 struct isl_basic_map *bmap;
1364 if (!space)
1365 return NULL;
1366 isl_assert(space->ctx, space->n_in == 0, goto error);
1367 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1368 return bset_from_bmap(bmap);
1369 error:
1370 isl_space_free(space);
1371 return NULL;
1374 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1375 unsigned extra, unsigned n_eq, unsigned n_ineq)
1377 struct isl_basic_map *bmap;
1379 if (!space)
1380 return NULL;
1381 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1382 if (!bmap)
1383 goto error;
1384 bmap->dim = space;
1386 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1387 error:
1388 isl_space_free(space);
1389 return NULL;
1392 __isl_give isl_basic_map *isl_basic_map_alloc(isl_ctx *ctx,
1393 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1394 unsigned n_eq, unsigned n_ineq)
1396 struct isl_basic_map *bmap;
1397 isl_space *space;
1399 space = isl_space_alloc(ctx, nparam, in, out);
1400 if (!space)
1401 return NULL;
1403 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1404 return bmap;
1407 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1408 __isl_keep isl_basic_map *src)
1410 int i;
1411 isl_size total = isl_basic_map_dim(src, isl_dim_all);
1413 if (!dst || total < 0)
1414 return isl_basic_map_free(dst);
1416 for (i = 0; i < src->n_eq; ++i) {
1417 int j = isl_basic_map_alloc_equality(dst);
1418 if (j < 0)
1419 return isl_basic_map_free(dst);
1420 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1423 for (i = 0; i < src->n_ineq; ++i) {
1424 int j = isl_basic_map_alloc_inequality(dst);
1425 if (j < 0)
1426 return isl_basic_map_free(dst);
1427 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1430 for (i = 0; i < src->n_div; ++i) {
1431 int j = isl_basic_map_alloc_div(dst);
1432 if (j < 0)
1433 return isl_basic_map_free(dst);
1434 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1436 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1437 return dst;
1440 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1442 struct isl_basic_map *dup;
1444 if (!bmap)
1445 return NULL;
1446 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1447 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1448 dup = dup_constraints(dup, bmap);
1449 if (!dup)
1450 return NULL;
1451 dup->flags = bmap->flags;
1452 dup->sample = isl_vec_copy(bmap->sample);
1453 return dup;
1456 __isl_give isl_basic_set *isl_basic_set_dup(__isl_keep isl_basic_set *bset)
1458 struct isl_basic_map *dup;
1460 dup = isl_basic_map_dup(bset_to_bmap(bset));
1461 return bset_from_bmap(dup);
1464 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1466 return bset_from_bmap(isl_basic_map_copy(bset_to_bmap(bset)));
1469 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1471 if (!set)
1472 return NULL;
1474 set->ref++;
1475 return set;
1478 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1480 if (!bmap)
1481 return NULL;
1483 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1484 bmap->ref++;
1485 return bmap;
1487 bmap = isl_basic_map_dup(bmap);
1488 if (bmap)
1489 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1490 return bmap;
1493 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1495 if (!map)
1496 return NULL;
1498 map->ref++;
1499 return map;
1502 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1504 if (!bmap)
1505 return NULL;
1507 if (--bmap->ref > 0)
1508 return NULL;
1510 isl_ctx_deref(bmap->ctx);
1511 free(bmap->div);
1512 isl_blk_free(bmap->ctx, bmap->block2);
1513 free(bmap->ineq);
1514 isl_blk_free(bmap->ctx, bmap->block);
1515 isl_vec_free(bmap->sample);
1516 isl_space_free(bmap->dim);
1517 free(bmap);
1519 return NULL;
1522 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1524 return isl_basic_map_free(bset_to_bmap(bset));
1527 static int room_for_con(__isl_keep isl_basic_map *bmap, unsigned n)
1529 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1532 /* Check that "bset" does not involve any parameters.
1534 isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1536 isl_size nparam;
1538 nparam = isl_basic_set_dim(bset, isl_dim_param);
1539 if (nparam < 0)
1540 return isl_stat_error;
1541 if (nparam != 0)
1542 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1543 "basic set should not have any parameters",
1544 return isl_stat_error);
1545 return isl_stat_ok;
1548 /* Check that "bset" does not involve any local variables.
1550 isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1552 isl_size n_div;
1554 n_div = isl_basic_set_dim(bset, isl_dim_div);
1555 if (n_div < 0)
1556 return isl_stat_error;
1557 if (n_div != 0)
1558 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1559 "basic set should not have any local variables",
1560 return isl_stat_error);
1561 return isl_stat_ok;
1564 #undef TYPE
1565 #define TYPE isl_map
1567 #include "isl_check_named_params_templ.c"
1569 #undef TYPE
1570 #define TYPE isl_basic_map
1572 static
1573 #include "isl_check_named_params_templ.c"
1575 /* Check that "bmap1" and "bmap2" have the same parameters,
1576 * reporting an error if they do not.
1578 static isl_stat isl_basic_map_check_equal_params(
1579 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1581 isl_bool match;
1583 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1584 if (match < 0)
1585 return isl_stat_error;
1586 if (!match)
1587 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1588 "parameters don't match", return isl_stat_error);
1589 return isl_stat_ok;
1592 #undef TYPE
1593 #define TYPE isl_map
1595 #include "isl_align_params_bin_templ.c"
1597 #undef SUFFIX
1598 #define SUFFIX set
1599 #undef ARG1
1600 #define ARG1 isl_map
1601 #undef ARG2
1602 #define ARG2 isl_set
1604 #include "isl_align_params_templ.c"
1606 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1607 __isl_keep isl_map *map2,
1608 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1610 isl_bool r;
1612 if (!map1 || !map2)
1613 return isl_bool_error;
1614 if (isl_map_has_equal_params(map1, map2))
1615 return fn(map1, map2);
1616 if (isl_map_check_named_params(map1) < 0)
1617 return isl_bool_error;
1618 if (isl_map_check_named_params(map2) < 0)
1619 return isl_bool_error;
1620 map1 = isl_map_copy(map1);
1621 map2 = isl_map_copy(map2);
1622 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1623 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1624 r = fn(map1, map2);
1625 isl_map_free(map1);
1626 isl_map_free(map2);
1627 return r;
1630 int isl_basic_map_alloc_equality(__isl_keep isl_basic_map *bmap)
1632 isl_size total;
1633 struct isl_ctx *ctx;
1635 total = isl_basic_map_dim(bmap, isl_dim_all);
1636 if (total < 0)
1637 return -1;
1638 ctx = bmap->ctx;
1639 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1640 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1641 return -1);
1642 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1643 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1644 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1645 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1646 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1647 isl_int *t;
1648 int j = isl_basic_map_alloc_inequality(bmap);
1649 if (j < 0)
1650 return -1;
1651 t = bmap->ineq[j];
1652 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1653 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1654 bmap->eq[-1] = t;
1655 bmap->n_eq++;
1656 bmap->n_ineq--;
1657 bmap->eq--;
1658 return 0;
1660 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + total,
1661 bmap->extra - bmap->n_div);
1662 return bmap->n_eq++;
1665 int isl_basic_set_alloc_equality(__isl_keep isl_basic_set *bset)
1667 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1670 __isl_give isl_basic_map *isl_basic_map_free_equality(
1671 __isl_take isl_basic_map *bmap, unsigned n)
1673 if (!bmap)
1674 return NULL;
1675 if (n > bmap->n_eq)
1676 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1677 "invalid number of equalities",
1678 isl_basic_map_free(bmap));
1679 bmap->n_eq -= n;
1680 return bmap;
1683 __isl_give isl_basic_set *isl_basic_set_free_equality(
1684 __isl_take isl_basic_set *bset, unsigned n)
1686 return bset_from_bmap(isl_basic_map_free_equality(bset_to_bmap(bset),
1687 n));
1690 /* Drop the equality constraint at position "pos",
1691 * preserving the order of the other equality constraints.
1693 int isl_basic_map_drop_equality(__isl_keep isl_basic_map *bmap, unsigned pos)
1695 isl_int *t;
1696 int r;
1698 if (!bmap)
1699 return -1;
1700 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1702 t = bmap->eq[pos];
1703 bmap->n_eq--;
1704 for (r = pos; r < bmap->n_eq; ++r)
1705 bmap->eq[r] = bmap->eq[r + 1];
1706 bmap->eq[bmap->n_eq] = t;
1708 return 0;
1711 /* Turn inequality "pos" of "bmap" into an equality.
1713 * In particular, we move the inequality in front of the equalities
1714 * and move the last inequality in the position of the moved inequality.
1715 * Note that isl_tab_make_equalities_explicit depends on this particular
1716 * change in the ordering of the constraints.
1718 void isl_basic_map_inequality_to_equality(
1719 __isl_keep isl_basic_map *bmap, unsigned pos)
1721 isl_int *t;
1723 t = bmap->ineq[pos];
1724 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1725 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1726 bmap->eq[-1] = t;
1727 bmap->n_eq++;
1728 bmap->n_ineq--;
1729 bmap->eq--;
1730 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1731 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1732 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1733 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1736 static int room_for_ineq(__isl_keep isl_basic_map *bmap, unsigned n)
1738 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1741 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1743 isl_size total;
1744 struct isl_ctx *ctx;
1746 total = isl_basic_map_dim(bmap, isl_dim_all);
1747 if (total < 0)
1748 return -1;
1749 ctx = bmap->ctx;
1750 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1751 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1752 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1753 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1754 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1755 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1756 isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1 + total,
1757 bmap->extra - bmap->n_div);
1758 return bmap->n_ineq++;
1761 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1763 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1766 __isl_give isl_basic_map *isl_basic_map_free_inequality(
1767 __isl_take isl_basic_map *bmap, unsigned n)
1769 if (!bmap)
1770 return NULL;
1771 if (n > bmap->n_ineq)
1772 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1773 "invalid number of inequalities",
1774 return isl_basic_map_free(bmap));
1775 bmap->n_ineq -= n;
1776 return bmap;
1779 __isl_give isl_basic_set *isl_basic_set_free_inequality(
1780 __isl_take isl_basic_set *bset, unsigned n)
1782 return bset_from_bmap(isl_basic_map_free_inequality(bset_to_bmap(bset),
1783 n));
1786 int isl_basic_map_drop_inequality(__isl_keep isl_basic_map *bmap, unsigned pos)
1788 isl_int *t;
1789 if (!bmap)
1790 return -1;
1791 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1793 if (pos != bmap->n_ineq - 1) {
1794 t = bmap->ineq[pos];
1795 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1796 bmap->ineq[bmap->n_ineq - 1] = t;
1797 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1799 bmap->n_ineq--;
1800 return 0;
1803 int isl_basic_set_drop_inequality(__isl_keep isl_basic_set *bset, unsigned pos)
1805 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1808 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1809 isl_int *eq)
1811 isl_bool empty;
1812 isl_size total;
1813 int k;
1815 empty = isl_basic_map_plain_is_empty(bmap);
1816 if (empty < 0)
1817 return isl_basic_map_free(bmap);
1818 if (empty)
1819 return bmap;
1821 bmap = isl_basic_map_cow(bmap);
1822 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1823 total = isl_basic_map_dim(bmap, isl_dim_all);
1824 if (total < 0)
1825 return isl_basic_map_free(bmap);
1826 k = isl_basic_map_alloc_equality(bmap);
1827 if (k < 0)
1828 goto error;
1829 isl_seq_cpy(bmap->eq[k], eq, 1 + total);
1830 return bmap;
1831 error:
1832 isl_basic_map_free(bmap);
1833 return NULL;
1836 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1837 isl_int *eq)
1839 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1842 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1843 isl_int *ineq)
1845 isl_size total;
1846 int k;
1848 bmap = isl_basic_map_cow(bmap);
1849 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1850 total = isl_basic_map_dim(bmap, isl_dim_all);
1851 if (total < 0)
1852 return isl_basic_map_free(bmap);
1853 k = isl_basic_map_alloc_inequality(bmap);
1854 if (k < 0)
1855 goto error;
1856 isl_seq_cpy(bmap->ineq[k], ineq, 1 + total);
1857 return bmap;
1858 error:
1859 isl_basic_map_free(bmap);
1860 return NULL;
1863 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1864 isl_int *ineq)
1866 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1869 int isl_basic_map_alloc_div(__isl_keep isl_basic_map *bmap)
1871 isl_size total;
1873 total = isl_basic_map_dim(bmap, isl_dim_all);
1874 if (total < 0)
1875 return -1;
1876 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1877 isl_seq_clr(bmap->div[bmap->n_div] + 1 + 1 + total,
1878 bmap->extra - bmap->n_div);
1879 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1880 return bmap->n_div++;
1883 int isl_basic_set_alloc_div(__isl_keep isl_basic_set *bset)
1885 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1888 #undef TYPE
1889 #define TYPE isl_basic_map
1890 #include "check_type_range_templ.c"
1892 /* Check that there are "n" dimensions of type "type" starting at "first"
1893 * in "bset".
1895 isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1896 enum isl_dim_type type, unsigned first, unsigned n)
1898 return isl_basic_map_check_range(bset_to_bmap(bset),
1899 type, first, n);
1902 /* Insert an extra integer division, prescribed by "div", to "bmap"
1903 * at (integer division) position "pos".
1905 * The integer division is first added at the end and then moved
1906 * into the right position.
1908 __isl_give isl_basic_map *isl_basic_map_insert_div(
1909 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1911 int i, k;
1912 isl_size total;
1914 bmap = isl_basic_map_cow(bmap);
1915 total = isl_basic_map_dim(bmap, isl_dim_all);
1916 if (total < 0 || !div)
1917 return isl_basic_map_free(bmap);
1919 if (div->size != 1 + 1 + total)
1920 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1921 "unexpected size", return isl_basic_map_free(bmap));
1922 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1923 return isl_basic_map_free(bmap);
1925 bmap = isl_basic_map_extend(bmap, 1, 0, 2);
1926 k = isl_basic_map_alloc_div(bmap);
1927 if (k < 0)
1928 return isl_basic_map_free(bmap);
1929 isl_seq_cpy(bmap->div[k], div->el, div->size);
1930 isl_int_set_si(bmap->div[k][div->size], 0);
1932 for (i = k; i > pos; --i)
1933 bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1935 return bmap;
1938 isl_stat isl_basic_map_free_div(__isl_keep isl_basic_map *bmap, unsigned n)
1940 if (!bmap)
1941 return isl_stat_error;
1942 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1943 bmap->n_div -= n;
1944 return isl_stat_ok;
1947 static __isl_give isl_basic_map *add_constraints(
1948 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1949 unsigned i_pos, unsigned o_pos)
1951 isl_size total, n_param, n_in, n_out, n_div;
1952 unsigned o_in, o_out;
1953 isl_ctx *ctx;
1954 isl_space *space;
1955 struct isl_dim_map *dim_map;
1957 space = isl_basic_map_peek_space(bmap2);
1958 if (!bmap1 || !space)
1959 goto error;
1961 total = isl_basic_map_dim(bmap1, isl_dim_all);
1962 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1963 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1964 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1965 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1966 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1967 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1968 if (total < 0 || n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
1969 goto error;
1970 ctx = isl_basic_map_get_ctx(bmap1);
1971 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1972 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1973 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1974 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1975 isl_dim_map_div(dim_map, bmap2, total);
1977 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1978 error:
1979 isl_basic_map_free(bmap1);
1980 isl_basic_map_free(bmap2);
1981 return NULL;
1984 __isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
1985 unsigned extra, unsigned n_eq, unsigned n_ineq)
1987 isl_space *space;
1988 struct isl_basic_map *ext;
1989 unsigned flags;
1990 int dims_ok;
1992 if (!base)
1993 goto error;
1995 dims_ok = base->extra >= base->n_div + extra;
1997 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1998 room_for_ineq(base, n_ineq))
1999 return base;
2001 extra += base->extra;
2002 n_eq += base->n_eq;
2003 n_ineq += base->n_ineq;
2005 space = isl_basic_map_get_space(base);
2006 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
2007 if (!ext)
2008 goto error;
2010 if (dims_ok)
2011 ext->sample = isl_vec_copy(base->sample);
2012 flags = base->flags;
2013 ext = add_constraints(ext, base, 0, 0);
2014 if (ext) {
2015 ext->flags = flags;
2016 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
2019 return ext;
2021 error:
2022 isl_basic_map_free(base);
2023 return NULL;
2026 __isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,
2027 unsigned extra, unsigned n_eq, unsigned n_ineq)
2029 return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
2030 extra, n_eq, n_ineq));
2033 __isl_give isl_basic_map *isl_basic_map_extend_constraints(
2034 __isl_take isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
2036 return isl_basic_map_extend(base, 0, n_eq, n_ineq);
2039 __isl_give isl_basic_set *isl_basic_set_extend_constraints(
2040 __isl_take isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
2042 isl_basic_map *bmap = bset_to_bmap(base);
2043 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
2044 return bset_from_bmap(bmap);
2047 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
2049 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
2052 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
2054 if (!bmap)
2055 return NULL;
2057 if (bmap->ref > 1) {
2058 bmap->ref--;
2059 bmap = isl_basic_map_dup(bmap);
2061 if (bmap)
2062 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
2063 return bmap;
2066 /* Clear all cached information in "map", either because it is about
2067 * to be modified or because it is being freed.
2068 * Always return the same pointer that is passed in.
2069 * This is needed for the use in isl_map_free.
2071 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
2073 isl_basic_map_free(map->cached_simple_hull[0]);
2074 isl_basic_map_free(map->cached_simple_hull[1]);
2075 map->cached_simple_hull[0] = NULL;
2076 map->cached_simple_hull[1] = NULL;
2077 return map;
2080 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
2082 return isl_map_cow(set);
2085 /* Return an isl_map that is equal to "map" and that has only
2086 * a single reference.
2088 * If the original input already has only one reference, then
2089 * simply return it, but clear all cached information, since
2090 * it may be rendered invalid by the operations that will be
2091 * performed on the result.
2093 * Otherwise, create a duplicate (without any cached information).
2095 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
2097 if (!map)
2098 return NULL;
2100 if (map->ref == 1)
2101 return clear_caches(map);
2102 map->ref--;
2103 return isl_map_dup(map);
2106 static void swap_vars(struct isl_blk blk, isl_int *a,
2107 unsigned a_len, unsigned b_len)
2109 isl_seq_cpy(blk.data, a+a_len, b_len);
2110 isl_seq_cpy(blk.data+b_len, a, a_len);
2111 isl_seq_cpy(a, blk.data, b_len+a_len);
2114 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
2115 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
2117 int i;
2118 struct isl_blk blk;
2120 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
2121 goto error;
2123 if (n1 == 0 || n2 == 0)
2124 return bmap;
2126 bmap = isl_basic_map_cow(bmap);
2127 if (!bmap)
2128 return NULL;
2130 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2131 if (isl_blk_is_error(blk))
2132 goto error;
2134 for (i = 0; i < bmap->n_eq; ++i)
2135 swap_vars(blk,
2136 bmap->eq[i] + pos, n1, n2);
2138 for (i = 0; i < bmap->n_ineq; ++i)
2139 swap_vars(blk,
2140 bmap->ineq[i] + pos, n1, n2);
2142 for (i = 0; i < bmap->n_div; ++i)
2143 swap_vars(blk,
2144 bmap->div[i]+1 + pos, n1, n2);
2146 isl_blk_free(bmap->ctx, blk);
2148 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2149 bmap = isl_basic_map_gauss(bmap, NULL);
2150 return isl_basic_map_finalize(bmap);
2151 error:
2152 isl_basic_map_free(bmap);
2153 return NULL;
2156 /* The given basic map has turned out to be empty.
2157 * Explicitly mark it as such and change the representation
2158 * to a canonical representation of the empty basic map.
2159 * Since the basic map has conflicting constraints,
2160 * it must have at least one constraint, except perhaps
2161 * if it was already explicitly marked as being empty.
2162 * Do nothing in the latter case, i.e., if it has been marked empty and
2163 * has no constraints.
2165 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2166 __isl_take isl_basic_map *bmap)
2168 int i = 0;
2169 isl_bool empty;
2170 isl_size n;
2171 isl_size total;
2173 n = isl_basic_map_n_constraint(bmap);
2174 empty = isl_basic_map_plain_is_empty(bmap);
2175 if (n < 0 || empty < 0)
2176 return isl_basic_map_free(bmap);
2177 if (n == 0 && empty)
2178 return bmap;
2179 total = isl_basic_map_dim(bmap, isl_dim_all);
2180 if (total < 0)
2181 return isl_basic_map_free(bmap);
2182 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2183 return isl_basic_map_free(bmap);
2184 bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2185 if (!bmap)
2186 return NULL;
2187 if (bmap->n_eq > 0) {
2188 bmap = isl_basic_map_free_equality(bmap, bmap->n_eq - 1);
2189 if (!bmap)
2190 return NULL;
2191 } else {
2192 i = isl_basic_map_alloc_equality(bmap);
2193 if (i < 0)
2194 goto error;
2196 isl_int_set_si(bmap->eq[i][0], 1);
2197 isl_seq_clr(bmap->eq[i]+1, total);
2198 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2199 isl_vec_free(bmap->sample);
2200 bmap->sample = NULL;
2201 return isl_basic_map_finalize(bmap);
2202 error:
2203 isl_basic_map_free(bmap);
2204 return NULL;
2207 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2208 __isl_take isl_basic_set *bset)
2210 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2213 __isl_give isl_basic_map *isl_basic_map_set_rational(
2214 __isl_take isl_basic_map *bmap)
2216 if (!bmap)
2217 return NULL;
2219 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2220 return bmap;
2222 bmap = isl_basic_map_cow(bmap);
2223 if (!bmap)
2224 return NULL;
2226 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2228 return isl_basic_map_finalize(bmap);
2231 __isl_give isl_basic_set *isl_basic_set_set_rational(
2232 __isl_take isl_basic_set *bset)
2234 return isl_basic_map_set_rational(bset);
2237 __isl_give isl_basic_set *isl_basic_set_set_integral(
2238 __isl_take isl_basic_set *bset)
2240 if (!bset)
2241 return NULL;
2243 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2244 return bset;
2246 bset = isl_basic_set_cow(bset);
2247 if (!bset)
2248 return NULL;
2250 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2252 return isl_basic_set_finalize(bset);
2255 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2257 int i;
2259 map = isl_map_cow(map);
2260 if (!map)
2261 return NULL;
2262 for (i = 0; i < map->n; ++i) {
2263 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2264 if (!map->p[i])
2265 goto error;
2267 return map;
2268 error:
2269 isl_map_free(map);
2270 return NULL;
2273 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2275 return isl_map_set_rational(set);
2278 /* Given a constraint "c" that expresses a bound
2279 * on the variable at position "pos" in terms of the first "len" variables
2280 * (other than the variable itself if pos < len), extract this bound
2281 * as a function of those first "len" variables.
2283 * That is, the constraint is of one of the following forms
2285 * -e(...) + m x >= 0
2286 * e(...) - m x >= 0
2287 * -e(...) + m x = 0
2288 * e(...) - m x = 0
2290 * Return (e(...)) / m, with the denominator m in the first position.
2292 static __isl_give isl_vec *extract_bound_from_constraint(isl_ctx *ctx,
2293 isl_int *c, int len, int pos)
2295 isl_vec *v;
2297 v = isl_vec_alloc(ctx, 1 + 1 + len);
2298 if (!v)
2299 return NULL;
2300 if (isl_int_is_pos(c[1 + pos])) {
2301 isl_int_set(v->el[0], c[1 + pos]);
2302 isl_seq_neg(v->el + 1, c, 1 + len);
2303 } else {
2304 isl_int_neg(v->el[0], c[1 + pos]);
2305 isl_seq_cpy(v->el + 1, c, 1 + len);
2307 if (pos < len)
2308 isl_int_set_si(v->el[1 + 1 + pos], 0);
2310 return v;
2313 /* Return the position of the last non-zero coefficient of
2314 * inequality constraint "ineq" of "bmap" or length "len",
2315 * given that the coefficient at position "first" is non-zero,
2316 * or that it is known that there is at least one coefficient
2317 * after "first" that is non-zero.
2319 static int extend_last_non_zero(__isl_keep isl_basic_map *bmap, int ineq,
2320 int first, unsigned len)
2322 int last;
2324 last = isl_seq_last_non_zero(bmap->ineq[ineq] + 1 + first + 1,
2325 len - (first + 1));
2326 if (last < 0)
2327 return first;
2328 else
2329 return first + 1 + last;
2332 /* Do the inequality constraints "i" and "j" of "bmap"
2333 * form a pair of opposite constraints, in the (first) "len" coefficients?
2335 static int is_constraint_pair(__isl_keep isl_basic_map *bmap, int i, int j,
2336 unsigned len)
2338 return isl_seq_is_neg(bmap->ineq[i] + 1, bmap->ineq[j] + 1, len);
2341 /* Given that inequality constraints "i" and "j" of "bmap"
2342 * form a pair of opposite constraints
2344 * f(x) + c1 >= 0
2345 * -f(x) + c2 >= 0
2347 * or
2349 * -c1 <= f(x) <= c2
2351 * do they allow for at most "bound" values in that direction?
2352 * That is, is the sum of their constant terms smaller than "bound"?
2354 * "tmp" is a temporary location that can be used to store the sum.
2356 static int constraint_pair_has_bound(__isl_keep isl_basic_map *bmap,
2357 int i, int j, isl_int bound, isl_int *tmp)
2359 isl_int_add(*tmp, bmap->ineq[i][0], bmap->ineq[j][0]);
2360 return isl_int_abs_lt(*tmp, bound);
2363 /* Return the position of an inequality constraint in "bmap"
2364 * that together with inequality constraint "ineq" forms
2365 * a pair of opposite constraints that allow at most "bound" values
2366 * in their shared direction and that appears after "ineq".
2367 * Return a position beyond the number of inequality constraints
2368 * if no such constraint can be found.
2370 * The constraints of "bmap" are assumed to have been sorted.
2371 * This means that as soon as a constraint is found where the value
2372 * of the last coefficient (in absolute value) is different from that of "ineq",
2373 * no opposite constraint can be found.
2374 * It also means that only the coefficients up to this last coefficient
2375 * need to be compared.
2377 * "pos" is the position of a coefficient that is known to be non-zero.
2378 * If no such position is known a priori, then the value 0 can be passed in.
2379 * "len" is the number of (relevant) coefficients in the constraints.
2380 * "tmp" is a temporary location that can be used to store the sum.
2382 static isl_size find_later_constraint_in_pair(__isl_keep isl_basic_map *bmap,
2383 int ineq, int pos, int len, isl_int bound, isl_int *tmp)
2385 int j;
2386 int last;
2387 isl_size n_ineq;
2389 n_ineq = isl_basic_map_n_inequality(bmap);
2390 if (n_ineq < 0)
2391 return isl_size_error;
2393 last = extend_last_non_zero(bmap, ineq, pos, len);
2395 for (j = ineq + 1; j < n_ineq; ++j) {
2396 if (!isl_int_abs_eq(bmap->ineq[ineq][1 + last],
2397 bmap->ineq[j][1 + last]))
2398 return n_ineq;
2399 if (isl_seq_last_non_zero(bmap->ineq[j] + 1 + last + 1,
2400 len - (last + 1)) != -1)
2401 return n_ineq;
2402 if (!is_constraint_pair(bmap, ineq, j, last + 1))
2403 continue;
2404 if (constraint_pair_has_bound(bmap, ineq, j, bound, tmp))
2405 return j;
2406 return n_ineq;
2409 return n_ineq;
2412 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2413 * of "bmap").
2415 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2417 isl_int *t = bmap->div[a];
2418 bmap->div[a] = bmap->div[b];
2419 bmap->div[b] = t;
2422 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2423 * div definitions accordingly.
2425 __isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2426 int a, int b)
2428 int i;
2429 isl_size off;
2431 off = isl_basic_map_var_offset(bmap, isl_dim_div);
2432 if (off < 0)
2433 return isl_basic_map_free(bmap);
2435 swap_div(bmap, a, b);
2437 for (i = 0; i < bmap->n_eq; ++i)
2438 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2440 for (i = 0; i < bmap->n_ineq; ++i)
2441 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2443 for (i = 0; i < bmap->n_div; ++i)
2444 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2445 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2447 return bmap;
2450 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2452 isl_seq_cpy(c, c + n, rem);
2453 isl_seq_clr(c + rem, n);
2456 /* Drop n dimensions starting at first.
2458 * In principle, this frees up some extra variables as the number
2459 * of columns remains constant, but we would have to extend
2460 * the div array too as the number of rows in this array is assumed
2461 * to be equal to extra.
2463 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2464 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2466 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2469 /* Move "n" divs starting at "first" to the end of the list of divs.
2471 static __isl_give isl_basic_map *move_divs_last(__isl_take isl_basic_map *bmap,
2472 unsigned first, unsigned n)
2474 isl_int **div;
2475 int i;
2477 if (first + n == bmap->n_div)
2478 return bmap;
2480 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2481 if (!div)
2482 goto error;
2483 for (i = 0; i < n; ++i)
2484 div[i] = bmap->div[first + i];
2485 for (i = 0; i < bmap->n_div - first - n; ++i)
2486 bmap->div[first + i] = bmap->div[first + n + i];
2487 for (i = 0; i < n; ++i)
2488 bmap->div[bmap->n_div - n + i] = div[i];
2489 free(div);
2490 return bmap;
2491 error:
2492 isl_basic_map_free(bmap);
2493 return NULL;
2496 #undef TYPE
2497 #define TYPE isl_map
2498 static
2499 #include "check_type_range_templ.c"
2501 /* Check that there are "n" dimensions of type "type" starting at "first"
2502 * in "set".
2504 isl_stat isl_set_check_range(__isl_keep isl_set *set,
2505 enum isl_dim_type type, unsigned first, unsigned n)
2507 return isl_map_check_range(set_to_map(set), type, first, n);
2510 /* Drop "n" dimensions of type "type" starting at "first".
2511 * Perform the core computation, without cowing or
2512 * simplifying and finalizing the result.
2514 * In principle, this frees up some extra variables as the number
2515 * of columns remains constant, but we would have to extend
2516 * the div array too as the number of rows in this array is assumed
2517 * to be equal to extra.
2519 __isl_give isl_basic_map *isl_basic_map_drop_core(
2520 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2521 unsigned first, unsigned n)
2523 int i;
2524 unsigned offset;
2525 unsigned left;
2526 isl_size total;
2528 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2529 return isl_basic_map_free(bmap);
2531 total = isl_basic_map_dim(bmap, isl_dim_all);
2532 if (total < 0)
2533 return isl_basic_map_free(bmap);
2535 offset = isl_basic_map_offset(bmap, type) + first;
2536 left = total - (offset - 1) - n;
2537 for (i = 0; i < bmap->n_eq; ++i)
2538 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2540 for (i = 0; i < bmap->n_ineq; ++i)
2541 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2543 for (i = 0; i < bmap->n_div; ++i)
2544 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2546 if (type == isl_dim_div) {
2547 bmap = move_divs_last(bmap, first, n);
2548 if (!bmap)
2549 return NULL;
2550 if (isl_basic_map_free_div(bmap, n) < 0)
2551 return isl_basic_map_free(bmap);
2552 } else
2553 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2554 if (!bmap->dim)
2555 return isl_basic_map_free(bmap);
2557 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2558 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2559 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
2560 return bmap;
2563 /* Drop "n" dimensions of type "type" starting at "first".
2565 * In principle, this frees up some extra variables as the number
2566 * of columns remains constant, but we would have to extend
2567 * the div array too as the number of rows in this array is assumed
2568 * to be equal to extra.
2570 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2571 enum isl_dim_type type, unsigned first, unsigned n)
2573 if (!bmap)
2574 return NULL;
2575 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2576 return bmap;
2578 bmap = isl_basic_map_cow(bmap);
2579 if (!bmap)
2580 return NULL;
2582 bmap = isl_basic_map_drop_core(bmap, type, first, n);
2584 bmap = isl_basic_map_simplify(bmap);
2585 return isl_basic_map_finalize(bmap);
2588 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2589 enum isl_dim_type type, unsigned first, unsigned n)
2591 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2592 type, first, n));
2595 /* No longer consider "map" to be normalized.
2597 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2599 if (!map)
2600 return NULL;
2601 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2602 return map;
2605 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2606 enum isl_dim_type type, unsigned first, unsigned n)
2608 int i;
2609 isl_space *space;
2611 if (isl_map_check_range(map, type, first, n) < 0)
2612 return isl_map_free(map);
2614 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2615 return map;
2616 map = isl_map_cow(map);
2617 if (!map)
2618 goto error;
2620 for (i = 0; i < map->n; ++i) {
2621 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2622 if (!map->p[i])
2623 goto error;
2625 map = isl_map_unmark_normalized(map);
2627 space = isl_map_take_space(map);
2628 space = isl_space_drop_dims(space, type, first, n);
2629 map = isl_map_restore_space(map, space);
2631 return map;
2632 error:
2633 isl_map_free(map);
2634 return NULL;
2637 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2638 enum isl_dim_type type, unsigned first, unsigned n)
2640 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2643 /* Drop the integer division at position "div", which is assumed
2644 * not to appear in any of the constraints or
2645 * in any of the other integer divisions.
2647 * Since the integer division is redundant, there is no need to cow.
2649 __isl_give isl_basic_map *isl_basic_map_drop_div(
2650 __isl_take isl_basic_map *bmap, unsigned div)
2652 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2655 /* Eliminate the specified n dimensions starting at first from the
2656 * constraints, without removing the dimensions from the space.
2657 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2659 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2660 enum isl_dim_type type, unsigned first, unsigned n)
2662 int i;
2664 if (n == 0)
2665 return map;
2667 if (isl_map_check_range(map, type, first, n) < 0)
2668 return isl_map_free(map);
2670 map = isl_map_cow(map);
2671 if (!map)
2672 return NULL;
2674 for (i = 0; i < map->n; ++i) {
2675 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2676 if (!map->p[i])
2677 goto error;
2679 return map;
2680 error:
2681 isl_map_free(map);
2682 return NULL;
2685 /* Eliminate the specified n dimensions starting at first from the
2686 * constraints, without removing the dimensions from the space.
2687 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2689 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2690 enum isl_dim_type type, unsigned first, unsigned n)
2692 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2695 /* Eliminate the specified n dimensions starting at first from the
2696 * constraints, without removing the dimensions from the space.
2697 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2699 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2700 unsigned first, unsigned n)
2702 return isl_set_eliminate(set, isl_dim_set, first, n);
2705 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2706 __isl_take isl_basic_map *bmap)
2708 isl_size v_div;
2710 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2711 if (v_div < 0)
2712 return isl_basic_map_free(bmap);
2713 bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);
2714 if (!bmap)
2715 return NULL;
2716 bmap->n_div = 0;
2717 return isl_basic_map_finalize(bmap);
2720 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2721 __isl_take isl_basic_set *bset)
2723 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2726 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2728 int i;
2730 if (!map)
2731 return NULL;
2732 if (map->n == 0)
2733 return map;
2735 map = isl_map_cow(map);
2736 if (!map)
2737 return NULL;
2739 for (i = 0; i < map->n; ++i) {
2740 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2741 if (!map->p[i])
2742 goto error;
2744 return map;
2745 error:
2746 isl_map_free(map);
2747 return NULL;
2750 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2752 return isl_map_remove_divs(set);
2755 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2756 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2757 unsigned first, unsigned n)
2759 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2760 return isl_basic_map_free(bmap);
2761 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2762 return bmap;
2763 bmap = isl_basic_map_eliminate_vars(bmap,
2764 isl_basic_map_offset(bmap, type) - 1 + first, n);
2765 if (!bmap)
2766 return bmap;
2767 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2768 return bmap;
2769 bmap = isl_basic_map_drop(bmap, type, first, n);
2770 return bmap;
2773 /* Does the local variable "div" of "bmap" have a known expression
2774 * that involves the "n" variables starting at "first"?
2776 isl_bool isl_basic_map_div_expr_involves_vars(__isl_keep isl_basic_map *bmap,
2777 int div, unsigned first, unsigned n)
2779 isl_bool unknown;
2781 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
2782 if (unknown < 0 || unknown)
2783 return isl_bool_not(unknown);
2784 if (isl_seq_first_non_zero(bmap->div[div] + 1 + 1 + first, n) >= 0)
2785 return isl_bool_true;
2787 return isl_bool_false;
2790 /* Return true if the definition of the given div (recursively) involves
2791 * any of the given variables.
2793 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2794 unsigned first, unsigned n)
2796 int i;
2797 isl_bool involves;
2798 isl_size n_div, v_div;
2800 involves = isl_basic_map_div_expr_involves_vars(bmap, div, first, n);
2801 if (involves < 0 || involves)
2802 return involves;
2804 n_div = isl_basic_map_dim(bmap, isl_dim_div);
2805 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2806 if (n_div < 0 || v_div < 0)
2807 return isl_bool_error;
2808 for (i = n_div - 1; i >= 0; --i) {
2809 isl_bool involves;
2811 if (isl_int_is_zero(bmap->div[div][1 + 1 + v_div + i]))
2812 continue;
2813 involves = div_involves_vars(bmap, i, first, n);
2814 if (involves < 0 || involves)
2815 return involves;
2818 return isl_bool_false;
2821 /* Does the definition of any integer division involve
2822 * any of the given variables?
2824 isl_bool isl_basic_map_any_div_involves_vars(__isl_keep isl_basic_map *bmap,
2825 unsigned first, unsigned n)
2827 int i;
2828 isl_size n_div;
2830 n_div = isl_basic_map_dim(bmap, isl_dim_div);
2831 if (n_div < 0)
2832 return isl_bool_error;
2834 for (i = 0; i < n_div; ++i) {
2835 isl_bool has;
2837 has = isl_basic_map_div_expr_involves_vars(bmap, i, first, n);
2838 if (has < 0 || has)
2839 return has;
2842 return isl_bool_false;
2845 /* Try and add a lower and/or upper bound on "div" to "bmap"
2846 * based on inequality "i".
2847 * "total" is the total number of variables (excluding the divs).
2848 * "v" is a temporary object that can be used during the calculations.
2849 * If "lb" is set, then a lower bound should be constructed.
2850 * If "ub" is set, then an upper bound should be constructed.
2852 * The calling function has already checked that the inequality does not
2853 * reference "div", but we still need to check that the inequality is
2854 * of the right form. We'll consider the case where we want to construct
2855 * a lower bound. The construction of upper bounds is similar.
2857 * Let "div" be of the form
2859 * q = floor((a + f(x))/d)
2861 * We essentially check if constraint "i" is of the form
2863 * b + f(x) >= 0
2865 * so that we can use it to derive a lower bound on "div".
2866 * However, we allow a slightly more general form
2868 * b + g(x) >= 0
2870 * with the condition that the coefficients of g(x) - f(x) are all
2871 * divisible by d.
2872 * Rewriting this constraint as
2874 * 0 >= -b - g(x)
2876 * adding a + f(x) to both sides and dividing by d, we obtain
2878 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2880 * Taking the floor on both sides, we obtain
2882 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2884 * or
2886 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2888 * In the case of an upper bound, we construct the constraint
2890 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2893 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2894 __isl_take isl_basic_map *bmap, int div, int i,
2895 unsigned total, isl_int v, int lb, int ub)
2897 int j;
2899 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2900 if (lb) {
2901 isl_int_sub(v, bmap->ineq[i][1 + j],
2902 bmap->div[div][1 + 1 + j]);
2903 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2905 if (ub) {
2906 isl_int_add(v, bmap->ineq[i][1 + j],
2907 bmap->div[div][1 + 1 + j]);
2908 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2911 if (!lb && !ub)
2912 return bmap;
2914 bmap = isl_basic_map_cow(bmap);
2915 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2916 if (lb) {
2917 int k = isl_basic_map_alloc_inequality(bmap);
2918 if (k < 0)
2919 goto error;
2920 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2921 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2922 bmap->div[div][1 + j]);
2923 isl_int_cdiv_q(bmap->ineq[k][j],
2924 bmap->ineq[k][j], bmap->div[div][0]);
2926 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2928 if (ub) {
2929 int k = isl_basic_map_alloc_inequality(bmap);
2930 if (k < 0)
2931 goto error;
2932 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2933 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2934 bmap->div[div][1 + j]);
2935 isl_int_fdiv_q(bmap->ineq[k][j],
2936 bmap->ineq[k][j], bmap->div[div][0]);
2938 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2941 return bmap;
2942 error:
2943 isl_basic_map_free(bmap);
2944 return NULL;
2947 /* This function is called right before "div" is eliminated from "bmap"
2948 * using Fourier-Motzkin.
2949 * Look through the constraints of "bmap" for constraints on the argument
2950 * of the integer division and use them to construct constraints on the
2951 * integer division itself. These constraints can then be combined
2952 * during the Fourier-Motzkin elimination.
2953 * Note that it is only useful to introduce lower bounds on "div"
2954 * if "bmap" already contains upper bounds on "div" as the newly
2955 * introduce lower bounds can then be combined with the pre-existing
2956 * upper bounds. Similarly for upper bounds.
2957 * We therefore first check if "bmap" contains any lower and/or upper bounds
2958 * on "div".
2960 * It is interesting to note that the introduction of these constraints
2961 * can indeed lead to more accurate results, even when compared to
2962 * deriving constraints on the argument of "div" from constraints on "div".
2963 * Consider, for example, the set
2965 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2967 * The second constraint can be rewritten as
2969 * 2 * [(-i-2j+3)/4] + k >= 0
2971 * from which we can derive
2973 * -i - 2j + 3 >= -2k
2975 * or
2977 * i + 2j <= 3 + 2k
2979 * Combined with the first constraint, we obtain
2981 * -3 <= 3 + 2k or k >= -3
2983 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2984 * the first constraint, we obtain
2986 * [(i + 2j)/4] >= [-3/4] = -1
2988 * Combining this constraint with the second constraint, we obtain
2990 * k >= -2
2992 static __isl_give isl_basic_map *insert_bounds_on_div(
2993 __isl_take isl_basic_map *bmap, int div)
2995 int i;
2996 int check_lb, check_ub;
2997 isl_int v;
2998 isl_size v_div;
3000 if (!bmap)
3001 return NULL;
3003 if (isl_int_is_zero(bmap->div[div][0]))
3004 return bmap;
3006 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
3007 if (v_div < 0)
3008 return isl_basic_map_free(bmap);
3010 check_lb = 0;
3011 check_ub = 0;
3012 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
3013 int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);
3014 if (s > 0)
3015 check_ub = 1;
3016 if (s < 0)
3017 check_lb = 1;
3020 if (!check_lb && !check_ub)
3021 return bmap;
3023 isl_int_init(v);
3025 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
3026 if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))
3027 continue;
3029 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,
3030 check_lb, check_ub);
3033 isl_int_clear(v);
3035 return bmap;
3038 /* Remove all divs (recursively) involving any of the given variables
3039 * in their definitions.
3041 static __isl_give isl_basic_map *remove_divs_involving_vars(
3042 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
3044 int i;
3046 for (i = bmap->n_div - 1; i >= 0; --i) {
3047 isl_bool involves;
3049 involves = div_involves_vars(bmap, i, first, n);
3050 if (involves < 0)
3051 return isl_basic_map_free(bmap);
3052 if (!involves)
3053 continue;
3054 bmap = insert_bounds_on_div(bmap, i);
3055 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3056 if (!bmap)
3057 return NULL;
3058 i = bmap->n_div;
3061 return bmap;
3064 /* Remove all divs (recursively) involving any of the given dimensions
3065 * in their definitions.
3067 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
3068 __isl_take isl_basic_map *bmap,
3069 enum isl_dim_type type, unsigned first, unsigned n)
3071 isl_size off;
3073 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3074 return isl_basic_map_free(bmap);
3075 off = isl_basic_map_var_offset(bmap, type);
3076 if (off < 0)
3077 return isl_basic_map_free(bmap);
3078 first += off;
3080 return remove_divs_involving_vars(bmap, first, n);
3083 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
3084 __isl_take isl_basic_set *bset,
3085 enum isl_dim_type type, unsigned first, unsigned n)
3087 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
3090 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
3091 enum isl_dim_type type, unsigned first, unsigned n)
3093 int i;
3095 if (!map)
3096 return NULL;
3097 if (map->n == 0)
3098 return map;
3100 map = isl_map_cow(map);
3101 if (!map)
3102 return NULL;
3104 for (i = 0; i < map->n; ++i) {
3105 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
3106 type, first, n);
3107 if (!map->p[i])
3108 goto error;
3110 return map;
3111 error:
3112 isl_map_free(map);
3113 return NULL;
3116 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
3117 enum isl_dim_type type, unsigned first, unsigned n)
3119 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
3120 type, first, n));
3123 /* Does the description of "bmap" depend on the specified dimensions?
3124 * We also check whether the dimensions appear in any of the div definitions.
3125 * In principle there is no need for this check. If the dimensions appear
3126 * in a div definition, they also appear in the defining constraints of that
3127 * div.
3129 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
3130 enum isl_dim_type type, unsigned first, unsigned n)
3132 int i;
3134 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3135 return isl_bool_error;
3137 first += isl_basic_map_offset(bmap, type);
3138 for (i = 0; i < bmap->n_eq; ++i)
3139 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
3140 return isl_bool_true;
3141 for (i = 0; i < bmap->n_ineq; ++i)
3142 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
3143 return isl_bool_true;
3144 for (i = 0; i < bmap->n_div; ++i) {
3145 if (isl_int_is_zero(bmap->div[i][0]))
3146 continue;
3147 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
3148 return isl_bool_true;
3151 return isl_bool_false;
3154 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
3155 enum isl_dim_type type, unsigned first, unsigned n)
3157 int i;
3159 if (isl_map_check_range(map, type, first, n) < 0)
3160 return isl_bool_error;
3162 for (i = 0; i < map->n; ++i) {
3163 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
3164 type, first, n);
3165 if (involves < 0 || involves)
3166 return involves;
3169 return isl_bool_false;
3172 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
3173 enum isl_dim_type type, unsigned first, unsigned n)
3175 return isl_basic_map_involves_dims(bset, type, first, n);
3178 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
3179 enum isl_dim_type type, unsigned first, unsigned n)
3181 return isl_map_involves_dims(set, type, first, n);
3184 /* Does "bset" involve any local variables, i.e., integer divisions?
3186 static isl_bool isl_basic_set_involves_locals(__isl_keep isl_basic_set *bset)
3188 isl_size n;
3190 n = isl_basic_set_dim(bset, isl_dim_div);
3191 if (n < 0)
3192 return isl_bool_error;
3193 return isl_bool_ok(n > 0);
3196 /* isl_set_every_basic_set callback that checks whether "bset"
3197 * is free of local variables.
3199 static isl_bool basic_set_no_locals(__isl_keep isl_basic_set *bset, void *user)
3201 return isl_bool_not(isl_basic_set_involves_locals(bset));
3204 /* Does "set" involve any local variables, i.e., integer divisions?
3206 isl_bool isl_set_involves_locals(__isl_keep isl_set *set)
3208 isl_bool no_locals;
3210 no_locals = isl_set_every_basic_set(set, &basic_set_no_locals, NULL);
3211 return isl_bool_not(no_locals);
3214 /* Drop all constraints in bmap that involve any of the dimensions
3215 * first to first+n-1.
3216 * This function only performs the actual removal of constraints.
3218 * This function should not call finalize since it is used by
3219 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
3221 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
3222 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
3224 int i;
3226 if (n == 0)
3227 return bmap;
3229 bmap = isl_basic_map_cow(bmap);
3231 if (!bmap)
3232 return NULL;
3234 for (i = bmap->n_eq - 1; i >= 0; --i) {
3235 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
3236 continue;
3237 if (isl_basic_map_drop_equality(bmap, i) < 0)
3238 return isl_basic_map_free(bmap);
3241 for (i = bmap->n_ineq - 1; i >= 0; --i) {
3242 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
3243 continue;
3244 if (isl_basic_map_drop_inequality(bmap, i) < 0)
3245 return isl_basic_map_free(bmap);
3248 return bmap;
3251 /* Drop all constraints in bset that involve any of the dimensions
3252 * first to first+n-1.
3253 * This function only performs the actual removal of constraints.
3255 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
3256 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
3258 return isl_basic_map_drop_constraints_involving(bset, first, n);
3261 /* Drop all constraints in bmap that do not involve any of the dimensions
3262 * first to first + n - 1 of the given type.
3264 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
3265 __isl_take isl_basic_map *bmap,
3266 enum isl_dim_type type, unsigned first, unsigned n)
3268 int i;
3270 if (n == 0) {
3271 isl_space *space = isl_basic_map_get_space(bmap);
3272 isl_basic_map_free(bmap);
3273 return isl_basic_map_universe(space);
3275 bmap = isl_basic_map_cow(bmap);
3276 if (!bmap)
3277 return NULL;
3279 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3280 return isl_basic_map_free(bmap);
3282 first += isl_basic_map_offset(bmap, type) - 1;
3284 for (i = bmap->n_eq - 1; i >= 0; --i) {
3285 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
3286 continue;
3287 if (isl_basic_map_drop_equality(bmap, i) < 0)
3288 return isl_basic_map_free(bmap);
3291 for (i = bmap->n_ineq - 1; i >= 0; --i) {
3292 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
3293 continue;
3294 if (isl_basic_map_drop_inequality(bmap, i) < 0)
3295 return isl_basic_map_free(bmap);
3298 bmap = isl_basic_map_add_known_div_constraints(bmap);
3299 return bmap;
3302 /* Drop all constraints in bset that do not involve any of the dimensions
3303 * first to first + n - 1 of the given type.
3305 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
3306 __isl_take isl_basic_set *bset,
3307 enum isl_dim_type type, unsigned first, unsigned n)
3309 return isl_basic_map_drop_constraints_not_involving_dims(bset,
3310 type, first, n);
3313 /* Drop all constraints in bmap that involve any of the dimensions
3314 * first to first + n - 1 of the given type.
3316 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
3317 __isl_take isl_basic_map *bmap,
3318 enum isl_dim_type type, unsigned first, unsigned n)
3320 if (!bmap)
3321 return NULL;
3322 if (n == 0)
3323 return bmap;
3325 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3326 return isl_basic_map_free(bmap);
3328 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
3329 first += isl_basic_map_offset(bmap, type) - 1;
3330 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
3331 bmap = isl_basic_map_add_known_div_constraints(bmap);
3332 return bmap;
3335 /* Drop all constraints in bset that involve any of the dimensions
3336 * first to first + n - 1 of the given type.
3338 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
3339 __isl_take isl_basic_set *bset,
3340 enum isl_dim_type type, unsigned first, unsigned n)
3342 return isl_basic_map_drop_constraints_involving_dims(bset,
3343 type, first, n);
3346 /* Drop constraints from "map" by applying "drop" to each basic map.
3348 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
3349 enum isl_dim_type type, unsigned first, unsigned n,
3350 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
3351 enum isl_dim_type type, unsigned first, unsigned n))
3353 int i;
3355 if (isl_map_check_range(map, type, first, n) < 0)
3356 return isl_map_free(map);
3358 map = isl_map_cow(map);
3359 if (!map)
3360 return NULL;
3362 for (i = 0; i < map->n; ++i) {
3363 map->p[i] = drop(map->p[i], type, first, n);
3364 if (!map->p[i])
3365 return isl_map_free(map);
3368 if (map->n > 1)
3369 ISL_F_CLR(map, ISL_MAP_DISJOINT);
3371 return map;
3374 /* Drop all constraints in map that involve any of the dimensions
3375 * first to first + n - 1 of the given type.
3377 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
3378 __isl_take isl_map *map,
3379 enum isl_dim_type type, unsigned first, unsigned n)
3381 if (n == 0)
3382 return map;
3383 return drop_constraints(map, type, first, n,
3384 &isl_basic_map_drop_constraints_involving_dims);
3387 /* Drop all constraints in "map" that do not involve any of the dimensions
3388 * first to first + n - 1 of the given type.
3390 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3391 __isl_take isl_map *map,
3392 enum isl_dim_type type, unsigned first, unsigned n)
3394 if (n == 0) {
3395 isl_space *space = isl_map_get_space(map);
3396 isl_map_free(map);
3397 return isl_map_universe(space);
3399 return drop_constraints(map, type, first, n,
3400 &isl_basic_map_drop_constraints_not_involving_dims);
3403 /* Drop all constraints in set that involve any of the dimensions
3404 * first to first + n - 1 of the given type.
3406 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3407 __isl_take isl_set *set,
3408 enum isl_dim_type type, unsigned first, unsigned n)
3410 return isl_map_drop_constraints_involving_dims(set, type, first, n);
3413 /* Drop all constraints in "set" that do not involve any of the dimensions
3414 * first to first + n - 1 of the given type.
3416 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3417 __isl_take isl_set *set,
3418 enum isl_dim_type type, unsigned first, unsigned n)
3420 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3423 /* Does local variable "div" of "bmap" have a complete explicit representation?
3424 * Having a complete explicit representation requires not only
3425 * an explicit representation, but also that all local variables
3426 * that appear in this explicit representation in turn have
3427 * a complete explicit representation.
3429 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3431 int i;
3432 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3433 isl_bool marked;
3435 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3436 if (marked < 0 || marked)
3437 return isl_bool_not(marked);
3439 for (i = bmap->n_div - 1; i >= 0; --i) {
3440 isl_bool known;
3442 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3443 continue;
3444 known = isl_basic_map_div_is_known(bmap, i);
3445 if (known < 0 || !known)
3446 return known;
3449 return isl_bool_true;
3452 /* Remove all divs that are unknown or defined in terms of unknown divs.
3454 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3455 __isl_take isl_basic_map *bmap)
3457 int i;
3459 if (!bmap)
3460 return NULL;
3462 for (i = bmap->n_div - 1; i >= 0; --i) {
3463 if (isl_basic_map_div_is_known(bmap, i))
3464 continue;
3465 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3466 if (!bmap)
3467 return NULL;
3468 i = bmap->n_div;
3471 return bmap;
3474 /* Remove all divs that are unknown or defined in terms of unknown divs.
3476 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3477 __isl_take isl_basic_set *bset)
3479 return isl_basic_map_remove_unknown_divs(bset);
3482 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3484 int i;
3486 if (!map)
3487 return NULL;
3488 if (map->n == 0)
3489 return map;
3491 map = isl_map_cow(map);
3492 if (!map)
3493 return NULL;
3495 for (i = 0; i < map->n; ++i) {
3496 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3497 if (!map->p[i])
3498 goto error;
3500 return map;
3501 error:
3502 isl_map_free(map);
3503 return NULL;
3506 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3508 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3511 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3512 __isl_take isl_basic_set *bset,
3513 enum isl_dim_type type, unsigned first, unsigned n)
3515 isl_basic_map *bmap = bset_to_bmap(bset);
3516 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3517 return bset_from_bmap(bmap);
3520 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3521 enum isl_dim_type type, unsigned first, unsigned n)
3523 int i;
3525 if (n == 0)
3526 return map;
3528 map = isl_map_cow(map);
3529 if (isl_map_check_range(map, type, first, n) < 0)
3530 return isl_map_free(map);
3532 for (i = 0; i < map->n; ++i) {
3533 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3534 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3535 if (!map->p[i])
3536 goto error;
3538 map = isl_map_drop(map, type, first, n);
3539 return map;
3540 error:
3541 isl_map_free(map);
3542 return NULL;
3545 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3546 enum isl_dim_type type, unsigned first, unsigned n)
3548 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3549 type, first, n));
3552 /* Project out n inputs starting at first using Fourier-Motzkin */
3553 __isl_give isl_map *isl_map_remove_inputs(__isl_take isl_map *map,
3554 unsigned first, unsigned n)
3556 return isl_map_remove_dims(map, isl_dim_in, first, n);
3559 void isl_basic_set_print_internal(__isl_keep isl_basic_set *bset,
3560 FILE *out, int indent)
3562 isl_printer *p;
3564 if (!bset) {
3565 fprintf(out, "null basic set\n");
3566 return;
3569 fprintf(out, "%*s", indent, "");
3570 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3571 bset->ref, bset->dim->nparam, bset->dim->n_out,
3572 bset->extra, bset->flags);
3574 p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
3575 p = isl_printer_set_dump(p, 1);
3576 p = isl_printer_set_indent(p, indent);
3577 p = isl_printer_start_line(p);
3578 p = isl_printer_print_basic_set(p, bset);
3579 p = isl_printer_end_line(p);
3580 isl_printer_free(p);
3583 void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,
3584 FILE *out, int indent)
3586 isl_printer *p;
3588 if (!bmap) {
3589 fprintf(out, "null basic map\n");
3590 return;
3593 fprintf(out, "%*s", indent, "");
3594 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3595 "flags: %x, n_name: %d\n",
3596 bmap->ref,
3597 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3598 bmap->extra, bmap->flags, bmap->dim->n_id);
3600 p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
3601 p = isl_printer_set_dump(p, 1);
3602 p = isl_printer_set_indent(p, indent);
3603 p = isl_printer_start_line(p);
3604 p = isl_printer_print_basic_map(p, bmap);
3605 p = isl_printer_end_line(p);
3606 isl_printer_free(p);
3609 __isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3610 unsigned pos)
3612 isl_size total;
3614 total = isl_basic_map_dim(bmap, isl_dim_all);
3615 if (total < 0)
3616 return isl_basic_map_free(bmap);
3617 if (pos >= bmap->n_ineq)
3618 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3619 "invalid position", return isl_basic_map_free(bmap));
3620 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3621 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3622 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3623 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3624 return bmap;
3627 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3628 unsigned flags)
3630 if (isl_space_check_is_set(space) < 0)
3631 goto error;
3632 return isl_map_alloc_space(space, n, flags);
3633 error:
3634 isl_space_free(space);
3635 return NULL;
3638 /* Make sure "map" has room for at least "n" more basic maps.
3640 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3642 int i;
3643 struct isl_map *grown = NULL;
3645 if (!map)
3646 return NULL;
3647 isl_assert(map->ctx, n >= 0, goto error);
3648 if (map->n + n <= map->size)
3649 return map;
3650 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3651 if (!grown)
3652 goto error;
3653 for (i = 0; i < map->n; ++i) {
3654 grown->p[i] = isl_basic_map_copy(map->p[i]);
3655 if (!grown->p[i])
3656 goto error;
3657 grown->n++;
3659 isl_map_free(map);
3660 return grown;
3661 error:
3662 isl_map_free(grown);
3663 isl_map_free(map);
3664 return NULL;
3667 /* Make sure "set" has room for at least "n" more basic sets.
3669 __isl_give isl_set *isl_set_grow(__isl_take isl_set *set, int n)
3671 return set_from_map(isl_map_grow(set_to_map(set), n));
3674 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3676 return isl_map_from_basic_map(bset);
3679 /* This function performs the same operation as isl_set_from_basic_set,
3680 * but is considered as a function on an isl_basic_set when exported.
3682 __isl_give isl_set *isl_basic_set_to_set(__isl_take isl_basic_set *bset)
3684 return isl_set_from_basic_set(bset);
3687 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3689 struct isl_map *map;
3691 if (!bmap)
3692 return NULL;
3694 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3695 return isl_map_add_basic_map(map, bmap);
3698 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3699 __isl_take isl_basic_set *bset)
3701 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3702 bset_to_bmap(bset)));
3705 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3707 return isl_map_free(set);
3710 void isl_set_print_internal(__isl_keep isl_set *set, FILE *out, int indent)
3712 int i;
3714 if (!set) {
3715 fprintf(out, "null set\n");
3716 return;
3719 fprintf(out, "%*s", indent, "");
3720 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3721 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3722 set->flags);
3723 for (i = 0; i < set->n; ++i) {
3724 fprintf(out, "%*s", indent, "");
3725 fprintf(out, "basic set %d:\n", i);
3726 isl_basic_set_print_internal(set->p[i], out, indent+4);
3730 void isl_map_print_internal(__isl_keep isl_map *map, FILE *out, int indent)
3732 int i;
3734 if (!map) {
3735 fprintf(out, "null map\n");
3736 return;
3739 fprintf(out, "%*s", indent, "");
3740 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3741 "flags: %x, n_name: %d\n",
3742 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3743 map->dim->n_out, map->flags, map->dim->n_id);
3744 for (i = 0; i < map->n; ++i) {
3745 fprintf(out, "%*s", indent, "");
3746 fprintf(out, "basic map %d:\n", i);
3747 isl_basic_map_print_internal(map->p[i], out, indent+4);
3751 /* Check that the space of "bset" is the same as that of the domain of "bmap".
3753 static isl_stat isl_basic_map_check_compatible_domain(
3754 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3756 isl_bool ok;
3758 ok = isl_basic_map_compatible_domain(bmap, bset);
3759 if (ok < 0)
3760 return isl_stat_error;
3761 if (!ok)
3762 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3763 "incompatible spaces", return isl_stat_error);
3765 return isl_stat_ok;
3768 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3769 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3771 struct isl_basic_map *bmap_domain;
3772 isl_size dim;
3774 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3775 goto error;
3777 dim = isl_basic_set_dim(bset, isl_dim_set);
3778 if (dim < 0)
3779 goto error;
3780 if (dim != 0 &&
3781 isl_basic_map_check_compatible_domain(bmap, bset) < 0)
3782 goto error;
3784 bmap = isl_basic_map_cow(bmap);
3785 if (!bmap)
3786 goto error;
3787 bmap = isl_basic_map_extend(bmap,
3788 bset->n_div, bset->n_eq, bset->n_ineq);
3789 bmap_domain = isl_basic_map_from_domain(bset);
3790 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3792 bmap = isl_basic_map_simplify(bmap);
3793 return isl_basic_map_finalize(bmap);
3794 error:
3795 isl_basic_map_free(bmap);
3796 isl_basic_set_free(bset);
3797 return NULL;
3800 /* Check that the space of "bset" is the same as that of the range of "bmap".
3802 static isl_stat isl_basic_map_check_compatible_range(
3803 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3805 isl_bool ok;
3807 ok = isl_basic_map_compatible_range(bmap, bset);
3808 if (ok < 0)
3809 return isl_stat_error;
3810 if (!ok)
3811 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3812 "incompatible spaces", return isl_stat_error);
3814 return isl_stat_ok;
3817 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3818 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3820 struct isl_basic_map *bmap_range;
3821 isl_size dim;
3823 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3824 goto error;
3826 dim = isl_basic_set_dim(bset, isl_dim_set);
3827 if (dim < 0)
3828 goto error;
3829 if (dim != 0 && isl_basic_map_check_compatible_range(bmap, bset) < 0)
3830 goto error;
3832 if (isl_basic_set_plain_is_universe(bset)) {
3833 isl_basic_set_free(bset);
3834 return bmap;
3837 bmap = isl_basic_map_cow(bmap);
3838 if (!bmap)
3839 goto error;
3840 bmap = isl_basic_map_extend(bmap,
3841 bset->n_div, bset->n_eq, bset->n_ineq);
3842 bmap_range = bset_to_bmap(bset);
3843 bmap = add_constraints(bmap, bmap_range, 0, 0);
3845 bmap = isl_basic_map_simplify(bmap);
3846 return isl_basic_map_finalize(bmap);
3847 error:
3848 isl_basic_map_free(bmap);
3849 isl_basic_set_free(bset);
3850 return NULL;
3853 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3854 __isl_keep isl_vec *vec)
3856 int i;
3857 isl_size total;
3858 isl_int s;
3860 total = isl_basic_map_dim(bmap, isl_dim_all);
3861 if (total < 0 || !vec)
3862 return isl_bool_error;
3864 if (1 + total != vec->size)
3865 return isl_bool_false;
3867 isl_int_init(s);
3869 for (i = 0; i < bmap->n_eq; ++i) {
3870 isl_seq_inner_product(vec->el, bmap->eq[i], 1 + total, &s);
3871 if (!isl_int_is_zero(s)) {
3872 isl_int_clear(s);
3873 return isl_bool_false;
3877 for (i = 0; i < bmap->n_ineq; ++i) {
3878 isl_seq_inner_product(vec->el, bmap->ineq[i], 1 + total, &s);
3879 if (isl_int_is_neg(s)) {
3880 isl_int_clear(s);
3881 return isl_bool_false;
3885 isl_int_clear(s);
3887 return isl_bool_true;
3890 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3891 __isl_keep isl_vec *vec)
3893 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3896 __isl_give isl_basic_map *isl_basic_map_intersect(
3897 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3899 struct isl_vec *sample = NULL;
3900 isl_space *space1, *space2;
3901 isl_size dim1, dim2, nparam1, nparam2;
3903 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3904 goto error;
3905 space1 = isl_basic_map_peek_space(bmap1);
3906 space2 = isl_basic_map_peek_space(bmap2);
3907 dim1 = isl_space_dim(space1, isl_dim_all);
3908 dim2 = isl_space_dim(space2, isl_dim_all);
3909 nparam1 = isl_space_dim(space1, isl_dim_param);
3910 nparam2 = isl_space_dim(space2, isl_dim_param);
3911 if (dim1 < 0 || dim2 < 0 || nparam1 < 0 || nparam2 < 0)
3912 goto error;
3913 if (dim1 == nparam1 && dim2 != nparam2)
3914 return isl_basic_map_intersect(bmap2, bmap1);
3916 if (dim2 != nparam2 &&
3917 isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
3918 goto error;
3920 if (isl_basic_map_plain_is_empty(bmap1)) {
3921 isl_basic_map_free(bmap2);
3922 return bmap1;
3924 if (isl_basic_map_plain_is_empty(bmap2)) {
3925 isl_basic_map_free(bmap1);
3926 return bmap2;
3929 if (bmap1->sample &&
3930 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3931 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3932 sample = isl_vec_copy(bmap1->sample);
3933 else if (bmap2->sample &&
3934 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3935 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3936 sample = isl_vec_copy(bmap2->sample);
3938 bmap1 = isl_basic_map_cow(bmap1);
3939 if (!bmap1)
3940 goto error;
3941 bmap1 = isl_basic_map_extend(bmap1,
3942 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3943 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3945 if (!bmap1)
3946 isl_vec_free(sample);
3947 else if (sample) {
3948 isl_vec_free(bmap1->sample);
3949 bmap1->sample = sample;
3952 bmap1 = isl_basic_map_simplify(bmap1);
3953 return isl_basic_map_finalize(bmap1);
3954 error:
3955 if (sample)
3956 isl_vec_free(sample);
3957 isl_basic_map_free(bmap1);
3958 isl_basic_map_free(bmap2);
3959 return NULL;
3962 __isl_give isl_basic_set *isl_basic_set_intersect(
3963 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3965 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3966 bset_to_bmap(bset2)));
3969 /* Intersect the parameter domain of "bmap" with "bset".
3971 * isl_basic_map_intersect handles this as a special case.
3973 __isl_give isl_basic_map *isl_basic_map_intersect_params(
3974 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3976 return isl_basic_map_intersect(bmap, bset);
3979 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3980 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3982 isl_basic_map *bmap;
3984 bmap = bset_to_bmap(bset1);
3985 bmap = isl_basic_map_intersect_params(bmap, bset2);
3986 return bset_from_bmap(bmap);
3989 /* Does "map" consist of a single disjunct, without any local variables?
3991 static isl_bool is_convex_no_locals(__isl_keep isl_map *map)
3993 isl_size n_div;
3995 if (!map)
3996 return isl_bool_error;
3997 if (map->n != 1)
3998 return isl_bool_false;
3999 n_div = isl_basic_map_dim(map->p[0], isl_dim_div);
4000 if (n_div < 0)
4001 return isl_bool_error;
4002 if (n_div != 0)
4003 return isl_bool_false;
4004 return isl_bool_true;
4007 /* Check that "map" consists of a single disjunct, without any local variables.
4009 static isl_stat check_convex_no_locals(__isl_keep isl_map *map)
4011 isl_bool ok;
4013 ok = is_convex_no_locals(map);
4014 if (ok < 0)
4015 return isl_stat_error;
4016 if (ok)
4017 return isl_stat_ok;
4019 isl_die(isl_map_get_ctx(map), isl_error_internal,
4020 "unexpectedly not convex or involving local variables",
4021 return isl_stat_error);
4024 /* Special case of isl_map_intersect, where both map1 and map2
4025 * are convex, without any divs and such that either map1 or map2
4026 * contains a single constraint. This constraint is then simply
4027 * added to the other map.
4029 static __isl_give isl_map *map_intersect_add_constraint(
4030 __isl_take isl_map *map1, __isl_take isl_map *map2)
4032 if (check_convex_no_locals(map1) < 0 ||
4033 check_convex_no_locals(map2) < 0)
4034 goto error;
4036 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
4037 return isl_map_intersect(map2, map1);
4039 map1 = isl_map_cow(map1);
4040 if (!map1)
4041 goto error;
4042 if (isl_map_plain_is_empty(map1)) {
4043 isl_map_free(map2);
4044 return map1;
4046 if (map2->p[0]->n_eq == 1)
4047 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
4048 else
4049 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
4050 map2->p[0]->ineq[0]);
4052 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
4053 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
4054 if (!map1->p[0])
4055 goto error;
4057 if (isl_basic_map_plain_is_empty(map1->p[0])) {
4058 isl_basic_map_free(map1->p[0]);
4059 map1->n = 0;
4062 isl_map_free(map2);
4064 map1 = isl_map_unmark_normalized(map1);
4065 return map1;
4066 error:
4067 isl_map_free(map1);
4068 isl_map_free(map2);
4069 return NULL;
4072 /* map2 may be either a parameter domain or a map living in the same
4073 * space as map1.
4075 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
4076 __isl_take isl_map *map2)
4078 unsigned flags = 0;
4079 isl_bool equal;
4080 isl_map *result;
4081 int i, j;
4082 isl_size dim2, nparam2;
4084 if (!map1 || !map2)
4085 goto error;
4087 if ((isl_map_plain_is_empty(map1) ||
4088 isl_map_plain_is_universe(map2)) &&
4089 isl_space_is_equal(map1->dim, map2->dim)) {
4090 isl_map_free(map2);
4091 return map1;
4093 if ((isl_map_plain_is_empty(map2) ||
4094 isl_map_plain_is_universe(map1)) &&
4095 isl_space_is_equal(map1->dim, map2->dim)) {
4096 isl_map_free(map1);
4097 return map2;
4100 if (is_convex_no_locals(map1) == isl_bool_true &&
4101 is_convex_no_locals(map2) == isl_bool_true &&
4102 isl_space_is_equal(map1->dim, map2->dim) &&
4103 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
4104 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
4105 return map_intersect_add_constraint(map1, map2);
4107 equal = isl_map_plain_is_equal(map1, map2);
4108 if (equal < 0)
4109 goto error;
4110 if (equal) {
4111 isl_map_free(map2);
4112 return map1;
4115 dim2 = isl_map_dim(map2, isl_dim_all);
4116 nparam2 = isl_map_dim(map2, isl_dim_param);
4117 if (dim2 < 0 || nparam2 < 0)
4118 goto error;
4119 if (dim2 != nparam2)
4120 isl_assert(map1->ctx,
4121 isl_space_is_equal(map1->dim, map2->dim), goto error);
4123 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
4124 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
4125 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
4127 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4128 map1->n * map2->n, flags);
4129 if (!result)
4130 goto error;
4131 for (i = 0; i < map1->n; ++i)
4132 for (j = 0; j < map2->n; ++j) {
4133 struct isl_basic_map *part;
4134 part = isl_basic_map_intersect(
4135 isl_basic_map_copy(map1->p[i]),
4136 isl_basic_map_copy(map2->p[j]));
4137 if (isl_basic_map_is_empty(part) < 0)
4138 part = isl_basic_map_free(part);
4139 result = isl_map_add_basic_map(result, part);
4140 if (!result)
4141 goto error;
4143 isl_map_free(map1);
4144 isl_map_free(map2);
4145 return result;
4146 error:
4147 isl_map_free(map1);
4148 isl_map_free(map2);
4149 return NULL;
4152 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
4153 __isl_take isl_map *map2)
4155 if (isl_map_check_equal_space(map1, map2) < 0)
4156 goto error;
4157 return map_intersect_internal(map1, map2);
4158 error:
4159 isl_map_free(map1);
4160 isl_map_free(map2);
4161 return NULL;
4164 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
4165 __isl_take isl_map *map2)
4167 isl_map_align_params_bin(&map1, &map2);
4168 return map_intersect(map1, map2);
4171 __isl_give isl_set *isl_set_intersect(__isl_take isl_set *set1,
4172 __isl_take isl_set *set2)
4174 return set_from_map(isl_map_intersect(set_to_map(set1),
4175 set_to_map(set2)));
4178 /* map_intersect_internal accepts intersections
4179 * with parameter domains, so we can just call that function.
4181 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
4182 __isl_take isl_set *params)
4184 isl_map_align_params_set(&map, &params);
4185 return map_intersect_internal(map, params);
4188 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
4189 __isl_take isl_set *params)
4191 return isl_map_intersect_params(set, params);
4194 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
4196 isl_space *space;
4197 unsigned pos;
4198 isl_size n1, n2;
4200 if (!bmap)
4201 return NULL;
4202 bmap = isl_basic_map_cow(bmap);
4203 if (!bmap)
4204 return NULL;
4205 space = isl_space_reverse(isl_space_copy(bmap->dim));
4206 pos = isl_basic_map_offset(bmap, isl_dim_in);
4207 n1 = isl_basic_map_dim(bmap, isl_dim_in);
4208 n2 = isl_basic_map_dim(bmap, isl_dim_out);
4209 if (n1 < 0 || n2 < 0)
4210 bmap = isl_basic_map_free(bmap);
4211 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
4212 return isl_basic_map_reset_space(bmap, space);
4215 /* Given a basic map where the tuple of type "type" is a wrapped map,
4216 * swap domain and range of that wrapped map.
4218 static __isl_give isl_basic_map *isl_basic_map_reverse_wrapped(
4219 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
4221 isl_space *space;
4222 isl_size offset, n1, n2;
4224 space = isl_basic_map_peek_space(bmap);
4225 offset = isl_basic_map_var_offset(bmap, type);
4226 n1 = isl_space_wrapped_dim(space, type, isl_dim_in);
4227 n2 = isl_space_wrapped_dim(space, type, isl_dim_out);
4228 if (offset < 0 || n1 < 0 || n2 < 0)
4229 return isl_basic_map_free(bmap);
4231 bmap = isl_basic_map_swap_vars(bmap, 1 + offset, n1, n2);
4233 space = isl_basic_map_take_space(bmap);
4234 space = isl_space_reverse_wrapped(space, type);
4235 bmap = isl_basic_map_restore_space(bmap, space);
4237 return bmap;
4240 /* Given a basic map (A -> B) -> C, return the corresponding basic map
4241 * (B -> A) -> C.
4243 static __isl_give isl_basic_map *isl_basic_map_domain_reverse(
4244 __isl_take isl_basic_map *bmap)
4246 isl_space *space;
4248 space = isl_basic_map_peek_space(bmap);
4249 if (isl_space_check_domain_is_wrapping(space) < 0)
4250 return isl_basic_map_free(bmap);
4251 bmap = isl_basic_map_reverse_wrapped(bmap, isl_dim_in);
4253 return bmap;
4256 /* Given a basic map A -> (B -> C), return the corresponding basic map
4257 * A -> (C -> B).
4259 static __isl_give isl_basic_map *isl_basic_map_range_reverse(
4260 __isl_take isl_basic_map *bmap)
4262 isl_space *space;
4264 space = isl_basic_map_peek_space(bmap);
4265 if (isl_space_check_range_is_wrapping(space) < 0)
4266 return isl_basic_map_free(bmap);
4267 bmap = isl_basic_map_reverse_wrapped(bmap, isl_dim_out);
4269 return bmap;
4272 /* Given a basic map that is actually a basic set (A -> B),
4273 * return the corresponding basic set (B -> A) as a basic map.
4275 static __isl_give isl_basic_map *isl_basic_map_set_reverse(
4276 __isl_take isl_basic_map *bmap)
4278 isl_space *space;
4280 space = isl_basic_map_peek_space(bmap);
4281 if (isl_space_check_is_wrapping(space) < 0)
4282 return isl_basic_map_free(bmap);
4283 bmap = isl_basic_map_reverse_wrapped(bmap, isl_dim_set);
4285 return bmap;
4288 static __isl_give isl_basic_map *basic_map_space_reset(
4289 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
4291 isl_space *space;
4293 if (!bmap)
4294 return NULL;
4295 if (!isl_space_is_named_or_nested(bmap->dim, type))
4296 return bmap;
4298 space = isl_basic_map_get_space(bmap);
4299 space = isl_space_reset(space, type);
4300 bmap = isl_basic_map_reset_space(bmap, space);
4301 return bmap;
4304 __isl_give isl_basic_map *isl_basic_map_insert_dims(
4305 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4306 unsigned pos, unsigned n)
4308 isl_bool rational, is_empty;
4309 isl_space *res_space;
4310 struct isl_basic_map *res;
4311 struct isl_dim_map *dim_map;
4312 isl_size total;
4313 unsigned off;
4314 enum isl_dim_type t;
4316 if (n == 0)
4317 return basic_map_space_reset(bmap, type);
4319 is_empty = isl_basic_map_plain_is_empty(bmap);
4320 total = isl_basic_map_dim(bmap, isl_dim_all);
4321 if (is_empty < 0 || total < 0)
4322 return isl_basic_map_free(bmap);
4323 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
4324 type, pos, n);
4325 if (!res_space)
4326 return isl_basic_map_free(bmap);
4327 if (is_empty) {
4328 isl_basic_map_free(bmap);
4329 return isl_basic_map_empty(res_space);
4332 dim_map = isl_dim_map_alloc(bmap->ctx, total + n);
4333 off = 0;
4334 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4335 isl_size dim;
4337 if (t != type) {
4338 isl_dim_map_dim(dim_map, bmap->dim, t, off);
4339 } else {
4340 isl_size size = isl_basic_map_dim(bmap, t);
4341 if (size < 0)
4342 dim_map = isl_dim_map_free(dim_map);
4343 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4344 0, pos, off);
4345 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4346 pos, size - pos, off + pos + n);
4348 dim = isl_space_dim(res_space, t);
4349 if (dim < 0)
4350 dim_map = isl_dim_map_free(dim_map);
4351 off += dim;
4353 isl_dim_map_div(dim_map, bmap, off);
4355 res = isl_basic_map_alloc_space(res_space,
4356 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4357 rational = isl_basic_map_is_rational(bmap);
4358 if (rational < 0)
4359 res = isl_basic_map_free(res);
4360 if (rational)
4361 res = isl_basic_map_set_rational(res);
4362 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4363 return isl_basic_map_finalize(res);
4366 __isl_give isl_basic_set *isl_basic_set_insert_dims(
4367 __isl_take isl_basic_set *bset,
4368 enum isl_dim_type type, unsigned pos, unsigned n)
4370 return isl_basic_map_insert_dims(bset, type, pos, n);
4373 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
4374 enum isl_dim_type type, unsigned n)
4376 isl_size dim;
4378 dim = isl_basic_map_dim(bmap, type);
4379 if (dim < 0)
4380 return isl_basic_map_free(bmap);
4381 return isl_basic_map_insert_dims(bmap, type, dim, n);
4384 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
4385 enum isl_dim_type type, unsigned n)
4387 if (!bset)
4388 return NULL;
4389 isl_assert(bset->ctx, type != isl_dim_in, goto error);
4390 return isl_basic_map_add_dims(bset, type, n);
4391 error:
4392 isl_basic_set_free(bset);
4393 return NULL;
4396 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
4397 enum isl_dim_type type)
4399 isl_space *space;
4401 if (!map || !isl_space_is_named_or_nested(map->dim, type))
4402 return map;
4404 space = isl_map_get_space(map);
4405 space = isl_space_reset(space, type);
4406 map = isl_map_reset_space(map, space);
4407 return map;
4410 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
4411 enum isl_dim_type type, unsigned pos, unsigned n)
4413 int i;
4414 isl_space *space;
4416 if (n == 0)
4417 return map_space_reset(map, type);
4419 map = isl_map_cow(map);
4420 if (!map)
4421 return NULL;
4423 for (i = 0; i < map->n; ++i) {
4424 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
4425 if (!map->p[i])
4426 goto error;
4429 space = isl_map_take_space(map);
4430 space = isl_space_insert_dims(space, type, pos, n);
4431 map = isl_map_restore_space(map, space);
4433 return map;
4434 error:
4435 isl_map_free(map);
4436 return NULL;
4439 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
4440 enum isl_dim_type type, unsigned pos, unsigned n)
4442 return isl_map_insert_dims(set, type, pos, n);
4445 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
4446 enum isl_dim_type type, unsigned n)
4448 isl_size dim;
4450 dim = isl_map_dim(map, type);
4451 if (dim < 0)
4452 return isl_map_free(map);
4453 return isl_map_insert_dims(map, type, dim, n);
4456 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
4457 enum isl_dim_type type, unsigned n)
4459 if (!set)
4460 return NULL;
4461 isl_assert(set->ctx, type != isl_dim_in, goto error);
4462 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
4463 error:
4464 isl_set_free(set);
4465 return NULL;
4468 __isl_give isl_basic_map *isl_basic_map_move_dims(
4469 __isl_take isl_basic_map *bmap,
4470 enum isl_dim_type dst_type, unsigned dst_pos,
4471 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4473 isl_space *space;
4474 struct isl_dim_map *dim_map;
4475 struct isl_basic_map *res;
4476 enum isl_dim_type t;
4477 isl_size total;
4478 unsigned off;
4480 if (!bmap)
4481 return NULL;
4482 if (n == 0) {
4483 bmap = isl_basic_map_reset(bmap, src_type);
4484 bmap = isl_basic_map_reset(bmap, dst_type);
4485 return bmap;
4488 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
4489 return isl_basic_map_free(bmap);
4491 if (dst_type == src_type && dst_pos == src_pos)
4492 return bmap;
4494 isl_assert(bmap->ctx, dst_type != src_type, goto error);
4496 if (pos(bmap->dim, dst_type) + dst_pos ==
4497 pos(bmap->dim, src_type) + src_pos +
4498 ((src_type < dst_type) ? n : 0)) {
4499 space = isl_basic_map_take_space(bmap);
4500 space = isl_space_move_dims(space, dst_type, dst_pos,
4501 src_type, src_pos, n);
4502 bmap = isl_basic_map_restore_space(bmap, space);
4503 bmap = isl_basic_map_finalize(bmap);
4505 return bmap;
4508 total = isl_basic_map_dim(bmap, isl_dim_all);
4509 if (total < 0)
4510 return isl_basic_map_free(bmap);
4511 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4513 off = 0;
4514 space = isl_basic_map_peek_space(bmap);
4515 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4516 isl_size size = isl_space_dim(space, t);
4517 if (size < 0)
4518 dim_map = isl_dim_map_free(dim_map);
4519 if (t == dst_type) {
4520 isl_dim_map_dim_range(dim_map, space, t,
4521 0, dst_pos, off);
4522 off += dst_pos;
4523 isl_dim_map_dim_range(dim_map, space, src_type,
4524 src_pos, n, off);
4525 off += n;
4526 isl_dim_map_dim_range(dim_map, space, t,
4527 dst_pos, size - dst_pos, off);
4528 off += size - dst_pos;
4529 } else if (t == src_type) {
4530 isl_dim_map_dim_range(dim_map, space, t,
4531 0, src_pos, off);
4532 off += src_pos;
4533 isl_dim_map_dim_range(dim_map, space, t,
4534 src_pos + n, size - src_pos - n, off);
4535 off += size - src_pos - n;
4536 } else {
4537 isl_dim_map_dim(dim_map, space, t, off);
4538 off += size;
4541 isl_dim_map_div(dim_map, bmap, off);
4543 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4544 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4545 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4546 space = isl_basic_map_take_space(bmap);
4547 space = isl_space_move_dims(space, dst_type, dst_pos,
4548 src_type, src_pos, n);
4549 bmap = isl_basic_map_restore_space(bmap, space);
4550 if (!bmap)
4551 goto error;
4553 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4554 bmap = isl_basic_map_gauss(bmap, NULL);
4555 bmap = isl_basic_map_finalize(bmap);
4557 return bmap;
4558 error:
4559 isl_basic_map_free(bmap);
4560 return NULL;
4563 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4564 enum isl_dim_type dst_type, unsigned dst_pos,
4565 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4567 isl_basic_map *bmap = bset_to_bmap(bset);
4568 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4569 src_type, src_pos, n);
4570 return bset_from_bmap(bmap);
4573 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4574 enum isl_dim_type dst_type, unsigned dst_pos,
4575 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4577 if (!set)
4578 return NULL;
4579 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4580 return set_from_map(isl_map_move_dims(set_to_map(set),
4581 dst_type, dst_pos, src_type, src_pos, n));
4582 error:
4583 isl_set_free(set);
4584 return NULL;
4587 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4588 enum isl_dim_type dst_type, unsigned dst_pos,
4589 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4591 int i;
4592 isl_space *space;
4594 if (n == 0) {
4595 map = isl_map_reset(map, src_type);
4596 map = isl_map_reset(map, dst_type);
4597 return map;
4600 if (isl_map_check_range(map, src_type, src_pos, n))
4601 return isl_map_free(map);
4603 if (dst_type == src_type && dst_pos == src_pos)
4604 return map;
4606 isl_assert(map->ctx, dst_type != src_type, goto error);
4608 map = isl_map_cow(map);
4609 if (!map)
4610 return NULL;
4612 for (i = 0; i < map->n; ++i) {
4613 map->p[i] = isl_basic_map_move_dims(map->p[i],
4614 dst_type, dst_pos,
4615 src_type, src_pos, n);
4616 if (!map->p[i])
4617 goto error;
4620 space = isl_map_take_space(map);
4621 space = isl_space_move_dims(space, dst_type, dst_pos,
4622 src_type, src_pos, n);
4623 map = isl_map_restore_space(map, space);
4625 return map;
4626 error:
4627 isl_map_free(map);
4628 return NULL;
4631 /* Move the specified dimensions to the last columns right before
4632 * the divs. Don't change the dimension specification of bmap.
4633 * That's the responsibility of the caller.
4635 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4636 enum isl_dim_type type, unsigned first, unsigned n)
4638 isl_space *space;
4639 struct isl_dim_map *dim_map;
4640 struct isl_basic_map *res;
4641 enum isl_dim_type t;
4642 isl_size total;
4643 unsigned off;
4645 if (!bmap)
4646 return NULL;
4647 if (isl_basic_map_offset(bmap, type) + first + n ==
4648 isl_basic_map_offset(bmap, isl_dim_div))
4649 return bmap;
4651 total = isl_basic_map_dim(bmap, isl_dim_all);
4652 if (total < 0)
4653 return isl_basic_map_free(bmap);
4654 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4656 off = 0;
4657 space = isl_basic_map_peek_space(bmap);
4658 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4659 isl_size size = isl_space_dim(space, t);
4660 if (size < 0)
4661 dim_map = isl_dim_map_free(dim_map);
4662 if (t == type) {
4663 isl_dim_map_dim_range(dim_map, space, t,
4664 0, first, off);
4665 off += first;
4666 isl_dim_map_dim_range(dim_map, space, t,
4667 first, n, total - bmap->n_div - n);
4668 isl_dim_map_dim_range(dim_map, space, t,
4669 first + n, size - (first + n), off);
4670 off += size - (first + n);
4671 } else {
4672 isl_dim_map_dim(dim_map, space, t, off);
4673 off += size;
4676 isl_dim_map_div(dim_map, bmap, off + n);
4678 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4679 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4680 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4681 return res;
4684 /* Insert "n" rows in the divs of "bmap".
4686 * The number of columns is not changed, which means that the last
4687 * dimensions of "bmap" are being reintepreted as the new divs.
4688 * The space of "bmap" is not adjusted, however, which means
4689 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4690 * from the space of "bmap" is the responsibility of the caller.
4692 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4693 int n)
4695 int i;
4696 size_t row_size;
4697 isl_int **new_div;
4698 isl_int *old;
4700 bmap = isl_basic_map_cow(bmap);
4701 if (!bmap)
4702 return NULL;
4704 row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;
4705 old = bmap->block2.data;
4706 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4707 (bmap->extra + n) * (1 + row_size));
4708 if (!bmap->block2.data)
4709 return isl_basic_map_free(bmap);
4710 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4711 if (!new_div)
4712 return isl_basic_map_free(bmap);
4713 for (i = 0; i < n; ++i) {
4714 new_div[i] = bmap->block2.data +
4715 (bmap->extra + i) * (1 + row_size);
4716 isl_seq_clr(new_div[i], 1 + row_size);
4718 for (i = 0; i < bmap->extra; ++i)
4719 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4720 free(bmap->div);
4721 bmap->div = new_div;
4722 bmap->n_div += n;
4723 bmap->extra += n;
4725 return bmap;
4728 /* Drop constraints from "bmap" that only involve the variables
4729 * of "type" in the range [first, first + n] that are not related
4730 * to any of the variables outside that interval.
4731 * These constraints cannot influence the values for the variables
4732 * outside the interval, except in case they cause "bmap" to be empty.
4733 * Only drop the constraints if "bmap" is known to be non-empty.
4735 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4736 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4737 unsigned first, unsigned n)
4739 int i;
4740 int *groups;
4741 isl_size dim, n_div;
4742 isl_bool non_empty;
4744 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4745 if (non_empty < 0)
4746 return isl_basic_map_free(bmap);
4747 if (!non_empty)
4748 return bmap;
4750 dim = isl_basic_map_dim(bmap, isl_dim_all);
4751 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4752 if (dim < 0 || n_div < 0)
4753 return isl_basic_map_free(bmap);
4754 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4755 if (!groups)
4756 return isl_basic_map_free(bmap);
4757 first += isl_basic_map_offset(bmap, type) - 1;
4758 for (i = 0; i < first; ++i)
4759 groups[i] = -1;
4760 for (i = first + n; i < dim - n_div; ++i)
4761 groups[i] = -1;
4763 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4765 return bmap;
4768 /* Turn the n dimensions of type type, starting at first
4769 * into existentially quantified variables.
4771 * If a subset of the projected out variables are unrelated
4772 * to any of the variables that remain, then the constraints
4773 * involving this subset are simply dropped first.
4775 __isl_give isl_basic_map *isl_basic_map_project_out(
4776 __isl_take isl_basic_map *bmap,
4777 enum isl_dim_type type, unsigned first, unsigned n)
4779 isl_bool empty;
4780 isl_space *space;
4782 if (n == 0)
4783 return basic_map_space_reset(bmap, type);
4784 if (type == isl_dim_div)
4785 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4786 "cannot project out existentially quantified variables",
4787 return isl_basic_map_free(bmap));
4789 empty = isl_basic_map_plain_is_empty(bmap);
4790 if (empty < 0)
4791 return isl_basic_map_free(bmap);
4792 if (empty)
4793 bmap = isl_basic_map_set_to_empty(bmap);
4795 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4796 if (!bmap)
4797 return NULL;
4799 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4800 return isl_basic_map_remove_dims(bmap, type, first, n);
4802 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4803 return isl_basic_map_free(bmap);
4805 bmap = move_last(bmap, type, first, n);
4806 bmap = isl_basic_map_cow(bmap);
4807 bmap = insert_div_rows(bmap, n);
4809 space = isl_basic_map_take_space(bmap);
4810 space = isl_space_drop_dims(space, type, first, n);
4811 bmap = isl_basic_map_restore_space(bmap, space);
4812 bmap = isl_basic_map_simplify(bmap);
4813 bmap = isl_basic_map_drop_redundant_divs(bmap);
4814 return isl_basic_map_finalize(bmap);
4817 /* Turn the n dimensions of type type, starting at first
4818 * into existentially quantified variables.
4820 __isl_give isl_basic_set *isl_basic_set_project_out(
4821 __isl_take isl_basic_set *bset, enum isl_dim_type type,
4822 unsigned first, unsigned n)
4824 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4825 type, first, n));
4828 /* Turn the n dimensions of type type, starting at first
4829 * into existentially quantified variables.
4831 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4832 enum isl_dim_type type, unsigned first, unsigned n)
4834 int i;
4835 isl_space *space;
4837 if (n == 0)
4838 return map_space_reset(map, type);
4840 if (isl_map_check_range(map, type, first, n) < 0)
4841 return isl_map_free(map);
4843 map = isl_map_cow(map);
4844 if (!map)
4845 return NULL;
4847 for (i = 0; i < map->n; ++i) {
4848 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4849 if (!map->p[i])
4850 goto error;
4853 if (map->n > 1)
4854 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4855 map = isl_map_unmark_normalized(map);
4857 space = isl_map_take_space(map);
4858 space = isl_space_drop_dims(space, type, first, n);
4859 map = isl_map_restore_space(map, space);
4861 return map;
4862 error:
4863 isl_map_free(map);
4864 return NULL;
4867 #undef TYPE
4868 #define TYPE isl_map
4869 #include "isl_project_out_all_params_templ.c"
4870 #include "isl_project_out_param_templ.c"
4872 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4873 * into existentially quantified variables.
4875 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4876 enum isl_dim_type type, unsigned first, unsigned n)
4878 isl_size dim;
4880 dim = isl_map_dim(map, type);
4881 if (isl_map_check_range(map, type, first, n) < 0 || dim < 0)
4882 return isl_map_free(map);
4883 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4884 map = isl_map_project_out(map, type, 0, first);
4885 return map;
4888 /* Turn the n dimensions of type type, starting at first
4889 * into existentially quantified variables.
4891 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4892 enum isl_dim_type type, unsigned first, unsigned n)
4894 return set_from_map(isl_map_project_out(set_to_map(set),
4895 type, first, n));
4898 /* If "set" involves a parameter with identifier "id",
4899 * then turn it into an existentially quantified variable.
4901 __isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,
4902 __isl_take isl_id *id)
4904 return set_from_map(isl_map_project_out_param_id(set_to_map(set), id));
4907 /* If "set" involves any of the parameters with identifiers in "list",
4908 * then turn them into existentially quantified variables.
4910 __isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,
4911 __isl_take isl_id_list *list)
4913 isl_map *map;
4915 map = set_to_map(set);
4916 map = isl_map_project_out_param_id_list(map, list);
4917 return set_from_map(map);
4920 /* Project out all parameters from "set" by existentially quantifying
4921 * over them.
4923 __isl_give isl_set *isl_set_project_out_all_params(__isl_take isl_set *set)
4925 return set_from_map(isl_map_project_out_all_params(set_to_map(set)));
4928 /* Return a map that projects the elements in "set" onto their
4929 * "n" set dimensions starting at "first".
4930 * "type" should be equal to isl_dim_set.
4932 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4933 enum isl_dim_type type, unsigned first, unsigned n)
4935 int i;
4936 isl_map *map;
4938 if (type != isl_dim_set)
4939 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4940 "only set dimensions can be projected out", goto error);
4941 if (isl_set_check_range(set, type, first, n) < 0)
4942 return isl_set_free(set);
4944 map = isl_map_from_domain(set);
4945 map = isl_map_add_dims(map, isl_dim_out, n);
4946 for (i = 0; i < n; ++i)
4947 map = isl_map_equate(map, isl_dim_in, first + i,
4948 isl_dim_out, i);
4949 return map;
4950 error:
4951 isl_set_free(set);
4952 return NULL;
4955 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4956 unsigned n)
4958 int i, j;
4959 isl_size total;
4961 total = isl_basic_map_dim(bmap, isl_dim_all);
4962 if (total < 0)
4963 return isl_basic_map_free(bmap);
4964 for (i = 0; i < n; ++i) {
4965 j = isl_basic_map_alloc_div(bmap);
4966 if (j < 0)
4967 goto error;
4968 isl_seq_clr(bmap->div[j], 1 + 1 + total);
4970 return bmap;
4971 error:
4972 isl_basic_map_free(bmap);
4973 return NULL;
4976 /* Does "bmap2" apply to the range of "bmap1" (ignoring parameters)?
4978 isl_bool isl_basic_map_applies_range(__isl_keep isl_basic_map *bmap1,
4979 __isl_keep isl_basic_map *bmap2)
4981 isl_space *space1, *space2;
4983 space1 = isl_basic_map_peek_space(bmap1);
4984 space2 = isl_basic_map_peek_space(bmap2);
4985 return isl_space_tuple_is_equal(space1, isl_dim_out,
4986 space2, isl_dim_in);
4989 /* Check that "bmap2" applies to the range of "bmap1" (ignoring parameters).
4991 static isl_stat isl_basic_map_check_applies_range(
4992 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
4994 isl_bool equal;
4996 equal = isl_basic_map_applies_range(bmap1, bmap2);
4997 if (equal < 0)
4998 return isl_stat_error;
4999 if (!equal)
5000 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
5001 "spaces don't match", return isl_stat_error);
5002 return isl_stat_ok;
5005 __isl_give isl_basic_map *isl_basic_map_apply_range(
5006 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
5008 isl_space *space_result = NULL;
5009 struct isl_basic_map *bmap;
5010 isl_size n_in, n_out, n, nparam;
5011 unsigned total, pos;
5012 struct isl_dim_map *dim_map1, *dim_map2;
5014 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
5015 goto error;
5016 if (isl_basic_map_check_applies_range(bmap1, bmap2) < 0)
5017 goto error;
5019 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
5020 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
5021 n = isl_basic_map_dim(bmap1, isl_dim_out);
5022 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
5023 if (n_in < 0 || n_out < 0 || n < 0 || nparam < 0)
5024 goto error;
5026 space_result = isl_space_join(isl_basic_map_get_space(bmap1),
5027 isl_basic_map_get_space(bmap2));
5029 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
5030 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
5031 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
5032 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
5033 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
5034 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
5035 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
5036 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
5037 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
5038 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
5039 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
5041 bmap = isl_basic_map_alloc_space(space_result,
5042 bmap1->n_div + bmap2->n_div + n,
5043 bmap1->n_eq + bmap2->n_eq,
5044 bmap1->n_ineq + bmap2->n_ineq);
5045 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
5046 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
5047 bmap = add_divs(bmap, n);
5048 bmap = isl_basic_map_simplify(bmap);
5049 bmap = isl_basic_map_drop_redundant_divs(bmap);
5050 return isl_basic_map_finalize(bmap);
5051 error:
5052 isl_basic_map_free(bmap1);
5053 isl_basic_map_free(bmap2);
5054 return NULL;
5057 __isl_give isl_basic_set *isl_basic_set_apply(__isl_take isl_basic_set *bset,
5058 __isl_take isl_basic_map *bmap)
5060 if (isl_basic_map_check_compatible_domain(bmap, bset) < 0)
5061 goto error;
5063 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
5064 bmap));
5065 error:
5066 isl_basic_set_free(bset);
5067 isl_basic_map_free(bmap);
5068 return NULL;
5071 __isl_give isl_basic_map *isl_basic_map_apply_domain(
5072 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
5074 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
5075 goto error;
5076 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
5077 bmap2->dim, isl_dim_in))
5078 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
5079 "spaces don't match", goto error);
5081 bmap1 = isl_basic_map_reverse(bmap1);
5082 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
5083 return isl_basic_map_reverse(bmap1);
5084 error:
5085 isl_basic_map_free(bmap1);
5086 isl_basic_map_free(bmap2);
5087 return NULL;
5090 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
5091 * A \cap B -> f(A) + f(B)
5093 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
5094 __isl_take isl_basic_map *bmap2)
5096 isl_size n_in, n_out, nparam;
5097 unsigned total, pos;
5098 struct isl_basic_map *bmap = NULL;
5099 struct isl_dim_map *dim_map1, *dim_map2;
5100 int i;
5102 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
5103 goto error;
5105 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
5106 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
5107 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
5108 if (nparam < 0 || n_in < 0 || n_out < 0)
5109 goto error;
5111 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
5112 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
5113 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
5114 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
5115 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
5116 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
5117 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
5118 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
5119 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
5120 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
5121 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
5123 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
5124 bmap1->n_div + bmap2->n_div + 2 * n_out,
5125 bmap1->n_eq + bmap2->n_eq + n_out,
5126 bmap1->n_ineq + bmap2->n_ineq);
5127 for (i = 0; i < n_out; ++i) {
5128 int j = isl_basic_map_alloc_equality(bmap);
5129 if (j < 0)
5130 goto error;
5131 isl_seq_clr(bmap->eq[j], 1+total);
5132 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
5133 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
5134 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
5136 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
5137 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
5138 bmap = add_divs(bmap, 2 * n_out);
5140 bmap = isl_basic_map_simplify(bmap);
5141 return isl_basic_map_finalize(bmap);
5142 error:
5143 isl_basic_map_free(bmap);
5144 isl_basic_map_free(bmap1);
5145 isl_basic_map_free(bmap2);
5146 return NULL;
5149 /* Given two maps A -> f(A) and B -> g(B), construct a map
5150 * A \cap B -> f(A) + f(B)
5152 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
5153 __isl_take isl_map *map2)
5155 struct isl_map *result;
5156 int i, j;
5158 if (isl_map_check_equal_space(map1, map2) < 0)
5159 goto error;
5161 result = isl_map_alloc_space(isl_space_copy(map1->dim),
5162 map1->n * map2->n, 0);
5163 if (!result)
5164 goto error;
5165 for (i = 0; i < map1->n; ++i)
5166 for (j = 0; j < map2->n; ++j) {
5167 struct isl_basic_map *part;
5168 part = isl_basic_map_sum(
5169 isl_basic_map_copy(map1->p[i]),
5170 isl_basic_map_copy(map2->p[j]));
5171 if (isl_basic_map_is_empty(part))
5172 isl_basic_map_free(part);
5173 else
5174 result = isl_map_add_basic_map(result, part);
5175 if (!result)
5176 goto error;
5178 isl_map_free(map1);
5179 isl_map_free(map2);
5180 return result;
5181 error:
5182 isl_map_free(map1);
5183 isl_map_free(map2);
5184 return NULL;
5187 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
5188 __isl_take isl_set *set2)
5190 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
5193 /* Given a basic map A -> f(A), construct A -> -f(A).
5195 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
5197 int i, j;
5198 unsigned off;
5199 isl_size n;
5201 bmap = isl_basic_map_cow(bmap);
5202 n = isl_basic_map_dim(bmap, isl_dim_out);
5203 if (n < 0)
5204 return isl_basic_map_free(bmap);
5206 off = isl_basic_map_offset(bmap, isl_dim_out);
5207 for (i = 0; i < bmap->n_eq; ++i)
5208 for (j = 0; j < n; ++j)
5209 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
5210 for (i = 0; i < bmap->n_ineq; ++i)
5211 for (j = 0; j < n; ++j)
5212 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
5213 for (i = 0; i < bmap->n_div; ++i)
5214 for (j = 0; j < n; ++j)
5215 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
5216 bmap = isl_basic_map_gauss(bmap, NULL);
5217 return isl_basic_map_finalize(bmap);
5220 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
5222 return isl_basic_map_neg(bset);
5225 /* Given a map A -> f(A), construct A -> -f(A).
5227 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
5229 int i;
5231 map = isl_map_cow(map);
5232 if (!map)
5233 return NULL;
5235 for (i = 0; i < map->n; ++i) {
5236 map->p[i] = isl_basic_map_neg(map->p[i]);
5237 if (!map->p[i])
5238 goto error;
5241 return map;
5242 error:
5243 isl_map_free(map);
5244 return NULL;
5247 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
5249 return set_from_map(isl_map_neg(set_to_map(set)));
5252 /* Given a basic map A -> f(A) and an integer d, construct a basic map
5253 * A -> floor(f(A)/d).
5255 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
5256 isl_int d)
5258 isl_size n_in, n_out, nparam;
5259 unsigned total, pos;
5260 struct isl_basic_map *result = NULL;
5261 struct isl_dim_map *dim_map;
5262 int i;
5264 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5265 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5266 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5267 if (nparam < 0 || n_in < 0 || n_out < 0)
5268 return isl_basic_map_free(bmap);
5270 total = nparam + n_in + n_out + bmap->n_div + n_out;
5271 dim_map = isl_dim_map_alloc(bmap->ctx, total);
5272 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
5273 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
5274 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
5275 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
5277 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
5278 bmap->n_div + n_out,
5279 bmap->n_eq, bmap->n_ineq + 2 * n_out);
5280 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
5281 result = add_divs(result, n_out);
5282 for (i = 0; i < n_out; ++i) {
5283 int j;
5284 j = isl_basic_map_alloc_inequality(result);
5285 if (j < 0)
5286 goto error;
5287 isl_seq_clr(result->ineq[j], 1+total);
5288 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
5289 isl_int_set_si(result->ineq[j][1+pos+i], 1);
5290 j = isl_basic_map_alloc_inequality(result);
5291 if (j < 0)
5292 goto error;
5293 isl_seq_clr(result->ineq[j], 1+total);
5294 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
5295 isl_int_set_si(result->ineq[j][1+pos+i], -1);
5296 isl_int_sub_ui(result->ineq[j][0], d, 1);
5299 result = isl_basic_map_simplify(result);
5300 return isl_basic_map_finalize(result);
5301 error:
5302 isl_basic_map_free(result);
5303 return NULL;
5306 /* Given a map A -> f(A) and an integer d, construct a map
5307 * A -> floor(f(A)/d).
5309 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
5311 int i;
5313 map = isl_map_cow(map);
5314 if (!map)
5315 return NULL;
5317 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5318 for (i = 0; i < map->n; ++i) {
5319 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
5320 if (!map->p[i])
5321 goto error;
5323 map = isl_map_unmark_normalized(map);
5325 return map;
5326 error:
5327 isl_map_free(map);
5328 return NULL;
5331 /* Given a map A -> f(A) and an integer d, construct a map
5332 * A -> floor(f(A)/d).
5334 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
5335 __isl_take isl_val *d)
5337 if (!map || !d)
5338 goto error;
5339 if (!isl_val_is_int(d))
5340 isl_die(isl_val_get_ctx(d), isl_error_invalid,
5341 "expecting integer denominator", goto error);
5342 map = isl_map_floordiv(map, d->n);
5343 isl_val_free(d);
5344 return map;
5345 error:
5346 isl_map_free(map);
5347 isl_val_free(d);
5348 return NULL;
5351 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
5352 unsigned pos)
5354 int i;
5355 isl_size nparam;
5356 isl_size n_in;
5357 isl_size total;
5359 total = isl_basic_map_dim(bmap, isl_dim_all);
5360 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5361 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5362 if (total < 0 || nparam < 0 || n_in < 0)
5363 return isl_basic_map_free(bmap);
5364 i = isl_basic_map_alloc_equality(bmap);
5365 if (i < 0)
5366 goto error;
5367 isl_seq_clr(bmap->eq[i], 1 + total);
5368 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
5369 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
5370 return isl_basic_map_finalize(bmap);
5371 error:
5372 isl_basic_map_free(bmap);
5373 return NULL;
5376 /* Add a constraint to "bmap" expressing i_pos < o_pos
5378 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
5379 unsigned pos)
5381 int i;
5382 isl_size nparam;
5383 isl_size n_in;
5384 isl_size total;
5386 total = isl_basic_map_dim(bmap, isl_dim_all);
5387 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5388 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5389 if (total < 0 || nparam < 0 || n_in < 0)
5390 return isl_basic_map_free(bmap);
5391 i = isl_basic_map_alloc_inequality(bmap);
5392 if (i < 0)
5393 goto error;
5394 isl_seq_clr(bmap->ineq[i], 1 + total);
5395 isl_int_set_si(bmap->ineq[i][0], -1);
5396 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5397 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5398 return isl_basic_map_finalize(bmap);
5399 error:
5400 isl_basic_map_free(bmap);
5401 return NULL;
5404 /* Add a constraint to "bmap" expressing i_pos <= o_pos
5406 static __isl_give isl_basic_map *var_less_or_equal(
5407 __isl_take isl_basic_map *bmap, unsigned pos)
5409 int i;
5410 isl_size nparam;
5411 isl_size n_in;
5412 isl_size total;
5414 total = isl_basic_map_dim(bmap, isl_dim_all);
5415 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5416 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5417 if (total < 0 || nparam < 0 || n_in < 0)
5418 return isl_basic_map_free(bmap);
5419 i = isl_basic_map_alloc_inequality(bmap);
5420 if (i < 0)
5421 goto error;
5422 isl_seq_clr(bmap->ineq[i], 1 + total);
5423 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5424 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5425 return isl_basic_map_finalize(bmap);
5426 error:
5427 isl_basic_map_free(bmap);
5428 return NULL;
5431 /* Add a constraint to "bmap" expressing i_pos > o_pos
5433 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
5434 unsigned pos)
5436 int i;
5437 isl_size nparam;
5438 isl_size n_in;
5439 isl_size total;
5441 total = isl_basic_map_dim(bmap, isl_dim_all);
5442 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5443 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5444 if (total < 0 || nparam < 0 || n_in < 0)
5445 return isl_basic_map_free(bmap);
5446 i = isl_basic_map_alloc_inequality(bmap);
5447 if (i < 0)
5448 goto error;
5449 isl_seq_clr(bmap->ineq[i], 1 + total);
5450 isl_int_set_si(bmap->ineq[i][0], -1);
5451 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5452 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5453 return isl_basic_map_finalize(bmap);
5454 error:
5455 isl_basic_map_free(bmap);
5456 return NULL;
5459 /* Add a constraint to "bmap" expressing i_pos >= o_pos
5461 static __isl_give isl_basic_map *var_more_or_equal(
5462 __isl_take isl_basic_map *bmap, unsigned pos)
5464 int i;
5465 isl_size nparam;
5466 isl_size n_in;
5467 isl_size total;
5469 total = isl_basic_map_dim(bmap, isl_dim_all);
5470 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5471 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5472 if (total < 0 || nparam < 0 || n_in < 0)
5473 return isl_basic_map_free(bmap);
5474 i = isl_basic_map_alloc_inequality(bmap);
5475 if (i < 0)
5476 goto error;
5477 isl_seq_clr(bmap->ineq[i], 1 + total);
5478 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5479 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5480 return isl_basic_map_finalize(bmap);
5481 error:
5482 isl_basic_map_free(bmap);
5483 return NULL;
5486 __isl_give isl_basic_map *isl_basic_map_equal(
5487 __isl_take isl_space *space, unsigned n_equal)
5489 int i;
5490 struct isl_basic_map *bmap;
5491 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
5492 if (!bmap)
5493 return NULL;
5494 for (i = 0; i < n_equal && bmap; ++i)
5495 bmap = var_equal(bmap, i);
5496 return isl_basic_map_finalize(bmap);
5499 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
5501 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
5502 unsigned pos)
5504 int i;
5505 struct isl_basic_map *bmap;
5506 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5507 if (!bmap)
5508 return NULL;
5509 for (i = 0; i < pos && bmap; ++i)
5510 bmap = var_equal(bmap, i);
5511 if (bmap)
5512 bmap = var_less(bmap, pos);
5513 return isl_basic_map_finalize(bmap);
5516 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
5518 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
5519 __isl_take isl_space *space, unsigned pos)
5521 int i;
5522 isl_basic_map *bmap;
5524 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5525 for (i = 0; i < pos; ++i)
5526 bmap = var_equal(bmap, i);
5527 bmap = var_less_or_equal(bmap, pos);
5528 return isl_basic_map_finalize(bmap);
5531 /* Return a relation on "space" expressing i_pos > o_pos
5533 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
5534 unsigned pos)
5536 int i;
5537 struct isl_basic_map *bmap;
5538 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5539 if (!bmap)
5540 return NULL;
5541 for (i = 0; i < pos && bmap; ++i)
5542 bmap = var_equal(bmap, i);
5543 if (bmap)
5544 bmap = var_more(bmap, pos);
5545 return isl_basic_map_finalize(bmap);
5548 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
5550 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
5551 __isl_take isl_space *space, unsigned pos)
5553 int i;
5554 isl_basic_map *bmap;
5556 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5557 for (i = 0; i < pos; ++i)
5558 bmap = var_equal(bmap, i);
5559 bmap = var_more_or_equal(bmap, pos);
5560 return isl_basic_map_finalize(bmap);
5563 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
5564 unsigned n, int equal)
5566 struct isl_map *map;
5567 int i;
5569 if (n == 0 && equal)
5570 return isl_map_universe(space);
5572 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5574 for (i = 0; i + 1 < n; ++i)
5575 map = isl_map_add_basic_map(map,
5576 isl_basic_map_less_at(isl_space_copy(space), i));
5577 if (n > 0) {
5578 if (equal)
5579 map = isl_map_add_basic_map(map,
5580 isl_basic_map_less_or_equal_at(space, n - 1));
5581 else
5582 map = isl_map_add_basic_map(map,
5583 isl_basic_map_less_at(space, n - 1));
5584 } else
5585 isl_space_free(space);
5587 return map;
5590 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
5592 if (!space)
5593 return NULL;
5594 return map_lex_lte_first(space, space->n_out, equal);
5597 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *space,
5598 unsigned n)
5600 return map_lex_lte_first(space, n, 0);
5603 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *space,
5604 unsigned n)
5606 return map_lex_lte_first(space, n, 1);
5609 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_space)
5611 return map_lex_lte(isl_space_map_from_set(set_space), 0);
5614 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_space)
5616 return map_lex_lte(isl_space_map_from_set(set_space), 1);
5619 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5620 unsigned n, int equal)
5622 struct isl_map *map;
5623 int i;
5625 if (n == 0 && equal)
5626 return isl_map_universe(space);
5628 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5630 for (i = 0; i + 1 < n; ++i)
5631 map = isl_map_add_basic_map(map,
5632 isl_basic_map_more_at(isl_space_copy(space), i));
5633 if (n > 0) {
5634 if (equal)
5635 map = isl_map_add_basic_map(map,
5636 isl_basic_map_more_or_equal_at(space, n - 1));
5637 else
5638 map = isl_map_add_basic_map(map,
5639 isl_basic_map_more_at(space, n - 1));
5640 } else
5641 isl_space_free(space);
5643 return map;
5646 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5648 if (!space)
5649 return NULL;
5650 return map_lex_gte_first(space, space->n_out, equal);
5653 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *space,
5654 unsigned n)
5656 return map_lex_gte_first(space, n, 0);
5659 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *space,
5660 unsigned n)
5662 return map_lex_gte_first(space, n, 1);
5665 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_space)
5667 return map_lex_gte(isl_space_map_from_set(set_space), 0);
5670 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_space)
5672 return map_lex_gte(isl_space_map_from_set(set_space), 1);
5675 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5676 __isl_take isl_set *set2)
5678 isl_map *map;
5679 map = isl_map_lex_le(isl_set_get_space(set1));
5680 map = isl_map_intersect_domain(map, set1);
5681 map = isl_map_intersect_range(map, set2);
5682 return map;
5685 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5686 __isl_take isl_set *set2)
5688 isl_map *map;
5689 map = isl_map_lex_lt(isl_set_get_space(set1));
5690 map = isl_map_intersect_domain(map, set1);
5691 map = isl_map_intersect_range(map, set2);
5692 return map;
5695 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5696 __isl_take isl_set *set2)
5698 isl_map *map;
5699 map = isl_map_lex_ge(isl_set_get_space(set1));
5700 map = isl_map_intersect_domain(map, set1);
5701 map = isl_map_intersect_range(map, set2);
5702 return map;
5705 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5706 __isl_take isl_set *set2)
5708 isl_map *map;
5709 map = isl_map_lex_gt(isl_set_get_space(set1));
5710 map = isl_map_intersect_domain(map, set1);
5711 map = isl_map_intersect_range(map, set2);
5712 return map;
5715 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5716 __isl_take isl_map *map2)
5718 isl_map *map;
5719 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5720 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5721 map = isl_map_apply_range(map, isl_map_reverse(map2));
5722 return map;
5725 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5726 __isl_take isl_map *map2)
5728 isl_map *map;
5729 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5730 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5731 map = isl_map_apply_range(map, isl_map_reverse(map2));
5732 return map;
5735 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5736 __isl_take isl_map *map2)
5738 isl_map *map;
5739 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5740 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5741 map = isl_map_apply_range(map, isl_map_reverse(map2));
5742 return map;
5745 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5746 __isl_take isl_map *map2)
5748 isl_map *map;
5749 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5750 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5751 map = isl_map_apply_range(map, isl_map_reverse(map2));
5752 return map;
5755 /* For the div d = floor(f/m) at position "div", add the constraint
5757 * f - m d >= 0
5759 static __isl_give isl_basic_map *add_upper_div_constraint(
5760 __isl_take isl_basic_map *bmap, unsigned div)
5762 int i;
5763 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5764 isl_size n_div;
5765 unsigned pos;
5767 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5768 if (v_div < 0 || n_div < 0)
5769 return isl_basic_map_free(bmap);
5770 pos = v_div + div;
5771 i = isl_basic_map_alloc_inequality(bmap);
5772 if (i < 0)
5773 return isl_basic_map_free(bmap);
5774 isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5775 isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5777 return bmap;
5780 /* For the div d = floor(f/m) at position "div", add the constraint
5782 * -(f-(m-1)) + m d >= 0
5784 static __isl_give isl_basic_map *add_lower_div_constraint(
5785 __isl_take isl_basic_map *bmap, unsigned div)
5787 int i;
5788 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5789 isl_size n_div;
5790 unsigned pos;
5792 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5793 if (v_div < 0 || n_div < 0)
5794 return isl_basic_map_free(bmap);
5795 pos = v_div + div;
5796 i = isl_basic_map_alloc_inequality(bmap);
5797 if (i < 0)
5798 return isl_basic_map_free(bmap);
5799 isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5800 isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5801 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5802 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5804 return bmap;
5807 /* For the div d = floor(f/m) at position "pos", add the constraints
5809 * f - m d >= 0
5810 * -(f-(m-1)) + m d >= 0
5812 * Note that the second constraint is the negation of
5814 * f - m d >= m
5816 __isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5817 __isl_take isl_basic_map *bmap, unsigned pos)
5819 bmap = add_upper_div_constraint(bmap, pos);
5820 bmap = add_lower_div_constraint(bmap, pos);
5821 return bmap;
5824 /* For each known div d = floor(f/m), add the constraints
5826 * f - m d >= 0
5827 * -(f-(m-1)) + m d >= 0
5829 * Remove duplicate constraints in case of some these div constraints
5830 * already appear in "bmap".
5832 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5833 __isl_take isl_basic_map *bmap)
5835 isl_size n_div;
5837 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5838 if (n_div < 0)
5839 return isl_basic_map_free(bmap);
5840 if (n_div == 0)
5841 return bmap;
5843 bmap = add_known_div_constraints(bmap);
5844 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5845 bmap = isl_basic_map_finalize(bmap);
5846 return bmap;
5849 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5851 * In particular, if this div is of the form d = floor(f/m),
5852 * then add the constraint
5854 * f - m d >= 0
5856 * if sign < 0 or the constraint
5858 * -(f-(m-1)) + m d >= 0
5860 * if sign > 0.
5862 __isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5863 __isl_take isl_basic_map *bmap, unsigned div, int sign)
5865 if (sign < 0)
5866 return add_upper_div_constraint(bmap, div);
5867 else
5868 return add_lower_div_constraint(bmap, div);
5871 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5872 __isl_take isl_basic_map *bmap)
5874 isl_space *space;
5876 if (!bmap)
5877 goto error;
5878 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5879 bmap->n_div == 0 &&
5880 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5881 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5882 return bset_from_bmap(bmap);
5883 bmap = isl_basic_map_cow(bmap);
5884 if (!bmap)
5885 return NULL;
5886 space = isl_basic_map_take_space(bmap);
5887 space = isl_space_underlying(space, bmap->n_div);
5888 bmap = isl_basic_map_restore_space(bmap, space);
5889 if (!bmap)
5890 return NULL;
5891 bmap->extra -= bmap->n_div;
5892 bmap->n_div = 0;
5893 bmap = isl_basic_map_finalize(bmap);
5894 return bset_from_bmap(bmap);
5895 error:
5896 isl_basic_map_free(bmap);
5897 return NULL;
5900 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5901 __isl_take isl_basic_set *bset)
5903 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5906 /* Replace each element in "list" by the result of applying
5907 * isl_basic_map_underlying_set to the element.
5909 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5910 __isl_take isl_basic_map_list *list)
5912 int i;
5913 isl_size n;
5915 n = isl_basic_map_list_n_basic_map(list);
5916 if (n < 0)
5917 goto error;
5919 for (i = 0; i < n; ++i) {
5920 isl_basic_map *bmap;
5921 isl_basic_set *bset;
5923 bmap = isl_basic_map_list_get_basic_map(list, i);
5924 bset = isl_basic_set_underlying_set(bmap);
5925 list = isl_basic_set_list_set_basic_set(list, i, bset);
5928 return list;
5929 error:
5930 isl_basic_map_list_free(list);
5931 return NULL;
5934 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5935 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5937 struct isl_basic_map *bmap;
5938 struct isl_ctx *ctx;
5939 isl_size dim, bmap_total;
5940 unsigned total;
5941 int i;
5943 if (!bset || !like)
5944 goto error;
5945 ctx = bset->ctx;
5946 if (isl_basic_set_check_no_params(bset) < 0 ||
5947 isl_basic_set_check_no_locals(bset) < 0)
5948 goto error;
5949 dim = isl_basic_set_dim(bset, isl_dim_set);
5950 bmap_total = isl_basic_map_dim(like, isl_dim_all);
5951 if (dim < 0 || bmap_total < 0)
5952 goto error;
5953 isl_assert(ctx, dim == bmap_total, goto error);
5954 if (like->n_div == 0) {
5955 isl_space *space = isl_basic_map_get_space(like);
5956 isl_basic_map_free(like);
5957 return isl_basic_map_reset_space(bset, space);
5959 bset = isl_basic_set_cow(bset);
5960 if (!bset)
5961 goto error;
5962 total = dim + bset->extra;
5963 bmap = bset_to_bmap(bset);
5964 isl_space_free(isl_basic_map_take_space(bmap));
5965 bmap = isl_basic_map_restore_space(bmap, isl_basic_map_get_space(like));
5966 if (!bmap)
5967 goto error;
5968 bmap->n_div = like->n_div;
5969 bmap->extra += like->n_div;
5970 if (bmap->extra) {
5971 unsigned ltotal;
5972 isl_int **div;
5973 ltotal = total - bmap->extra + like->extra;
5974 if (ltotal > total)
5975 ltotal = total;
5976 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5977 bmap->extra * (1 + 1 + total));
5978 if (isl_blk_is_error(bmap->block2))
5979 goto error;
5980 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5981 if (!div)
5982 goto error;
5983 bmap->div = div;
5984 for (i = 0; i < bmap->extra; ++i)
5985 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5986 for (i = 0; i < like->n_div; ++i) {
5987 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5988 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5990 bmap = isl_basic_map_add_known_div_constraints(bmap);
5992 isl_basic_map_free(like);
5993 bmap = isl_basic_map_simplify(bmap);
5994 bmap = isl_basic_map_finalize(bmap);
5995 return bmap;
5996 error:
5997 isl_basic_map_free(like);
5998 isl_basic_set_free(bset);
5999 return NULL;
6002 __isl_give isl_basic_set *isl_basic_set_from_underlying_set(
6003 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *like)
6005 return bset_from_bmap(isl_basic_map_overlying_set(bset,
6006 bset_to_bmap(like)));
6009 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
6011 int i;
6013 map = isl_map_cow(map);
6014 if (!map)
6015 return NULL;
6016 map->dim = isl_space_cow(map->dim);
6017 if (!map->dim)
6018 goto error;
6020 for (i = 1; i < map->n; ++i)
6021 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
6022 goto error);
6023 for (i = 0; i < map->n; ++i) {
6024 map->p[i] = bset_to_bmap(
6025 isl_basic_map_underlying_set(map->p[i]));
6026 if (!map->p[i])
6027 goto error;
6029 if (map->n == 0)
6030 map->dim = isl_space_underlying(map->dim, 0);
6031 else {
6032 isl_space_free(map->dim);
6033 map->dim = isl_space_copy(map->p[0]->dim);
6035 if (!map->dim)
6036 goto error;
6037 return set_from_map(map);
6038 error:
6039 isl_map_free(map);
6040 return NULL;
6043 /* Replace the space of "bmap" by "space".
6045 * If the space of "bmap" is identical to "space" (including the identifiers
6046 * of the input and output dimensions), then simply return the original input.
6048 __isl_give isl_basic_map *isl_basic_map_reset_space(
6049 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
6051 isl_bool equal;
6052 isl_space *bmap_space;
6054 bmap_space = isl_basic_map_peek_space(bmap);
6055 equal = isl_space_is_equal(bmap_space, space);
6056 if (equal >= 0 && equal)
6057 equal = isl_space_has_equal_ids(bmap_space, space);
6058 if (equal < 0)
6059 goto error;
6060 if (equal) {
6061 isl_space_free(space);
6062 return bmap;
6064 isl_space_free(isl_basic_map_take_space(bmap));
6065 bmap = isl_basic_map_restore_space(bmap, space);
6067 bmap = isl_basic_map_finalize(bmap);
6069 return bmap;
6070 error:
6071 isl_basic_map_free(bmap);
6072 isl_space_free(space);
6073 return NULL;
6076 __isl_give isl_basic_set *isl_basic_set_reset_space(
6077 __isl_take isl_basic_set *bset, __isl_take isl_space *space)
6079 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
6080 space));
6083 /* Check that the total dimensions of "map" and "space" are the same.
6085 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
6086 __isl_keep isl_space *space)
6088 isl_size dim1, dim2;
6090 dim1 = isl_map_dim(map, isl_dim_all);
6091 dim2 = isl_space_dim(space, isl_dim_all);
6092 if (dim1 < 0 || dim2 < 0)
6093 return isl_stat_error;
6094 if (dim1 == dim2)
6095 return isl_stat_ok;
6096 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6097 "total dimensions do not match", return isl_stat_error);
6100 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
6101 __isl_take isl_space *space)
6103 int i;
6105 map = isl_map_cow(map);
6106 if (!map || !space)
6107 goto error;
6109 for (i = 0; i < map->n; ++i) {
6110 map->p[i] = isl_basic_map_reset_space(map->p[i],
6111 isl_space_copy(space));
6112 if (!map->p[i])
6113 goto error;
6115 isl_space_free(isl_map_take_space(map));
6116 map = isl_map_restore_space(map, space);
6118 return map;
6119 error:
6120 isl_map_free(map);
6121 isl_space_free(space);
6122 return NULL;
6125 /* Replace the space of "map" by "space", without modifying
6126 * the dimension of "map".
6128 * If the space of "map" is identical to "space" (including the identifiers
6129 * of the input and output dimensions), then simply return the original input.
6131 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
6132 __isl_take isl_space *space)
6134 isl_bool equal;
6135 isl_space *map_space;
6137 map_space = isl_map_peek_space(map);
6138 equal = isl_space_is_equal(map_space, space);
6139 if (equal >= 0 && equal)
6140 equal = isl_space_has_equal_ids(map_space, space);
6141 if (equal < 0)
6142 goto error;
6143 if (equal) {
6144 isl_space_free(space);
6145 return map;
6147 if (check_map_space_equal_total_dim(map, space) < 0)
6148 goto error;
6149 return isl_map_reset_space(map, space);
6150 error:
6151 isl_map_free(map);
6152 isl_space_free(space);
6153 return NULL;
6156 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
6157 __isl_take isl_space *space)
6159 return set_from_map(isl_map_reset_space(set_to_map(set), space));
6162 /* Compute the parameter domain of the given basic set.
6164 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
6166 isl_bool is_params;
6167 isl_space *space;
6168 isl_size n;
6170 is_params = isl_basic_set_is_params(bset);
6171 if (is_params < 0)
6172 return isl_basic_set_free(bset);
6173 if (is_params)
6174 return bset;
6176 n = isl_basic_set_dim(bset, isl_dim_set);
6177 if (n < 0)
6178 return isl_basic_set_free(bset);
6179 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
6180 space = isl_basic_set_get_space(bset);
6181 space = isl_space_params(space);
6182 bset = isl_basic_set_reset_space(bset, space);
6183 return bset;
6186 /* Construct a zero-dimensional basic set with the given parameter domain.
6188 __isl_give isl_basic_set *isl_basic_set_from_params(
6189 __isl_take isl_basic_set *bset)
6191 isl_space *space;
6192 space = isl_basic_set_get_space(bset);
6193 space = isl_space_set_from_params(space);
6194 bset = isl_basic_set_reset_space(bset, space);
6195 return bset;
6198 /* Compute the parameter domain of the given set.
6200 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
6202 return isl_map_params(set_to_map(set));
6205 /* Construct a zero-dimensional set with the given parameter domain.
6207 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
6209 isl_space *space;
6210 space = isl_set_get_space(set);
6211 space = isl_space_set_from_params(space);
6212 set = isl_set_reset_space(set, space);
6213 return set;
6216 /* Compute the parameter domain of the given map.
6218 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
6220 isl_space *space;
6221 isl_size n_in, n_out;
6223 n_in = isl_map_dim(map, isl_dim_in);
6224 n_out = isl_map_dim(map, isl_dim_out);
6225 if (n_in < 0 || n_out < 0)
6226 return isl_map_free(map);
6227 map = isl_map_project_out(map, isl_dim_in, 0, n_in);
6228 map = isl_map_project_out(map, isl_dim_out, 0, n_out);
6229 space = isl_map_get_space(map);
6230 space = isl_space_params(space);
6231 map = isl_map_reset_space(map, space);
6232 return map;
6235 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
6237 isl_space *space;
6238 isl_size n_out;
6240 n_out = isl_basic_map_dim(bmap, isl_dim_out);
6241 if (n_out < 0)
6242 return isl_basic_map_free(bmap);
6243 space = isl_space_domain(isl_basic_map_get_space(bmap));
6245 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
6247 return isl_basic_map_reset_space(bmap, space);
6250 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
6252 if (!bmap)
6253 return isl_bool_error;
6254 return isl_space_may_be_set(bmap->dim);
6257 /* Is this basic map actually a set?
6258 * Users should never call this function. Outside of isl,
6259 * the type should indicate whether something is a set or a map.
6261 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
6263 if (!bmap)
6264 return isl_bool_error;
6265 return isl_space_is_set(bmap->dim);
6268 __isl_give isl_basic_set *isl_basic_map_range(__isl_take isl_basic_map *bmap)
6270 isl_bool is_set;
6272 is_set = isl_basic_map_is_set(bmap);
6273 if (is_set < 0)
6274 goto error;
6275 if (is_set)
6276 return bmap;
6277 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
6278 error:
6279 isl_basic_map_free(bmap);
6280 return NULL;
6283 __isl_give isl_basic_map *isl_basic_map_domain_map(
6284 __isl_take isl_basic_map *bmap)
6286 int i;
6287 isl_space *space;
6288 isl_basic_map *domain;
6289 isl_size nparam, n_in, n_out;
6291 nparam = isl_basic_map_dim(bmap, isl_dim_param);
6292 n_in = isl_basic_map_dim(bmap, isl_dim_in);
6293 n_out = isl_basic_map_dim(bmap, isl_dim_out);
6294 if (nparam < 0 || n_in < 0 || n_out < 0)
6295 return isl_basic_map_free(bmap);
6297 space = isl_basic_map_get_space(bmap);
6298 space = isl_space_from_range(isl_space_domain(space));
6299 domain = isl_basic_map_universe(space);
6301 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
6302 bmap = isl_basic_map_apply_range(bmap, domain);
6303 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
6305 for (i = 0; i < n_in; ++i)
6306 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
6307 isl_dim_out, i);
6309 bmap = isl_basic_map_gauss(bmap, NULL);
6310 return isl_basic_map_finalize(bmap);
6313 __isl_give isl_basic_map *isl_basic_map_range_map(
6314 __isl_take isl_basic_map *bmap)
6316 int i;
6317 isl_space *space;
6318 isl_basic_map *range;
6319 isl_size nparam, n_in, n_out;
6321 nparam = isl_basic_map_dim(bmap, isl_dim_param);
6322 n_in = isl_basic_map_dim(bmap, isl_dim_in);
6323 n_out = isl_basic_map_dim(bmap, isl_dim_out);
6324 if (nparam < 0 || n_in < 0 || n_out < 0)
6325 return isl_basic_map_free(bmap);
6327 space = isl_basic_map_get_space(bmap);
6328 space = isl_space_from_range(isl_space_range(space));
6329 range = isl_basic_map_universe(space);
6331 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
6332 bmap = isl_basic_map_apply_range(bmap, range);
6333 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
6335 for (i = 0; i < n_out; ++i)
6336 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
6337 isl_dim_out, i);
6339 bmap = isl_basic_map_gauss(bmap, NULL);
6340 return isl_basic_map_finalize(bmap);
6343 int isl_map_may_be_set(__isl_keep isl_map *map)
6345 if (!map)
6346 return -1;
6347 return isl_space_may_be_set(map->dim);
6350 /* Is this map actually a set?
6351 * Users should never call this function. Outside of isl,
6352 * the type should indicate whether something is a set or a map.
6354 isl_bool isl_map_is_set(__isl_keep isl_map *map)
6356 if (!map)
6357 return isl_bool_error;
6358 return isl_space_is_set(map->dim);
6361 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
6363 isl_space *space;
6364 isl_size n_in;
6366 n_in = isl_map_dim(map, isl_dim_in);
6367 if (n_in < 0)
6368 return set_from_map(isl_map_free(map));
6369 space = isl_space_range(isl_map_get_space(map));
6371 map = isl_map_project_out(map, isl_dim_in, 0, n_in);
6373 return set_from_map(isl_map_reset_space(map, space));
6376 /* Transform "map" by applying "fn_space" to its space and "fn_bmap"
6377 * to each of its basic maps.
6379 static __isl_give isl_map *isl_map_transform(__isl_take isl_map *map,
6380 __isl_give isl_space *(*fn_space)(__isl_take isl_space *space),
6381 __isl_give isl_basic_map *(*fn_bmap)(__isl_take isl_basic_map *bmap))
6383 int i;
6384 isl_space *space;
6386 map = isl_map_cow(map);
6387 if (!map)
6388 return NULL;
6390 for (i = 0; i < map->n; ++i) {
6391 map->p[i] = fn_bmap(map->p[i]);
6392 if (!map->p[i])
6393 return isl_map_free(map);
6395 map = isl_map_unmark_normalized(map);
6397 space = isl_map_take_space(map);
6398 space = fn_space(space);
6399 map = isl_map_restore_space(map, space);
6401 return map;
6404 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
6406 return isl_map_transform(map, &isl_space_domain_map,
6407 &isl_basic_map_domain_map);
6410 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
6412 return isl_map_transform(map, &isl_space_range_map,
6413 &isl_basic_map_range_map);
6416 /* Given a wrapped map of the form A[B -> C],
6417 * return the map A[B -> C] -> B.
6419 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
6421 isl_id *id;
6422 isl_map *map;
6424 if (!set)
6425 return NULL;
6426 if (!isl_set_has_tuple_id(set))
6427 return isl_map_domain_map(isl_set_unwrap(set));
6429 id = isl_set_get_tuple_id(set);
6430 map = isl_map_domain_map(isl_set_unwrap(set));
6431 map = isl_map_set_tuple_id(map, isl_dim_in, id);
6433 return map;
6436 __isl_give isl_basic_map *isl_basic_map_from_domain(
6437 __isl_take isl_basic_set *bset)
6439 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
6442 __isl_give isl_basic_map *isl_basic_map_from_range(
6443 __isl_take isl_basic_set *bset)
6445 isl_space *space;
6446 space = isl_basic_set_get_space(bset);
6447 space = isl_space_from_range(space);
6448 bset = isl_basic_set_reset_space(bset, space);
6449 return bset_to_bmap(bset);
6452 /* Create a relation with the given set as range.
6453 * The domain of the created relation is a zero-dimensional
6454 * flat anonymous space.
6456 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
6458 isl_space *space;
6459 space = isl_set_get_space(set);
6460 space = isl_space_from_range(space);
6461 set = isl_set_reset_space(set, space);
6462 return set_to_map(set);
6465 /* Create a relation with the given set as domain.
6466 * The range of the created relation is a zero-dimensional
6467 * flat anonymous space.
6469 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
6471 return isl_map_reverse(isl_map_from_range(set));
6474 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
6475 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
6477 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
6480 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
6481 __isl_take isl_set *range)
6483 return isl_map_apply_range(isl_map_reverse(domain), range);
6486 /* Return a newly allocated isl_map with given space and flags and
6487 * room for "n" basic maps.
6488 * Make sure that all cached information is cleared.
6490 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
6491 unsigned flags)
6493 struct isl_map *map;
6495 if (!space)
6496 return NULL;
6497 if (n < 0)
6498 isl_die(space->ctx, isl_error_internal,
6499 "negative number of basic maps", goto error);
6500 map = isl_calloc(space->ctx, struct isl_map,
6501 sizeof(struct isl_map) +
6502 (n - 1) * sizeof(struct isl_basic_map *));
6503 if (!map)
6504 goto error;
6506 map->ctx = space->ctx;
6507 isl_ctx_ref(map->ctx);
6508 map->ref = 1;
6509 map->size = n;
6510 map->n = 0;
6511 map->dim = space;
6512 map->flags = flags;
6513 return map;
6514 error:
6515 isl_space_free(space);
6516 return NULL;
6519 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
6521 struct isl_basic_map *bmap;
6522 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
6523 bmap = isl_basic_map_set_to_empty(bmap);
6524 return bmap;
6527 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
6529 struct isl_basic_set *bset;
6530 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
6531 bset = isl_basic_set_set_to_empty(bset);
6532 return bset;
6535 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6537 struct isl_basic_map *bmap;
6538 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6539 bmap = isl_basic_map_finalize(bmap);
6540 return bmap;
6543 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6545 struct isl_basic_set *bset;
6546 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6547 bset = isl_basic_set_finalize(bset);
6548 return bset;
6551 __isl_give isl_basic_map *isl_basic_map_nat_universe(
6552 __isl_take isl_space *space)
6554 int i;
6555 isl_size total = isl_space_dim(space, isl_dim_all);
6556 isl_basic_map *bmap;
6558 if (total < 0)
6559 space = isl_space_free(space);
6560 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
6561 for (i = 0; i < total; ++i) {
6562 int k = isl_basic_map_alloc_inequality(bmap);
6563 if (k < 0)
6564 goto error;
6565 isl_seq_clr(bmap->ineq[k], 1 + total);
6566 isl_int_set_si(bmap->ineq[k][1 + i], 1);
6568 return bmap;
6569 error:
6570 isl_basic_map_free(bmap);
6571 return NULL;
6574 __isl_give isl_basic_set *isl_basic_set_nat_universe(
6575 __isl_take isl_space *space)
6577 return isl_basic_map_nat_universe(space);
6580 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *space)
6582 return isl_map_from_basic_map(isl_basic_map_nat_universe(space));
6585 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *space)
6587 return isl_map_nat_universe(space);
6590 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6592 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6595 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6597 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6600 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6602 struct isl_map *map;
6603 if (!space)
6604 return NULL;
6605 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6606 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6607 return map;
6610 /* This function performs the same operation as isl_map_universe,
6611 * but is considered as a function on an isl_space when exported.
6613 __isl_give isl_map *isl_space_universe_map(__isl_take isl_space *space)
6615 return isl_map_universe(space);
6618 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6620 struct isl_set *set;
6621 if (!space)
6622 return NULL;
6623 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6624 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6625 return set;
6628 /* This function performs the same operation as isl_set_universe,
6629 * but is considered as a function on an isl_space when exported.
6631 __isl_give isl_set *isl_space_universe_set(__isl_take isl_space *space)
6633 return isl_set_universe(space);
6636 __isl_give isl_map *isl_map_dup(__isl_keep isl_map *map)
6638 int i;
6639 struct isl_map *dup;
6641 if (!map)
6642 return NULL;
6643 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6644 for (i = 0; i < map->n; ++i)
6645 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6646 return dup;
6649 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6650 __isl_take isl_basic_map *bmap)
6652 if (!bmap || !map)
6653 goto error;
6654 if (isl_basic_map_plain_is_empty(bmap)) {
6655 isl_basic_map_free(bmap);
6656 return map;
6658 if (isl_map_basic_map_check_equal_space(map, bmap) < 0)
6659 goto error;
6660 isl_assert(map->ctx, map->n < map->size, goto error);
6661 map->p[map->n] = bmap;
6662 map->n++;
6663 map = isl_map_unmark_normalized(map);
6664 return map;
6665 error:
6666 if (map)
6667 isl_map_free(map);
6668 if (bmap)
6669 isl_basic_map_free(bmap);
6670 return NULL;
6673 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6675 int i;
6677 if (!map)
6678 return NULL;
6680 if (--map->ref > 0)
6681 return NULL;
6683 clear_caches(map);
6684 isl_ctx_deref(map->ctx);
6685 for (i = 0; i < map->n; ++i)
6686 isl_basic_map_free(map->p[i]);
6687 isl_space_free(map->dim);
6688 free(map);
6690 return NULL;
6693 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6694 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6696 int j;
6697 isl_size total;
6699 total = isl_basic_map_dim(bmap, isl_dim_all);
6700 if (total < 0)
6701 return isl_basic_map_free(bmap);
6703 bmap = isl_basic_map_cow(bmap);
6704 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6705 j = isl_basic_map_alloc_equality(bmap);
6706 if (j < 0)
6707 goto error;
6708 isl_seq_clr(bmap->eq[j] + 1, total);
6709 isl_int_set_si(bmap->eq[j][pos], -1);
6710 isl_int_set_si(bmap->eq[j][0], value);
6711 bmap = isl_basic_map_simplify(bmap);
6712 return isl_basic_map_finalize(bmap);
6713 error:
6714 isl_basic_map_free(bmap);
6715 return NULL;
6718 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6719 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6721 int j;
6722 isl_size total;
6724 total = isl_basic_map_dim(bmap, isl_dim_all);
6725 if (total < 0)
6726 return isl_basic_map_free(bmap);
6728 bmap = isl_basic_map_cow(bmap);
6729 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6730 j = isl_basic_map_alloc_equality(bmap);
6731 if (j < 0)
6732 goto error;
6733 isl_seq_clr(bmap->eq[j] + 1, total);
6734 isl_int_set_si(bmap->eq[j][pos], -1);
6735 isl_int_set(bmap->eq[j][0], value);
6736 bmap = isl_basic_map_simplify(bmap);
6737 return isl_basic_map_finalize(bmap);
6738 error:
6739 isl_basic_map_free(bmap);
6740 return NULL;
6743 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6744 enum isl_dim_type type, unsigned pos, int value)
6746 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6747 return isl_basic_map_free(bmap);
6748 return isl_basic_map_fix_pos_si(bmap,
6749 isl_basic_map_offset(bmap, type) + pos, value);
6752 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6753 enum isl_dim_type type, unsigned pos, isl_int value)
6755 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6756 return isl_basic_map_free(bmap);
6757 return isl_basic_map_fix_pos(bmap,
6758 isl_basic_map_offset(bmap, type) + pos, value);
6761 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6762 * to be equal to "v".
6764 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6765 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6767 if (!bmap || !v)
6768 goto error;
6769 if (!isl_val_is_int(v))
6770 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6771 "expecting integer value", goto error);
6772 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6773 goto error;
6774 pos += isl_basic_map_offset(bmap, type);
6775 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6776 isl_val_free(v);
6777 return bmap;
6778 error:
6779 isl_basic_map_free(bmap);
6780 isl_val_free(v);
6781 return NULL;
6784 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6785 * to be equal to "v".
6787 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6788 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6790 return isl_basic_map_fix_val(bset, type, pos, v);
6793 __isl_give isl_basic_set *isl_basic_set_fix_si(__isl_take isl_basic_set *bset,
6794 enum isl_dim_type type, unsigned pos, int value)
6796 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6797 type, pos, value));
6800 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6801 enum isl_dim_type type, unsigned pos, isl_int value)
6803 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6804 type, pos, value));
6807 /* Remove the basic map at position "i" from "map" if this basic map
6808 * is (obviously) empty.
6810 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6812 isl_bool empty;
6814 if (!map)
6815 return NULL;
6817 empty = isl_basic_map_plain_is_empty(map->p[i]);
6818 if (empty < 0)
6819 return isl_map_free(map);
6820 if (!empty)
6821 return map;
6823 isl_basic_map_free(map->p[i]);
6824 map->n--;
6825 if (i != map->n) {
6826 map->p[i] = map->p[map->n];
6827 map = isl_map_unmark_normalized(map);
6831 return map;
6834 /* Perform "fn" on each basic map of "map", where we may not be holding
6835 * the only reference to "map".
6836 * In particular, "fn" should be a semantics preserving operation
6837 * that we want to apply to all copies of "map". We therefore need
6838 * to be careful not to modify "map" in a way that breaks "map"
6839 * in case anything goes wrong.
6841 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6842 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6844 struct isl_basic_map *bmap;
6845 int i;
6847 if (!map)
6848 return NULL;
6850 for (i = map->n - 1; i >= 0; --i) {
6851 bmap = isl_basic_map_copy(map->p[i]);
6852 bmap = fn(bmap);
6853 if (!bmap)
6854 goto error;
6855 isl_basic_map_free(map->p[i]);
6856 map->p[i] = bmap;
6857 map = remove_if_empty(map, i);
6858 if (!map)
6859 return NULL;
6862 return map;
6863 error:
6864 isl_map_free(map);
6865 return NULL;
6868 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6869 enum isl_dim_type type, unsigned pos, int value)
6871 int i;
6873 map = isl_map_cow(map);
6874 if (isl_map_check_range(map, type, pos, 1) < 0)
6875 return isl_map_free(map);
6876 for (i = map->n - 1; i >= 0; --i) {
6877 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6878 map = remove_if_empty(map, i);
6879 if (!map)
6880 return NULL;
6882 map = isl_map_unmark_normalized(map);
6883 return map;
6886 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6887 enum isl_dim_type type, unsigned pos, int value)
6889 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6892 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6893 enum isl_dim_type type, unsigned pos, isl_int value)
6895 int i;
6897 map = isl_map_cow(map);
6898 if (isl_map_check_range(map, type, pos, 1) < 0)
6899 return isl_map_free(map);
6900 for (i = 0; i < map->n; ++i) {
6901 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6902 if (!map->p[i])
6903 goto error;
6905 map = isl_map_unmark_normalized(map);
6906 return map;
6907 error:
6908 isl_map_free(map);
6909 return NULL;
6912 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6913 enum isl_dim_type type, unsigned pos, isl_int value)
6915 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6918 /* Fix the value of the variable at position "pos" of type "type" of "map"
6919 * to be equal to "v".
6921 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6922 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6924 int i;
6926 map = isl_map_cow(map);
6927 if (!map || !v)
6928 goto error;
6930 if (!isl_val_is_int(v))
6931 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6932 "expecting integer value", goto error);
6933 if (isl_map_check_range(map, type, pos, 1) < 0)
6934 goto error;
6935 for (i = map->n - 1; i >= 0; --i) {
6936 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6937 isl_val_copy(v));
6938 map = remove_if_empty(map, i);
6939 if (!map)
6940 goto error;
6942 map = isl_map_unmark_normalized(map);
6943 isl_val_free(v);
6944 return map;
6945 error:
6946 isl_map_free(map);
6947 isl_val_free(v);
6948 return NULL;
6951 /* Fix the value of the variable at position "pos" of type "type" of "set"
6952 * to be equal to "v".
6954 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6955 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6957 return isl_map_fix_val(set, type, pos, v);
6960 __isl_give isl_map *isl_map_fix_input_si(__isl_take isl_map *map,
6961 unsigned input, int value)
6963 return isl_map_fix_si(map, isl_dim_in, input, value);
6966 __isl_give isl_set *isl_set_fix_dim_si(__isl_take isl_set *set, unsigned dim,
6967 int value)
6969 return set_from_map(isl_map_fix_si(set_to_map(set),
6970 isl_dim_set, dim, value));
6973 static __isl_give isl_basic_map *basic_map_bound_si(
6974 __isl_take isl_basic_map *bmap,
6975 enum isl_dim_type type, unsigned pos, int value, int upper)
6977 int j;
6978 isl_size total;
6980 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6981 return isl_basic_map_free(bmap);
6982 total = isl_basic_map_dim(bmap, isl_dim_all);
6983 if (total < 0)
6984 return isl_basic_map_free(bmap);
6985 pos += isl_basic_map_offset(bmap, type);
6986 bmap = isl_basic_map_cow(bmap);
6987 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6988 j = isl_basic_map_alloc_inequality(bmap);
6989 if (j < 0)
6990 goto error;
6991 isl_seq_clr(bmap->ineq[j], 1 + total);
6992 if (upper) {
6993 isl_int_set_si(bmap->ineq[j][pos], -1);
6994 isl_int_set_si(bmap->ineq[j][0], value);
6995 } else {
6996 isl_int_set_si(bmap->ineq[j][pos], 1);
6997 isl_int_set_si(bmap->ineq[j][0], -value);
6999 bmap = isl_basic_map_simplify(bmap);
7000 return isl_basic_map_finalize(bmap);
7001 error:
7002 isl_basic_map_free(bmap);
7003 return NULL;
7006 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
7007 __isl_take isl_basic_map *bmap,
7008 enum isl_dim_type type, unsigned pos, int value)
7010 return basic_map_bound_si(bmap, type, pos, value, 0);
7013 /* Constrain the values of the given dimension to be no greater than "value".
7015 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
7016 __isl_take isl_basic_map *bmap,
7017 enum isl_dim_type type, unsigned pos, int value)
7019 return basic_map_bound_si(bmap, type, pos, value, 1);
7022 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
7023 enum isl_dim_type type, unsigned pos, int value, int upper)
7025 int i;
7027 map = isl_map_cow(map);
7028 if (isl_map_check_range(map, type, pos, 1) < 0)
7029 return isl_map_free(map);
7030 for (i = 0; i < map->n; ++i) {
7031 map->p[i] = basic_map_bound_si(map->p[i],
7032 type, pos, value, upper);
7033 if (!map->p[i])
7034 goto error;
7036 map = isl_map_unmark_normalized(map);
7037 return map;
7038 error:
7039 isl_map_free(map);
7040 return NULL;
7043 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
7044 enum isl_dim_type type, unsigned pos, int value)
7046 return map_bound_si(map, type, pos, value, 0);
7049 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
7050 enum isl_dim_type type, unsigned pos, int value)
7052 return map_bound_si(map, type, pos, value, 1);
7055 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
7056 enum isl_dim_type type, unsigned pos, int value)
7058 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
7059 type, pos, value));
7062 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
7063 enum isl_dim_type type, unsigned pos, int value)
7065 return isl_map_upper_bound_si(set, type, pos, value);
7068 /* Bound the given variable of "bmap" from below (or above is "upper"
7069 * is set) to "value".
7071 static __isl_give isl_basic_map *basic_map_bound(
7072 __isl_take isl_basic_map *bmap,
7073 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
7075 int j;
7076 isl_size total;
7078 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
7079 return isl_basic_map_free(bmap);
7080 total = isl_basic_map_dim(bmap, isl_dim_all);
7081 if (total < 0)
7082 return isl_basic_map_free(bmap);
7083 pos += isl_basic_map_offset(bmap, type);
7084 bmap = isl_basic_map_cow(bmap);
7085 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
7086 j = isl_basic_map_alloc_inequality(bmap);
7087 if (j < 0)
7088 goto error;
7089 isl_seq_clr(bmap->ineq[j], 1 + total);
7090 if (upper) {
7091 isl_int_set_si(bmap->ineq[j][pos], -1);
7092 isl_int_set(bmap->ineq[j][0], value);
7093 } else {
7094 isl_int_set_si(bmap->ineq[j][pos], 1);
7095 isl_int_neg(bmap->ineq[j][0], value);
7097 bmap = isl_basic_map_simplify(bmap);
7098 return isl_basic_map_finalize(bmap);
7099 error:
7100 isl_basic_map_free(bmap);
7101 return NULL;
7104 /* Bound the given variable of "map" from below (or above is "upper"
7105 * is set) to "value".
7107 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
7108 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
7110 int i;
7112 map = isl_map_cow(map);
7113 if (isl_map_check_range(map, type, pos, 1) < 0)
7114 return isl_map_free(map);
7115 for (i = map->n - 1; i >= 0; --i) {
7116 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
7117 map = remove_if_empty(map, i);
7118 if (!map)
7119 return NULL;
7121 map = isl_map_unmark_normalized(map);
7122 return map;
7125 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
7126 enum isl_dim_type type, unsigned pos, isl_int value)
7128 return map_bound(map, type, pos, value, 0);
7131 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
7132 enum isl_dim_type type, unsigned pos, isl_int value)
7134 return map_bound(map, type, pos, value, 1);
7137 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
7138 enum isl_dim_type type, unsigned pos, isl_int value)
7140 return isl_map_lower_bound(set, type, pos, value);
7143 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
7144 enum isl_dim_type type, unsigned pos, isl_int value)
7146 return isl_map_upper_bound(set, type, pos, value);
7149 /* Force the values of the variable at position "pos" of type "type" of "map"
7150 * to be no smaller than "value".
7152 __isl_give isl_map *isl_map_lower_bound_val(__isl_take isl_map *map,
7153 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
7155 if (!value)
7156 goto error;
7157 if (!isl_val_is_int(value))
7158 isl_die(isl_map_get_ctx(map), isl_error_invalid,
7159 "expecting integer value", goto error);
7160 map = isl_map_lower_bound(map, type, pos, value->n);
7161 isl_val_free(value);
7162 return map;
7163 error:
7164 isl_val_free(value);
7165 isl_map_free(map);
7166 return NULL;
7169 /* Force the values of the variable at position "pos" of type "type" of "set"
7170 * to be no smaller than "value".
7172 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
7173 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
7175 isl_map *map;
7177 map = set_to_map(set);
7178 return set_from_map(isl_map_lower_bound_val(map, type, pos, value));
7181 /* Force the values of the variable at position "pos" of type "type" of "map"
7182 * to be no greater than "value".
7184 __isl_give isl_map *isl_map_upper_bound_val(__isl_take isl_map *map,
7185 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
7187 if (!value)
7188 goto error;
7189 if (!isl_val_is_int(value))
7190 isl_die(isl_map_get_ctx(map), isl_error_invalid,
7191 "expecting integer value", goto error);
7192 map = isl_map_upper_bound(map, type, pos, value->n);
7193 isl_val_free(value);
7194 return map;
7195 error:
7196 isl_val_free(value);
7197 isl_map_free(map);
7198 return NULL;
7201 /* Force the values of the variable at position "pos" of type "type" of "set"
7202 * to be no greater than "value".
7204 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
7205 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
7207 isl_map *map;
7209 map = set_to_map(set);
7210 return set_from_map(isl_map_upper_bound_val(map, type, pos, value));
7213 /* If "mv" has an explicit domain, then intersect the domain of "map"
7214 * with this explicit domain.
7216 * An isl_multi_val object never has an explicit domain,
7217 * so simply return "map".
7219 static __isl_give isl_map *isl_map_intersect_multi_val_explicit_domain(
7220 __isl_take isl_map *map, __isl_keep isl_multi_val *mv)
7222 return map;
7225 #undef BASE
7226 #define BASE val
7227 #include "isl_map_bound_templ.c"
7229 /* Apply "map_bound" to "set" with the corresponding value in "bound"
7230 * for each set dimension, by treating the set as a map.
7232 static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,
7233 __isl_take isl_multi_val *bound,
7234 __isl_give isl_map *map_bound(__isl_take isl_map *map,
7235 unsigned pos, __isl_take isl_val *value))
7237 isl_map *map;
7239 map = set_to_map(set);
7240 return set_from_map(map_bound_multi_val(map, bound, map_bound));
7243 #undef BASE
7244 #define BASE pw_aff
7245 #include "isl_map_bound_templ.c"
7247 /* Apply "map_bound" to "set" with the corresponding value in "bound"
7248 * for each set dimension, by converting the set and the bound
7249 * to objects living in a map space.
7251 static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,
7252 __isl_take isl_multi_pw_aff *bound,
7253 __isl_give isl_map *set_bound(__isl_take isl_map *map,
7254 unsigned pos, __isl_take TYPE *value))
7256 isl_map *map;
7258 map = isl_map_from_range(set);
7259 bound = isl_multi_pw_aff_from_range(bound);
7260 map = map_bound_multi_pw_aff(map, bound, set_bound);
7261 return isl_map_range(map);
7264 /* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,
7265 * setting a bound on the given output dimension.
7267 static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,
7268 unsigned pos, __isl_take isl_val *v)
7270 return isl_map_lower_bound_val(map, isl_dim_out, pos, v);
7273 /* Force the values of the set dimensions of "set"
7274 * to be no smaller than the corresponding values in "lower".
7276 __isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
7277 __isl_take isl_multi_val *lower)
7279 return set_bound_multi_val(set, lower, &map_lower_bound_val);
7282 /* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,
7283 * setting a bound on the given output dimension.
7285 static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,
7286 unsigned pos, __isl_take isl_val *v)
7288 return isl_map_upper_bound_val(map, isl_dim_out, pos, v);
7291 /* Force the values of the set dimensions of "set"
7292 * to be no greater than the corresponding values in "upper".
7294 __isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
7295 __isl_take isl_multi_val *upper)
7297 return set_bound_multi_val(set, upper, &map_upper_bound_val);
7300 /* Force the symbolic constant expression "bound"
7301 * to satisfy the relation "order" with respect to
7302 * the output variable at position "pos" of "map".
7304 * Create an affine expression representing the output variable
7305 * in terms of the range and
7306 * compare it using "order" to "bound" (defined on the domain).
7307 * The result is a relation between elements in domain and range that
7308 * can be intersected with "map".
7310 static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,
7311 unsigned pos, __isl_take isl_pw_aff *bound,
7312 __isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,
7313 __isl_take isl_pw_aff *pa2))
7315 isl_space *space;
7316 isl_local_space *ls;
7317 isl_pw_aff *var;
7319 space = isl_space_range(isl_map_get_space(map));
7320 ls = isl_local_space_from_space(space);
7321 var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);
7322 map = isl_map_intersect(map, order(bound, var));
7323 return map;
7326 /* Force the values of the output variable at position "pos" of "map"
7327 * to be no smaller than the symbolic constant expression "lower".
7329 static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,
7330 unsigned pos, __isl_take isl_pw_aff *lower)
7332 return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);
7335 /* Force the values of the output variable at position "pos" of "map"
7336 * to be no greater than the symbolic constant expression "upper".
7338 static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,
7339 unsigned pos, __isl_take isl_pw_aff *upper)
7341 return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);
7344 /* Force the values of the set dimensions of "set"
7345 * to be no smaller than the corresponding constant symbolic expressions
7346 * in "lower".
7348 __isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
7349 __isl_take isl_multi_pw_aff *lower)
7351 return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);
7354 /* Force the values of the set dimensions of "set"
7355 * to be no greater than the corresponding constant symbolic expressions
7356 * in "upper".
7358 __isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
7359 __isl_take isl_multi_pw_aff *upper)
7361 return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);
7364 /* Force the values of the output dimensions of "map"
7365 * to be no smaller than the corresponding constant symbolic expressions
7366 * in "lower".
7368 __isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
7369 __isl_take isl_multi_pw_aff *lower)
7371 return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);
7374 /* Force the values of the output dimensions of "map"
7375 * to be no greater than the corresponding constant symbolic expressions
7376 * in "upper".
7378 __isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
7379 __isl_take isl_multi_pw_aff *upper)
7381 return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);
7384 /* Bound the given variable of "bset" from below (or above is "upper"
7385 * is set) to "value".
7387 static __isl_give isl_basic_set *isl_basic_set_bound(
7388 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7389 isl_int value, int upper)
7391 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
7392 type, pos, value, upper));
7395 /* Bound the given variable of "bset" from below (or above is "upper"
7396 * is set) to "value".
7398 static __isl_give isl_basic_set *isl_basic_set_bound_val(
7399 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7400 __isl_take isl_val *value, int upper)
7402 if (!value)
7403 goto error;
7404 if (!isl_val_is_int(value))
7405 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
7406 "expecting integer value", goto error);
7407 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
7408 isl_val_free(value);
7409 return bset;
7410 error:
7411 isl_val_free(value);
7412 isl_basic_set_free(bset);
7413 return NULL;
7416 /* Bound the given variable of "bset" from below to "value".
7418 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
7419 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7420 __isl_take isl_val *value)
7422 return isl_basic_set_bound_val(bset, type, pos, value, 0);
7425 /* Bound the given variable of "bset" from above to "value".
7427 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
7428 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7429 __isl_take isl_val *value)
7431 return isl_basic_set_bound_val(bset, type, pos, value, 1);
7434 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
7436 return isl_map_transform(map, &isl_space_reverse,
7437 &isl_basic_map_reverse);
7440 /* Given a map (A -> B) -> C, return the corresponding map (B -> A) -> C.
7442 __isl_give isl_map *isl_map_domain_reverse(__isl_take isl_map *map)
7444 return isl_map_transform(map, &isl_space_domain_reverse,
7445 &isl_basic_map_domain_reverse);
7448 /* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).
7450 __isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)
7452 return isl_map_transform(map, &isl_space_range_reverse,
7453 &isl_basic_map_range_reverse);
7456 /* Given a set (A -> B), return the corresponding set (B -> A).
7458 __isl_give isl_set *isl_set_wrapped_reverse(__isl_take isl_set *set)
7460 isl_map *map = set_to_map(set);
7462 map = isl_map_transform(map, &isl_space_wrapped_reverse,
7463 &isl_basic_map_set_reverse);
7464 return set_from_map(map);
7467 #undef TYPE
7468 #define TYPE isl_pw_multi_aff
7469 #undef SUFFIX
7470 #define SUFFIX _pw_multi_aff
7471 #undef EMPTY
7472 #define EMPTY isl_pw_multi_aff_empty
7473 #undef ADD
7474 #define ADD isl_pw_multi_aff_union_add
7475 #include "isl_map_lexopt_templ.c"
7477 /* Given a map "map", compute the lexicographically minimal
7478 * (or maximal) image element for each domain element in dom,
7479 * in the form of an isl_pw_multi_aff.
7480 * If "empty" is not NULL, then set *empty to those elements in dom that
7481 * do not have an image element.
7482 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7483 * should be computed over the domain of "map". "empty" is also NULL
7484 * in this case.
7486 * We first compute the lexicographically minimal or maximal element
7487 * in the first basic map. This results in a partial solution "res"
7488 * and a subset "todo" of dom that still need to be handled.
7489 * We then consider each of the remaining maps in "map" and successively
7490 * update both "res" and "todo".
7491 * If "empty" is NULL, then the todo sets are not needed and therefore
7492 * also not computed.
7494 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
7495 __isl_take isl_map *map, __isl_take isl_set *dom,
7496 __isl_give isl_set **empty, unsigned flags)
7498 int i;
7499 int full;
7500 isl_pw_multi_aff *res;
7501 isl_set *todo;
7503 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7504 if (!map || (!full && !dom))
7505 goto error;
7507 if (isl_map_plain_is_empty(map)) {
7508 if (empty)
7509 *empty = dom;
7510 else
7511 isl_set_free(dom);
7512 return isl_pw_multi_aff_from_map(map);
7515 res = basic_map_partial_lexopt_pw_multi_aff(
7516 isl_basic_map_copy(map->p[0]),
7517 isl_set_copy(dom), empty, flags);
7519 if (empty)
7520 todo = *empty;
7521 for (i = 1; i < map->n; ++i) {
7522 isl_pw_multi_aff *res_i;
7524 res_i = basic_map_partial_lexopt_pw_multi_aff(
7525 isl_basic_map_copy(map->p[i]),
7526 isl_set_copy(dom), empty, flags);
7528 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
7529 res = isl_pw_multi_aff_union_lexmax(res, res_i);
7530 else
7531 res = isl_pw_multi_aff_union_lexmin(res, res_i);
7533 if (empty)
7534 todo = isl_set_intersect(todo, *empty);
7537 isl_set_free(dom);
7538 isl_map_free(map);
7540 if (empty)
7541 *empty = todo;
7543 return res;
7544 error:
7545 if (empty)
7546 *empty = NULL;
7547 isl_set_free(dom);
7548 isl_map_free(map);
7549 return NULL;
7552 #undef TYPE
7553 #define TYPE isl_map
7554 #undef SUFFIX
7555 #define SUFFIX
7556 #undef EMPTY
7557 #define EMPTY isl_map_empty
7558 #undef ADD
7559 #define ADD isl_map_union_disjoint
7560 #include "isl_map_lexopt_templ.c"
7562 /* Given a map "map", compute the lexicographically minimal
7563 * (or maximal) image element for each domain element in "dom",
7564 * in the form of an isl_map.
7565 * If "empty" is not NULL, then set *empty to those elements in "dom" that
7566 * do not have an image element.
7567 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7568 * should be computed over the domain of "map". "empty" is also NULL
7569 * in this case.
7571 * If the input consists of more than one disjunct, then first
7572 * compute the desired result in the form of an isl_pw_multi_aff and
7573 * then convert that into an isl_map.
7575 * This function used to have an explicit implementation in terms
7576 * of isl_maps, but it would continually intersect the domains of
7577 * partial results with the complement of the domain of the next
7578 * partial solution, potentially leading to an explosion in the number
7579 * of disjuncts if there are several disjuncts in the input.
7580 * An even earlier implementation of this function would look for
7581 * better results in the domain of the partial result and for extra
7582 * results in the complement of this domain, which would lead to
7583 * even more splintering.
7585 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
7586 __isl_take isl_map *map, __isl_take isl_set *dom,
7587 __isl_give isl_set **empty, unsigned flags)
7589 int full;
7590 struct isl_map *res;
7591 isl_pw_multi_aff *pma;
7593 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7594 if (!map || (!full && !dom))
7595 goto error;
7597 if (isl_map_plain_is_empty(map)) {
7598 if (empty)
7599 *empty = dom;
7600 else
7601 isl_set_free(dom);
7602 return map;
7605 if (map->n == 1) {
7606 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
7607 dom, empty, flags);
7608 isl_map_free(map);
7609 return res;
7612 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
7613 flags);
7614 return isl_map_from_pw_multi_aff_internal(pma);
7615 error:
7616 if (empty)
7617 *empty = NULL;
7618 isl_set_free(dom);
7619 isl_map_free(map);
7620 return NULL;
7623 __isl_give isl_map *isl_map_partial_lexmax(
7624 __isl_take isl_map *map, __isl_take isl_set *dom,
7625 __isl_give isl_set **empty)
7627 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
7630 __isl_give isl_map *isl_map_partial_lexmin(
7631 __isl_take isl_map *map, __isl_take isl_set *dom,
7632 __isl_give isl_set **empty)
7634 return isl_map_partial_lexopt(map, dom, empty, 0);
7637 __isl_give isl_set *isl_set_partial_lexmin(
7638 __isl_take isl_set *set, __isl_take isl_set *dom,
7639 __isl_give isl_set **empty)
7641 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
7642 dom, empty));
7645 __isl_give isl_set *isl_set_partial_lexmax(
7646 __isl_take isl_set *set, __isl_take isl_set *dom,
7647 __isl_give isl_set **empty)
7649 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
7650 dom, empty));
7653 /* Compute the lexicographic minimum (or maximum if "flags" includes
7654 * ISL_OPT_MAX) of "bset" over its parametric domain.
7656 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
7657 unsigned flags)
7659 return isl_basic_map_lexopt(bset, flags);
7662 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
7664 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
7667 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
7669 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
7672 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
7674 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
7677 /* Compute the lexicographic minimum of "bset" over its parametric domain
7678 * for the purpose of quantifier elimination.
7679 * That is, find an explicit representation for all the existentially
7680 * quantified variables in "bset" by computing their lexicographic
7681 * minimum.
7683 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
7684 __isl_take isl_basic_set *bset)
7686 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
7689 /* Given a basic map with one output dimension, compute the minimum or
7690 * maximum of that dimension as an isl_pw_aff.
7692 * Compute the optimum as a lexicographic optimum over the single
7693 * output dimension and extract the single isl_pw_aff from the result.
7695 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
7696 int max)
7698 isl_pw_multi_aff *pma;
7699 isl_pw_aff *pwaff;
7701 bmap = isl_basic_map_copy(bmap);
7702 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
7703 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
7704 isl_pw_multi_aff_free(pma);
7706 return pwaff;
7709 /* Compute the minimum or maximum of the given output dimension
7710 * as a function of the parameters and the input dimensions,
7711 * but independently of the other output dimensions.
7713 * We first project out the other output dimension and then compute
7714 * the "lexicographic" maximum in each basic map, combining the results
7715 * using isl_pw_aff_union_max.
7717 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
7718 int max)
7720 int i;
7721 isl_pw_aff *pwaff;
7722 isl_size n_out;
7724 n_out = isl_map_dim(map, isl_dim_out);
7725 if (n_out < 0)
7726 map = isl_map_free(map);
7727 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7728 map = isl_map_project_out(map, isl_dim_out, 0, pos);
7729 if (!map)
7730 return NULL;
7732 if (map->n == 0) {
7733 isl_space *space = isl_map_get_space(map);
7734 isl_map_free(map);
7735 return isl_pw_aff_empty(space);
7738 pwaff = basic_map_dim_opt(map->p[0], max);
7739 for (i = 1; i < map->n; ++i) {
7740 isl_pw_aff *pwaff_i;
7742 pwaff_i = basic_map_dim_opt(map->p[i], max);
7743 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7746 isl_map_free(map);
7748 return pwaff;
7751 /* Compute the minimum of the given output dimension as a function of the
7752 * parameters and input dimensions, but independently of
7753 * the other output dimensions.
7755 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7757 return map_dim_opt(map, pos, 0);
7760 /* Compute the maximum of the given output dimension as a function of the
7761 * parameters and input dimensions, but independently of
7762 * the other output dimensions.
7764 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7766 return map_dim_opt(map, pos, 1);
7769 /* Compute the minimum or maximum of the given set dimension
7770 * as a function of the parameters,
7771 * but independently of the other set dimensions.
7773 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7774 int max)
7776 return map_dim_opt(set, pos, max);
7779 /* Compute the maximum of the given set dimension as a function of the
7780 * parameters, but independently of the other set dimensions.
7782 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7784 return set_dim_opt(set, pos, 1);
7787 /* Compute the minimum of the given set dimension as a function of the
7788 * parameters, but independently of the other set dimensions.
7790 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7792 return set_dim_opt(set, pos, 0);
7795 /* Apply a preimage specified by "mat" on the parameters of "bset".
7796 * bset is assumed to have only parameters and divs.
7798 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7799 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7801 isl_size nparam;
7803 nparam = isl_basic_set_dim(bset, isl_dim_param);
7804 if (nparam < 0 || !mat)
7805 goto error;
7807 bset->dim = isl_space_cow(bset->dim);
7808 if (!bset->dim)
7809 goto error;
7811 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7813 bset->dim->nparam = 0;
7814 bset->dim->n_out = nparam;
7815 bset = isl_basic_set_preimage(bset, mat);
7816 if (bset) {
7817 bset->dim->nparam = bset->dim->n_out;
7818 bset->dim->n_out = 0;
7820 return bset;
7821 error:
7822 isl_mat_free(mat);
7823 isl_basic_set_free(bset);
7824 return NULL;
7827 /* Apply a preimage specified by "mat" on the parameters of "set".
7828 * set is assumed to have only parameters and divs.
7830 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7831 __isl_take isl_mat *mat)
7833 isl_space *space;
7834 isl_size nparam;
7836 nparam = isl_set_dim(set, isl_dim_param);
7837 if (nparam < 0 || !mat)
7838 goto error;
7840 if (mat->n_row != 1 + nparam)
7841 isl_die(isl_set_get_ctx(set), isl_error_internal,
7842 "unexpected number of rows", goto error);
7844 space = isl_set_get_space(set);
7845 space = isl_space_move_dims(space, isl_dim_set, 0,
7846 isl_dim_param, 0, nparam);
7847 set = isl_set_reset_space(set, space);
7848 set = isl_set_preimage(set, mat);
7849 nparam = isl_set_dim(set, isl_dim_out);
7850 if (nparam < 0)
7851 set = isl_set_free(set);
7852 space = isl_set_get_space(set);
7853 space = isl_space_move_dims(space, isl_dim_param, 0,
7854 isl_dim_out, 0, nparam);
7855 set = isl_set_reset_space(set, space);
7856 return set;
7857 error:
7858 isl_mat_free(mat);
7859 isl_set_free(set);
7860 return NULL;
7863 /* Intersect the basic set "bset" with the affine space specified by the
7864 * equalities in "eq".
7866 static __isl_give isl_basic_set *basic_set_append_equalities(
7867 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7869 int i, k;
7870 unsigned len;
7872 if (!bset || !eq)
7873 goto error;
7875 bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);
7876 if (!bset)
7877 goto error;
7879 len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7880 for (i = 0; i < eq->n_row; ++i) {
7881 k = isl_basic_set_alloc_equality(bset);
7882 if (k < 0)
7883 goto error;
7884 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7885 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7887 isl_mat_free(eq);
7889 bset = isl_basic_set_gauss(bset, NULL);
7890 bset = isl_basic_set_finalize(bset);
7892 return bset;
7893 error:
7894 isl_mat_free(eq);
7895 isl_basic_set_free(bset);
7896 return NULL;
7899 /* Intersect the set "set" with the affine space specified by the
7900 * equalities in "eq".
7902 static __isl_give isl_set *set_append_equalities(__isl_take isl_set *set,
7903 __isl_take isl_mat *eq)
7905 int i;
7907 if (!set || !eq)
7908 goto error;
7910 for (i = 0; i < set->n; ++i) {
7911 set->p[i] = basic_set_append_equalities(set->p[i],
7912 isl_mat_copy(eq));
7913 if (!set->p[i])
7914 goto error;
7916 isl_mat_free(eq);
7917 return set;
7918 error:
7919 isl_mat_free(eq);
7920 isl_set_free(set);
7921 return NULL;
7924 /* Given a basic set "bset" that only involves parameters and existentially
7925 * quantified variables, return the index of the first equality
7926 * that only involves parameters. If there is no such equality then
7927 * return bset->n_eq.
7929 * This function assumes that isl_basic_set_gauss has been called on "bset".
7931 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7933 int i, j;
7934 isl_size nparam, n_div;
7936 nparam = isl_basic_set_dim(bset, isl_dim_param);
7937 n_div = isl_basic_set_dim(bset, isl_dim_div);
7938 if (nparam < 0 || n_div < 0)
7939 return -1;
7941 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7942 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7943 ++i;
7946 return i;
7949 /* Compute an explicit representation for the existentially quantified
7950 * variables in "bset" by computing the "minimal value" of the set
7951 * variables. Since there are no set variables, the computation of
7952 * the minimal value essentially computes an explicit representation
7953 * of the non-empty part(s) of "bset".
7955 * The input only involves parameters and existentially quantified variables.
7956 * All equalities among parameters have been removed.
7958 * Since the existentially quantified variables in the result are in general
7959 * going to be different from those in the input, we first replace
7960 * them by the minimal number of variables based on their equalities.
7961 * This should simplify the parametric integer programming.
7963 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7965 isl_morph *morph1, *morph2;
7966 isl_set *set;
7967 isl_size n;
7969 if (!bset)
7970 return NULL;
7971 if (bset->n_eq == 0)
7972 return isl_basic_set_lexmin_compute_divs(bset);
7974 morph1 = isl_basic_set_parameter_compression(bset);
7975 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7976 bset = isl_basic_set_lift(bset);
7977 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7978 bset = isl_morph_basic_set(morph2, bset);
7979 n = isl_basic_set_dim(bset, isl_dim_set);
7980 if (n < 0)
7981 bset = isl_basic_set_free(bset);
7982 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7984 set = isl_basic_set_lexmin_compute_divs(bset);
7986 set = isl_morph_set(isl_morph_inverse(morph1), set);
7988 return set;
7991 /* Project the given basic set onto its parameter domain, possibly introducing
7992 * new, explicit, existential variables in the constraints.
7993 * The input has parameters and (possibly implicit) existential variables.
7994 * The output has the same parameters, but only
7995 * explicit existentially quantified variables.
7997 * The actual projection is performed by pip, but pip doesn't seem
7998 * to like equalities very much, so we first remove the equalities
7999 * among the parameters by performing a variable compression on
8000 * the parameters. Afterward, an inverse transformation is performed
8001 * and the equalities among the parameters are inserted back in.
8003 * The variable compression on the parameters may uncover additional
8004 * equalities that were only implicit before. We therefore check
8005 * if there are any new parameter equalities in the result and
8006 * if so recurse. The removal of parameter equalities is required
8007 * for the parameter compression performed by base_compute_divs.
8009 static __isl_give isl_set *parameter_compute_divs(
8010 __isl_take isl_basic_set *bset)
8012 int i;
8013 struct isl_mat *eq;
8014 struct isl_mat *T, *T2;
8015 struct isl_set *set;
8016 isl_size nparam;
8018 bset = isl_basic_set_cow(bset);
8019 if (!bset)
8020 return NULL;
8022 if (bset->n_eq == 0)
8023 return base_compute_divs(bset);
8025 bset = isl_basic_set_gauss(bset, NULL);
8026 if (!bset)
8027 return NULL;
8028 if (isl_basic_set_plain_is_empty(bset))
8029 return isl_set_from_basic_set(bset);
8031 i = first_parameter_equality(bset);
8032 if (i == bset->n_eq)
8033 return base_compute_divs(bset);
8035 nparam = isl_basic_set_dim(bset, isl_dim_param);
8036 if (nparam < 0)
8037 return isl_set_from_basic_set(isl_basic_set_free(bset));
8038 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
8039 0, 1 + nparam);
8040 eq = isl_mat_cow(eq);
8041 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
8042 if (T && T->n_col == 0) {
8043 isl_mat_free(T);
8044 isl_mat_free(T2);
8045 isl_mat_free(eq);
8046 bset = isl_basic_set_set_to_empty(bset);
8047 return isl_set_from_basic_set(bset);
8049 bset = basic_set_parameter_preimage(bset, T);
8051 i = first_parameter_equality(bset);
8052 if (!bset)
8053 set = NULL;
8054 else if (i == bset->n_eq)
8055 set = base_compute_divs(bset);
8056 else
8057 set = parameter_compute_divs(bset);
8058 set = set_parameter_preimage(set, T2);
8059 set = set_append_equalities(set, eq);
8060 return set;
8063 /* Insert the divs from "ls" before those of "bmap".
8065 * The number of columns is not changed, which means that the last
8066 * dimensions of "bmap" are being reintepreted as the divs from "ls".
8067 * The caller is responsible for removing the same number of dimensions
8068 * from the space of "bmap".
8070 static __isl_give isl_basic_map *insert_divs_from_local_space(
8071 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
8073 int i;
8074 isl_size n_div;
8075 int old_n_div;
8077 n_div = isl_local_space_dim(ls, isl_dim_div);
8078 if (n_div < 0)
8079 return isl_basic_map_free(bmap);
8080 if (n_div == 0)
8081 return bmap;
8083 old_n_div = bmap->n_div;
8084 bmap = insert_div_rows(bmap, n_div);
8085 if (!bmap)
8086 return NULL;
8088 for (i = 0; i < n_div; ++i) {
8089 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
8090 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
8093 return bmap;
8096 /* Replace the space of "bmap" by the space and divs of "ls".
8098 * If "ls" has any divs, then we simplify the result since we may
8099 * have discovered some additional equalities that could simplify
8100 * the div expressions.
8102 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
8103 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
8105 isl_size n_div;
8107 bmap = isl_basic_map_cow(bmap);
8108 n_div = isl_local_space_dim(ls, isl_dim_div);
8109 if (!bmap || n_div < 0)
8110 goto error;
8112 bmap = insert_divs_from_local_space(bmap, ls);
8113 if (!bmap)
8114 goto error;
8116 isl_space_free(bmap->dim);
8117 bmap->dim = isl_local_space_get_space(ls);
8118 if (!bmap->dim)
8119 goto error;
8121 isl_local_space_free(ls);
8122 if (n_div > 0)
8123 bmap = isl_basic_map_simplify(bmap);
8124 bmap = isl_basic_map_finalize(bmap);
8125 return bmap;
8126 error:
8127 isl_basic_map_free(bmap);
8128 isl_local_space_free(ls);
8129 return NULL;
8132 /* Replace the space of "map" by the space and divs of "ls".
8134 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
8135 __isl_take isl_local_space *ls)
8137 int i;
8139 map = isl_map_cow(map);
8140 if (!map || !ls)
8141 goto error;
8143 for (i = 0; i < map->n; ++i) {
8144 map->p[i] = basic_replace_space_by_local_space(map->p[i],
8145 isl_local_space_copy(ls));
8146 if (!map->p[i])
8147 goto error;
8149 isl_space_free(isl_map_take_space(map));
8150 map = isl_map_restore_space(map, isl_local_space_get_space(ls));
8152 isl_local_space_free(ls);
8153 return map;
8154 error:
8155 isl_local_space_free(ls);
8156 isl_map_free(map);
8157 return NULL;
8160 /* Compute an explicit representation for the existentially
8161 * quantified variables for which do not know any explicit representation yet.
8163 * We first sort the existentially quantified variables so that the
8164 * existentially quantified variables for which we already have an explicit
8165 * representation are placed before those for which we do not.
8166 * The input dimensions, the output dimensions and the existentially
8167 * quantified variables for which we already have an explicit
8168 * representation are then turned into parameters.
8169 * compute_divs returns a map with the same parameters and
8170 * no input or output dimensions and the dimension specification
8171 * is reset to that of the input, including the existentially quantified
8172 * variables for which we already had an explicit representation.
8174 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
8176 struct isl_basic_set *bset;
8177 struct isl_set *set;
8178 struct isl_map *map;
8179 isl_space *space;
8180 isl_local_space *ls;
8181 isl_size nparam;
8182 isl_size n_in;
8183 isl_size n_out;
8184 int n_known;
8185 int i;
8187 bmap = isl_basic_map_sort_divs(bmap);
8188 bmap = isl_basic_map_cow(bmap);
8189 if (!bmap)
8190 return NULL;
8192 n_known = isl_basic_map_first_unknown_div(bmap);
8193 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8194 n_in = isl_basic_map_dim(bmap, isl_dim_in);
8195 n_out = isl_basic_map_dim(bmap, isl_dim_out);
8196 if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
8197 return isl_map_from_basic_map(isl_basic_map_free(bmap));
8199 space = isl_space_set_alloc(bmap->ctx,
8200 nparam + n_in + n_out + n_known, 0);
8201 if (!space)
8202 goto error;
8204 ls = isl_basic_map_get_local_space(bmap);
8205 ls = isl_local_space_drop_dims(ls, isl_dim_div,
8206 n_known, bmap->n_div - n_known);
8207 if (n_known > 0) {
8208 for (i = n_known; i < bmap->n_div; ++i)
8209 swap_div(bmap, i - n_known, i);
8210 bmap->n_div -= n_known;
8211 bmap->extra -= n_known;
8213 bmap = isl_basic_map_reset_space(bmap, space);
8214 bset = bset_from_bmap(bmap);
8216 set = parameter_compute_divs(bset);
8217 map = set_to_map(set);
8218 map = replace_space_by_local_space(map, ls);
8220 return map;
8221 error:
8222 isl_basic_map_free(bmap);
8223 return NULL;
8226 /* Is the integer division at position "div" of "bmap" integral?
8227 * That is, does it have denominator 1?
8229 isl_bool isl_basic_map_div_is_integral(__isl_keep isl_basic_map *bmap, int div)
8231 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
8232 return isl_bool_error;
8233 return isl_int_is_one(bmap->div[div][0]);
8236 /* Remove the explicit representation of local variable "div",
8237 * if there is any.
8239 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
8240 __isl_take isl_basic_map *bmap, int div)
8242 isl_bool unknown;
8244 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
8245 if (unknown < 0)
8246 return isl_basic_map_free(bmap);
8247 if (unknown)
8248 return bmap;
8250 bmap = isl_basic_map_cow(bmap);
8251 if (!bmap)
8252 return NULL;
8253 isl_int_set_si(bmap->div[div][0], 0);
8254 return bmap;
8257 /* Is local variable "div" of "bmap" marked as not having an explicit
8258 * representation?
8259 * Note that even if "div" is not marked in this way and therefore
8260 * has an explicit representation, this representation may still
8261 * depend (indirectly) on other local variables that do not
8262 * have an explicit representation.
8264 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
8265 int div)
8267 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
8268 return isl_bool_error;
8269 return isl_int_is_zero(bmap->div[div][0]);
8272 /* Return the position of the first local variable that does not
8273 * have an explicit representation.
8274 * Return the total number of local variables if they all have
8275 * an explicit representation.
8276 * Return -1 on error.
8278 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
8280 int i;
8282 if (!bmap)
8283 return -1;
8285 for (i = 0; i < bmap->n_div; ++i) {
8286 if (!isl_basic_map_div_is_known(bmap, i))
8287 return i;
8289 return bmap->n_div;
8292 /* Return the position of the first local variable that does not
8293 * have an explicit representation.
8294 * Return the total number of local variables if they all have
8295 * an explicit representation.
8296 * Return -1 on error.
8298 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
8300 return isl_basic_map_first_unknown_div(bset);
8303 /* Does "bmap" have an explicit representation for all local variables?
8305 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
8307 int first;
8308 isl_size n;
8310 n = isl_basic_map_dim(bmap, isl_dim_div);
8311 first = isl_basic_map_first_unknown_div(bmap);
8312 if (n < 0 || first < 0)
8313 return isl_bool_error;
8314 return first == n;
8317 /* Do all basic maps in "map" have an explicit representation
8318 * for all local variables?
8320 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
8322 int i;
8324 if (!map)
8325 return isl_bool_error;
8327 for (i = 0; i < map->n; ++i) {
8328 int known = isl_basic_map_divs_known(map->p[i]);
8329 if (known <= 0)
8330 return known;
8333 return isl_bool_true;
8336 /* If bmap contains any unknown divs, then compute explicit
8337 * expressions for them. However, this computation may be
8338 * quite expensive, so first try to remove divs that aren't
8339 * strictly needed.
8341 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
8343 int known;
8344 struct isl_map *map;
8346 known = isl_basic_map_divs_known(bmap);
8347 if (known < 0)
8348 goto error;
8349 if (known)
8350 return isl_map_from_basic_map(bmap);
8352 bmap = isl_basic_map_drop_redundant_divs(bmap);
8354 known = isl_basic_map_divs_known(bmap);
8355 if (known < 0)
8356 goto error;
8357 if (known)
8358 return isl_map_from_basic_map(bmap);
8360 map = compute_divs(bmap);
8361 return map;
8362 error:
8363 isl_basic_map_free(bmap);
8364 return NULL;
8367 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
8369 int i;
8370 int known;
8371 struct isl_map *res;
8373 if (!map)
8374 return NULL;
8375 if (map->n == 0)
8376 return map;
8378 known = isl_map_divs_known(map);
8379 if (known < 0) {
8380 isl_map_free(map);
8381 return NULL;
8383 if (known)
8384 return map;
8386 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
8387 for (i = 1 ; i < map->n; ++i) {
8388 struct isl_map *r2;
8389 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
8390 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
8391 res = isl_map_union_disjoint(res, r2);
8392 else
8393 res = isl_map_union(res, r2);
8395 isl_map_free(map);
8397 return res;
8400 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
8402 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
8405 __isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set)
8407 return set_from_map(isl_map_compute_divs(set_to_map(set)));
8410 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
8412 isl_space *space;
8413 isl_size n_out;
8415 n_out = isl_map_dim(map, isl_dim_out);
8416 if (n_out < 0)
8417 return set_from_map(isl_map_free(map));
8418 space = isl_space_domain(isl_map_get_space(map));
8420 map = isl_map_project_out(map, isl_dim_out, 0, n_out);
8422 return set_from_map(isl_map_reset_space(map, space));
8425 /* Return the union of "map1" and "map2", where we assume for now that
8426 * "map1" and "map2" are disjoint. Note that the basic maps inside
8427 * "map1" or "map2" may not be disjoint from each other.
8428 * Also note that this function is also called from isl_map_union,
8429 * which takes care of handling the situation where "map1" and "map2"
8430 * may not be disjoint.
8432 * If one of the inputs is empty, we can simply return the other input.
8433 * Similarly, if one of the inputs is universal, then it is equal to the union.
8435 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
8436 __isl_take isl_map *map2)
8438 int i;
8439 unsigned flags = 0;
8440 struct isl_map *map = NULL;
8441 int is_universe;
8443 if (isl_map_check_equal_space(map1, map2) < 0)
8444 goto error;
8446 if (map1->n == 0) {
8447 isl_map_free(map1);
8448 return map2;
8450 if (map2->n == 0) {
8451 isl_map_free(map2);
8452 return map1;
8455 is_universe = isl_map_plain_is_universe(map1);
8456 if (is_universe < 0)
8457 goto error;
8458 if (is_universe) {
8459 isl_map_free(map2);
8460 return map1;
8463 is_universe = isl_map_plain_is_universe(map2);
8464 if (is_universe < 0)
8465 goto error;
8466 if (is_universe) {
8467 isl_map_free(map1);
8468 return map2;
8471 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
8472 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
8473 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8475 map = isl_map_alloc_space(isl_space_copy(map1->dim),
8476 map1->n + map2->n, flags);
8477 if (!map)
8478 goto error;
8479 for (i = 0; i < map1->n; ++i) {
8480 map = isl_map_add_basic_map(map,
8481 isl_basic_map_copy(map1->p[i]));
8482 if (!map)
8483 goto error;
8485 for (i = 0; i < map2->n; ++i) {
8486 map = isl_map_add_basic_map(map,
8487 isl_basic_map_copy(map2->p[i]));
8488 if (!map)
8489 goto error;
8491 isl_map_free(map1);
8492 isl_map_free(map2);
8493 return map;
8494 error:
8495 isl_map_free(map);
8496 isl_map_free(map1);
8497 isl_map_free(map2);
8498 return NULL;
8501 /* Return the union of "map1" and "map2", where "map1" and "map2" are
8502 * guaranteed to be disjoint by the caller.
8504 * Note that this functions is called from within isl_map_make_disjoint,
8505 * so we have to be careful not to touch the constraints of the inputs
8506 * in any way.
8508 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
8509 __isl_take isl_map *map2)
8511 isl_map_align_params_bin(&map1, &map2);
8512 return map_union_disjoint(map1, map2);
8515 /* Return the union of "map1" and "map2", where "map1" and "map2" may
8516 * not be disjoint.
8518 * We currently simply call map_union_disjoint, the internal operation
8519 * of which does not really depend on the inputs being disjoint.
8520 * If the result contains more than one basic map, then we clear
8521 * the disjoint flag since the result may contain basic maps from
8522 * both inputs and these are not guaranteed to be disjoint.
8524 * As a special case, if "map1" and "map2" are obviously equal,
8525 * then we simply return "map1".
8527 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
8528 __isl_take isl_map *map2)
8530 int equal;
8532 if (isl_map_align_params_bin(&map1, &map2) < 0)
8533 goto error;
8535 equal = isl_map_plain_is_equal(map1, map2);
8536 if (equal < 0)
8537 goto error;
8538 if (equal) {
8539 isl_map_free(map2);
8540 return map1;
8543 map1 = map_union_disjoint(map1, map2);
8544 if (!map1)
8545 return NULL;
8546 if (map1->n > 1)
8547 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
8548 return map1;
8549 error:
8550 isl_map_free(map1);
8551 isl_map_free(map2);
8552 return NULL;
8555 __isl_give isl_set *isl_set_union_disjoint(
8556 __isl_take isl_set *set1, __isl_take isl_set *set2)
8558 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
8559 set_to_map(set2)));
8562 __isl_give isl_set *isl_set_union(__isl_take isl_set *set1,
8563 __isl_take isl_set *set2)
8565 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
8568 /* Apply "fn" to pairs of elements from "map" and "set" and collect
8569 * the results in a map living in "space".
8571 * "map" and "set" are assumed to be compatible and non-NULL.
8573 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
8574 __isl_take isl_space *space, __isl_take isl_set *set,
8575 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
8576 __isl_take isl_basic_set *bset))
8578 unsigned flags = 0;
8579 struct isl_map *result;
8580 int i, j;
8582 if (isl_set_plain_is_universe(set)) {
8583 isl_set_free(set);
8584 return isl_map_reset_equal_dim_space(map, space);
8587 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
8588 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
8589 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8591 result = isl_map_alloc_space(space, map->n * set->n, flags);
8592 for (i = 0; result && i < map->n; ++i)
8593 for (j = 0; j < set->n; ++j) {
8594 result = isl_map_add_basic_map(result,
8595 fn(isl_basic_map_copy(map->p[i]),
8596 isl_basic_set_copy(set->p[j])));
8597 if (!result)
8598 break;
8601 isl_map_free(map);
8602 isl_set_free(set);
8603 return result;
8606 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
8607 __isl_take isl_set *set)
8609 isl_bool ok;
8610 isl_space *space;
8612 isl_map_align_params_set(&map, &set);
8613 ok = isl_map_compatible_range(map, set);
8614 if (ok < 0)
8615 goto error;
8616 if (!ok)
8617 isl_die(set->ctx, isl_error_invalid,
8618 "incompatible spaces", goto error);
8620 space = isl_map_get_space(map);
8621 return map_intersect_set(map, space, set,
8622 &isl_basic_map_intersect_range);
8623 error:
8624 isl_map_free(map);
8625 isl_set_free(set);
8626 return NULL;
8629 /* Intersect the domain of "map" with "set".
8631 * If the domain dimensions of "map" do not have any identifiers,
8632 * then copy them over from "set".
8634 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
8635 __isl_take isl_set *set)
8637 isl_bool ok;
8638 isl_space *space;
8640 isl_map_align_params_set(&map, &set);
8641 ok = isl_map_compatible_domain(map, set);
8642 if (ok < 0)
8643 goto error;
8644 if (!ok)
8645 isl_die(set->ctx, isl_error_invalid,
8646 "incompatible spaces", goto error);
8648 space = isl_map_get_space(map);
8649 space = isl_space_copy_ids_if_unset(space, isl_dim_in,
8650 isl_set_peek_space(set), isl_dim_set);
8651 return map_intersect_set(map, space, set,
8652 &isl_basic_map_intersect_domain);
8653 error:
8654 isl_map_free(map);
8655 isl_set_free(set);
8656 return NULL;
8659 #undef BASE
8660 #define BASE map
8661 static
8662 #include "isl_copy_tuple_id_templ.c"
8664 /* Data structure that specifies how isl_map_intersect_factor
8665 * should operate.
8667 * "preserve_type" is the tuple where the factor differs from
8668 * the input map and of which the identifiers needs
8669 * to be preserved explicitly.
8670 * "other_factor" is used to extract the space of the other factor
8671 * from the space of the product ("map").
8672 * "product" is used to combine the given factor and a universe map
8673 * in the space returned by "other_factor" to produce a map
8674 * that lives in the same space as the input map.
8676 struct isl_intersect_factor_control {
8677 enum isl_dim_type preserve_type;
8678 __isl_give isl_space *(*other_factor)(__isl_take isl_space *space);
8679 __isl_give isl_map *(*product)(__isl_take isl_map *factor,
8680 __isl_take isl_map *other);
8683 /* Given a map "map" in some product space and a map "factor"
8684 * living in some factor space, return the intersection.
8686 * After aligning the parameters,
8687 * the map "factor" is first extended to a map living in the same space
8688 * as "map" and then a regular intersection is computed.
8690 * Note that the extension is computed as a product, which is anonymous
8691 * by default. If "map" has an identifier on the corresponding tuple,
8692 * then this identifier needs to be set on the product
8693 * before the intersection is computed.
8695 static __isl_give isl_map *isl_map_intersect_factor(
8696 __isl_take isl_map *map, __isl_take isl_map *factor,
8697 struct isl_intersect_factor_control *control)
8699 isl_bool equal;
8700 isl_space *space;
8701 isl_map *other, *product;
8703 equal = isl_map_has_equal_params(map, factor);
8704 if (equal < 0)
8705 goto error;
8706 if (!equal) {
8707 map = isl_map_align_params(map, isl_map_get_space(factor));
8708 factor = isl_map_align_params(factor, isl_map_get_space(map));
8711 space = isl_map_get_space(map);
8712 other = isl_map_universe(control->other_factor(space));
8713 product = control->product(factor, other);
8715 space = isl_map_peek_space(map);
8716 product = isl_map_copy_tuple_id(product, control->preserve_type,
8717 space, control->preserve_type);
8718 return map_intersect(map, product);
8719 error:
8720 isl_map_free(map);
8721 isl_map_free(factor);
8722 return NULL;
8725 /* Return the domain product of "map2" and "map1".
8727 static __isl_give isl_map *isl_map_reverse_domain_product(
8728 __isl_take isl_map *map1, __isl_take isl_map *map2)
8730 return isl_map_domain_product(map2, map1);
8733 /* Return the range product of "map2" and "map1".
8735 static __isl_give isl_map *isl_map_reverse_range_product(
8736 __isl_take isl_map *map1, __isl_take isl_map *map2)
8738 return isl_map_range_product(map2, map1);
8741 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8742 * in the space A -> C, return the intersection.
8744 __isl_give isl_map *isl_map_intersect_domain_factor_domain(
8745 __isl_take isl_map *map, __isl_take isl_map *factor)
8747 struct isl_intersect_factor_control control = {
8748 .preserve_type = isl_dim_in,
8749 .other_factor = isl_space_domain_factor_range,
8750 .product = isl_map_domain_product,
8753 return isl_map_intersect_factor(map, factor, &control);
8756 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8757 * in the space B -> C, return the intersection.
8759 __isl_give isl_map *isl_map_intersect_domain_factor_range(
8760 __isl_take isl_map *map, __isl_take isl_map *factor)
8762 struct isl_intersect_factor_control control = {
8763 .preserve_type = isl_dim_in,
8764 .other_factor = isl_space_domain_factor_domain,
8765 .product = isl_map_reverse_domain_product,
8768 return isl_map_intersect_factor(map, factor, &control);
8771 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8772 * in the space A -> B, return the intersection.
8774 __isl_give isl_map *isl_map_intersect_range_factor_domain(
8775 __isl_take isl_map *map, __isl_take isl_map *factor)
8777 struct isl_intersect_factor_control control = {
8778 .preserve_type = isl_dim_out,
8779 .other_factor = isl_space_range_factor_range,
8780 .product = isl_map_range_product,
8783 return isl_map_intersect_factor(map, factor, &control);
8786 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8787 * in the space A -> C, return the intersection.
8789 __isl_give isl_map *isl_map_intersect_range_factor_range(
8790 __isl_take isl_map *map, __isl_take isl_map *factor)
8792 struct isl_intersect_factor_control control = {
8793 .preserve_type = isl_dim_out,
8794 .other_factor = isl_space_range_factor_domain,
8795 .product = isl_map_reverse_range_product,
8798 return isl_map_intersect_factor(map, factor, &control);
8801 /* Given a set "set" in a space [A -> B] and a set "domain"
8802 * in the space A, return the intersection.
8804 * The set "domain" is first extended to a set living in the space
8805 * [A -> B] and then a regular intersection is computed.
8807 __isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
8808 __isl_take isl_set *domain)
8810 struct isl_intersect_factor_control control = {
8811 .preserve_type = isl_dim_set,
8812 .other_factor = isl_space_factor_range,
8813 .product = isl_map_range_product,
8816 return set_from_map(isl_map_intersect_factor(set_to_map(set),
8817 set_to_map(domain), &control));
8820 /* Given a set "set" in a space [A -> B] and a set "range"
8821 * in the space B, return the intersection.
8823 * The set "range" is first extended to a set living in the space
8824 * [A -> B] and then a regular intersection is computed.
8826 __isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
8827 __isl_take isl_set *range)
8829 struct isl_intersect_factor_control control = {
8830 .preserve_type = isl_dim_set,
8831 .other_factor = isl_space_factor_domain,
8832 .product = isl_map_reverse_range_product,
8835 return set_from_map(isl_map_intersect_factor(set_to_map(set),
8836 set_to_map(range), &control));
8839 #undef BASE
8840 #define BASE set
8841 static
8842 #include "isl_copy_tuple_id_templ.c"
8844 /* Given a map "map" in a space [A -> B] -> C and a set "domain"
8845 * in the space A, return the intersection.
8847 * The set "domain" is extended to a set living in the space [A -> B] and
8848 * the domain of "map" is intersected with this set.
8850 * If "map" has an identifier on the domain tuple,
8851 * then this identifier needs to be set on this product
8852 * before the intersection is computed.
8854 __isl_give isl_map *isl_map_intersect_domain_wrapped_domain(
8855 __isl_take isl_map *map, __isl_take isl_set *domain)
8857 isl_space *space;
8858 isl_set *factor;
8860 isl_map_align_params_set(&map, &domain);
8861 space = isl_map_get_space(map);
8862 space = isl_space_domain_wrapped_range(space);
8863 factor = isl_set_universe(space);
8864 domain = isl_set_product(domain, factor);
8865 space = isl_map_peek_space(map);
8866 domain = isl_set_copy_tuple_id(domain, isl_dim_set, space, isl_dim_in);
8867 return isl_map_intersect_domain(map, domain);
8870 /* Given a map "map" in a space A -> [B -> C] and a set "domain"
8871 * in the space B, return the intersection.
8873 * The set "domain" is extended to a set living in the space [B -> C] and
8874 * the range of "map" is intersected with this set.
8876 * If "map" has an identifier on the range tuple,
8877 * then this identifier needs to be set on this product
8878 * before the intersection is computed.
8880 __isl_give isl_map *isl_map_intersect_range_wrapped_domain(
8881 __isl_take isl_map *map, __isl_take isl_set *domain)
8883 isl_space *space;
8884 isl_set *factor;
8886 isl_map_align_params_set(&map, &domain);
8887 space = isl_map_get_space(map);
8888 space = isl_space_range_wrapped_range(space);
8889 factor = isl_set_universe(space);
8890 domain = isl_set_product(domain, factor);
8891 space = isl_map_peek_space(map);
8892 domain = isl_set_copy_tuple_id(domain, isl_dim_set, space, isl_dim_out);
8893 return isl_map_intersect_range(map, domain);
8896 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8897 __isl_take isl_map *map2)
8899 if (isl_map_align_params_bin(&map1, &map2) < 0)
8900 goto error;
8901 map1 = isl_map_reverse(map1);
8902 map1 = isl_map_apply_range(map1, map2);
8903 return isl_map_reverse(map1);
8904 error:
8905 isl_map_free(map1);
8906 isl_map_free(map2);
8907 return NULL;
8910 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8911 __isl_take isl_map *map2)
8913 isl_space *space;
8914 struct isl_map *result;
8915 int i, j;
8917 if (isl_map_align_params_bin(&map1, &map2) < 0)
8918 goto error;
8920 space = isl_space_join(isl_space_copy(map1->dim),
8921 isl_space_copy(map2->dim));
8923 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
8924 if (!result)
8925 goto error;
8926 for (i = 0; i < map1->n; ++i)
8927 for (j = 0; j < map2->n; ++j) {
8928 result = isl_map_add_basic_map(result,
8929 isl_basic_map_apply_range(
8930 isl_basic_map_copy(map1->p[i]),
8931 isl_basic_map_copy(map2->p[j])));
8932 if (!result)
8933 goto error;
8935 isl_map_free(map1);
8936 isl_map_free(map2);
8937 if (result && result->n <= 1)
8938 ISL_F_SET(result, ISL_MAP_DISJOINT);
8939 return result;
8940 error:
8941 isl_map_free(map1);
8942 isl_map_free(map2);
8943 return NULL;
8946 /* Is "bmap" a transformation, i.e.,
8947 * does it relate elements from the same space.
8949 isl_bool isl_basic_map_is_transformation(__isl_keep isl_basic_map *bmap)
8951 isl_space *space;
8953 space = isl_basic_map_peek_space(bmap);
8954 return isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8957 /* Check that "bmap" is a transformation, i.e.,
8958 * that it relates elements from the same space.
8960 static isl_stat isl_basic_map_check_transformation(
8961 __isl_keep isl_basic_map *bmap)
8963 isl_bool equal;
8965 equal = isl_basic_map_is_transformation(bmap);
8966 if (equal < 0)
8967 return isl_stat_error;
8968 if (!equal)
8969 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
8970 "domain and range don't match", return isl_stat_error);
8971 return isl_stat_ok;
8975 * returns range - domain
8977 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8979 isl_space *target_space;
8980 struct isl_basic_set *bset;
8981 isl_size dim;
8982 isl_size nparam;
8983 isl_size total;
8984 int i;
8986 if (isl_basic_map_check_transformation(bmap) < 0)
8987 return isl_basic_map_free(bmap);
8988 dim = isl_basic_map_dim(bmap, isl_dim_in);
8989 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8990 if (dim < 0 || nparam < 0)
8991 goto error;
8992 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8993 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8994 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8995 total = isl_basic_map_dim(bmap, isl_dim_all);
8996 if (total < 0)
8997 bmap = isl_basic_map_free(bmap);
8998 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8999 for (i = 0; i < dim; ++i) {
9000 int j = isl_basic_map_alloc_equality(bmap);
9001 if (j < 0) {
9002 bmap = isl_basic_map_free(bmap);
9003 break;
9005 isl_seq_clr(bmap->eq[j], 1 + total);
9006 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
9007 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
9008 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
9010 bset = isl_basic_map_domain(bmap);
9011 bset = isl_basic_set_reset_space(bset, target_space);
9012 return bset;
9013 error:
9014 isl_basic_map_free(bmap);
9015 return NULL;
9018 /* Is the tuple of type "type1" of "map" the same as
9019 * the tuple of type "type2" of "space"?
9021 isl_bool isl_map_space_tuple_is_equal(__isl_keep isl_map *map,
9022 enum isl_dim_type type1, __isl_keep isl_space *space,
9023 enum isl_dim_type type2)
9025 isl_space *map_space;
9027 map_space = isl_map_peek_space(map);
9028 return isl_space_tuple_is_equal(map_space, type1, space, type2);
9031 /* Is the tuple of type "type1" of "map1" the same as
9032 * the tuple of type "type2" of "map2"?
9034 isl_bool isl_map_tuple_is_equal(__isl_keep isl_map *map1,
9035 enum isl_dim_type type1, __isl_keep isl_map *map2,
9036 enum isl_dim_type type2)
9038 isl_space *space1, *space2;
9040 space1 = isl_map_peek_space(map1);
9041 space2 = isl_map_peek_space(map2);
9042 return isl_space_tuple_is_equal(space1, type1, space2, type2);
9045 /* Is the space of "obj" equal to "space", ignoring parameters?
9047 isl_bool isl_map_has_space_tuples(__isl_keep isl_map *map,
9048 __isl_keep isl_space *space)
9050 isl_space *map_space;
9052 map_space = isl_map_peek_space(map);
9053 return isl_space_has_equal_tuples(map_space, space);
9056 /* Check that "map" is a transformation, i.e.,
9057 * that it relates elements from the same space.
9059 isl_stat isl_map_check_transformation(__isl_keep isl_map *map)
9061 isl_bool equal;
9063 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
9064 if (equal < 0)
9065 return isl_stat_error;
9066 if (!equal)
9067 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9068 "domain and range don't match", return isl_stat_error);
9069 return isl_stat_ok;
9073 * returns range - domain
9075 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
9077 int i;
9078 isl_space *space;
9079 struct isl_set *result;
9081 if (isl_map_check_transformation(map) < 0)
9082 goto error;
9083 space = isl_map_get_space(map);
9084 space = isl_space_domain(space);
9085 result = isl_set_alloc_space(space, map->n, 0);
9086 if (!result)
9087 goto error;
9088 for (i = 0; i < map->n; ++i)
9089 result = isl_set_add_basic_set(result,
9090 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
9091 isl_map_free(map);
9092 return result;
9093 error:
9094 isl_map_free(map);
9095 return NULL;
9099 * returns [domain -> range] -> range - domain
9101 __isl_give isl_basic_map *isl_basic_map_deltas_map(
9102 __isl_take isl_basic_map *bmap)
9104 int i, k;
9105 isl_space *space;
9106 isl_basic_map *domain;
9107 isl_size nparam, n;
9108 isl_size total;
9110 if (isl_basic_map_check_transformation(bmap) < 0)
9111 return isl_basic_map_free(bmap);
9113 nparam = isl_basic_map_dim(bmap, isl_dim_param);
9114 n = isl_basic_map_dim(bmap, isl_dim_in);
9115 if (nparam < 0 || n < 0)
9116 return isl_basic_map_free(bmap);
9118 space = isl_basic_map_get_space(bmap);
9119 space = isl_space_from_range(isl_space_domain(space));
9120 domain = isl_basic_map_universe(space);
9122 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
9123 bmap = isl_basic_map_apply_range(bmap, domain);
9124 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
9126 total = isl_basic_map_dim(bmap, isl_dim_all);
9127 if (total < 0)
9128 return isl_basic_map_free(bmap);
9130 for (i = 0; i < n; ++i) {
9131 k = isl_basic_map_alloc_equality(bmap);
9132 if (k < 0)
9133 goto error;
9134 isl_seq_clr(bmap->eq[k], 1 + total);
9135 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
9136 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
9137 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
9140 bmap = isl_basic_map_gauss(bmap, NULL);
9141 return isl_basic_map_finalize(bmap);
9142 error:
9143 isl_basic_map_free(bmap);
9144 return NULL;
9148 * returns [domain -> range] -> range - domain
9150 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
9152 if (isl_map_check_transformation(map) < 0)
9153 return isl_map_free(map);
9155 return isl_map_transform(map, &isl_space_range_map,
9156 &isl_basic_map_deltas_map);
9159 /* Return pairs of elements { x -> y } such that y - x is in "deltas".
9161 __isl_give isl_map *isl_set_translation(__isl_take isl_set *deltas)
9163 isl_space *space;
9164 isl_map *map;
9166 space = isl_space_map_from_set(isl_set_get_space(deltas));
9167 map = isl_map_deltas_map(isl_map_universe(space));
9168 map = isl_map_intersect_range(map, deltas);
9170 return isl_set_unwrap(isl_map_domain(map));
9173 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
9175 isl_size n_in, n_out;
9177 n_in = isl_space_dim(space, isl_dim_in);
9178 n_out = isl_space_dim(space, isl_dim_out);
9179 if (n_in < 0 || n_out < 0)
9180 goto error;
9181 if (n_in != n_out)
9182 isl_die(space->ctx, isl_error_invalid,
9183 "number of input and output dimensions needs to be "
9184 "the same", goto error);
9185 return isl_basic_map_equal(space, n_in);
9186 error:
9187 isl_space_free(space);
9188 return NULL;
9191 __isl_give isl_map *isl_map_identity(__isl_take isl_space *space)
9193 return isl_map_from_basic_map(isl_basic_map_identity(space));
9196 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
9198 isl_space *space = isl_set_get_space(set);
9199 isl_map *id;
9200 id = isl_map_identity(isl_space_map_from_set(space));
9201 return isl_map_intersect_range(id, set);
9204 /* Construct a basic set with all set dimensions having only non-negative
9205 * values.
9207 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
9208 __isl_take isl_space *space)
9210 int i;
9211 isl_size nparam;
9212 isl_size dim;
9213 isl_size total;
9214 struct isl_basic_set *bset;
9216 nparam = isl_space_dim(space, isl_dim_param);
9217 dim = isl_space_dim(space, isl_dim_set);
9218 total = isl_space_dim(space, isl_dim_all);
9219 if (nparam < 0 || dim < 0 || total < 0)
9220 space = isl_space_free(space);
9221 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
9222 if (!bset)
9223 return NULL;
9224 for (i = 0; i < dim; ++i) {
9225 int k = isl_basic_set_alloc_inequality(bset);
9226 if (k < 0)
9227 goto error;
9228 isl_seq_clr(bset->ineq[k], 1 + total);
9229 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
9231 return bset;
9232 error:
9233 isl_basic_set_free(bset);
9234 return NULL;
9237 /* Construct the half-space x_pos >= 0.
9239 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
9240 int pos)
9242 int k;
9243 isl_size total;
9244 isl_basic_set *nonneg;
9246 total = isl_space_dim(space, isl_dim_all);
9247 if (total < 0)
9248 space = isl_space_free(space);
9249 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
9250 k = isl_basic_set_alloc_inequality(nonneg);
9251 if (k < 0)
9252 goto error;
9253 isl_seq_clr(nonneg->ineq[k], 1 + total);
9254 isl_int_set_si(nonneg->ineq[k][pos], 1);
9256 return isl_basic_set_finalize(nonneg);
9257 error:
9258 isl_basic_set_free(nonneg);
9259 return NULL;
9262 /* Construct the half-space x_pos <= -1.
9264 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
9265 int pos)
9267 int k;
9268 isl_size total;
9269 isl_basic_set *neg;
9271 total = isl_space_dim(space, isl_dim_all);
9272 if (total < 0)
9273 space = isl_space_free(space);
9274 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
9275 k = isl_basic_set_alloc_inequality(neg);
9276 if (k < 0)
9277 goto error;
9278 isl_seq_clr(neg->ineq[k], 1 + total);
9279 isl_int_set_si(neg->ineq[k][0], -1);
9280 isl_int_set_si(neg->ineq[k][pos], -1);
9282 return isl_basic_set_finalize(neg);
9283 error:
9284 isl_basic_set_free(neg);
9285 return NULL;
9288 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
9289 enum isl_dim_type type, unsigned first, unsigned n)
9291 int i;
9292 unsigned offset;
9293 isl_basic_set *nonneg;
9294 isl_basic_set *neg;
9296 if (n == 0)
9297 return set;
9299 if (isl_set_check_range(set, type, first, n) < 0)
9300 return isl_set_free(set);
9302 offset = pos(set->dim, type);
9303 for (i = 0; i < n; ++i) {
9304 nonneg = nonneg_halfspace(isl_set_get_space(set),
9305 offset + first + i);
9306 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
9308 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
9311 return set;
9314 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
9315 int len,
9316 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
9317 void *user)
9319 isl_set *half;
9321 if (!set)
9322 return isl_stat_error;
9323 if (isl_set_plain_is_empty(set)) {
9324 isl_set_free(set);
9325 return isl_stat_ok;
9327 if (first == len)
9328 return fn(set, signs, user);
9330 signs[first] = 1;
9331 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
9332 1 + first));
9333 half = isl_set_intersect(half, isl_set_copy(set));
9334 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
9335 goto error;
9337 signs[first] = -1;
9338 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
9339 1 + first));
9340 half = isl_set_intersect(half, set);
9341 return foreach_orthant(half, signs, first + 1, len, fn, user);
9342 error:
9343 isl_set_free(set);
9344 return isl_stat_error;
9347 /* Call "fn" on the intersections of "set" with each of the orthants
9348 * (except for obviously empty intersections). The orthant is identified
9349 * by the signs array, with each entry having value 1 or -1 according
9350 * to the sign of the corresponding variable.
9352 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
9353 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
9354 void *user)
9356 isl_size nparam;
9357 isl_size nvar;
9358 int *signs;
9359 isl_stat r;
9361 if (!set)
9362 return isl_stat_error;
9363 if (isl_set_plain_is_empty(set))
9364 return isl_stat_ok;
9366 nparam = isl_set_dim(set, isl_dim_param);
9367 nvar = isl_set_dim(set, isl_dim_set);
9368 if (nparam < 0 || nvar < 0)
9369 return isl_stat_error;
9371 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
9373 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
9374 fn, user);
9376 free(signs);
9378 return r;
9381 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9383 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
9386 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
9387 __isl_keep isl_basic_map *bmap2)
9389 isl_bool is_subset;
9390 struct isl_map *map1;
9391 struct isl_map *map2;
9393 if (!bmap1 || !bmap2)
9394 return isl_bool_error;
9396 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
9397 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
9399 is_subset = isl_map_is_subset(map1, map2);
9401 isl_map_free(map1);
9402 isl_map_free(map2);
9404 return is_subset;
9407 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
9408 __isl_keep isl_basic_set *bset2)
9410 return isl_basic_map_is_subset(bset1, bset2);
9413 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
9414 __isl_keep isl_basic_map *bmap2)
9416 isl_bool is_subset;
9418 if (!bmap1 || !bmap2)
9419 return isl_bool_error;
9420 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9421 if (is_subset != isl_bool_true)
9422 return is_subset;
9423 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9424 return is_subset;
9427 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
9428 __isl_keep isl_basic_set *bset2)
9430 return isl_basic_map_is_equal(
9431 bset_to_bmap(bset1), bset_to_bmap(bset2));
9434 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
9436 int i;
9437 int is_empty;
9439 if (!map)
9440 return isl_bool_error;
9441 for (i = 0; i < map->n; ++i) {
9442 is_empty = isl_basic_map_is_empty(map->p[i]);
9443 if (is_empty < 0)
9444 return isl_bool_error;
9445 if (!is_empty)
9446 return isl_bool_false;
9448 return isl_bool_true;
9451 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
9453 return map ? map->n == 0 : isl_bool_error;
9456 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
9458 return set ? set->n == 0 : isl_bool_error;
9461 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
9463 return isl_map_is_empty(set_to_map(set));
9466 #undef TYPE
9467 #define TYPE isl_basic_map
9469 static
9470 #include "isl_type_has_equal_space_bin_templ.c"
9471 #include "isl_type_check_equal_space_templ.c"
9473 /* Check that "bset1" and "bset2" live in the same space,
9474 * reporting an error if they do not.
9476 isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
9477 __isl_keep isl_basic_set *bset2)
9479 return isl_basic_map_check_equal_space(bset_to_bmap(bset1),
9480 bset_to_bmap(bset1));
9483 #undef TYPE
9484 #define TYPE isl_map
9486 #include "isl_type_has_equal_space_bin_templ.c"
9487 #include "isl_type_check_equal_space_templ.c"
9488 #include "isl_type_has_space_templ.c"
9490 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
9491 __isl_keep isl_set *set2)
9493 return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));
9496 #undef TYPE1
9497 #define TYPE1 isl_map
9498 #undef TYPE2
9499 #define TYPE2 isl_basic_map
9500 #undef TYPE_PAIR
9501 #define TYPE_PAIR isl_map_basic_map
9503 static
9504 #include "isl_type_has_equal_space_templ.c"
9505 #include "isl_type_check_equal_space_templ.c"
9507 /* Check that "set" and "bset" live in the same space,
9508 * reporting an error if they do not.
9510 isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
9511 __isl_keep isl_basic_set *bset)
9513 return isl_map_basic_map_check_equal_space(set_to_map(set),
9514 bset_to_bmap(bset));
9517 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9519 isl_bool is_subset;
9521 if (!map1 || !map2)
9522 return isl_bool_error;
9523 is_subset = isl_map_is_subset(map1, map2);
9524 if (is_subset != isl_bool_true)
9525 return is_subset;
9526 is_subset = isl_map_is_subset(map2, map1);
9527 return is_subset;
9530 /* Is "map1" equal to "map2"?
9532 * First check if they are obviously equal.
9533 * If not, then perform a more detailed analysis.
9535 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9537 isl_bool equal;
9539 equal = isl_map_plain_is_equal(map1, map2);
9540 if (equal < 0 || equal)
9541 return equal;
9542 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
9545 isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
9546 __isl_keep isl_basic_map *bmap2)
9548 isl_bool is_subset;
9550 if (!bmap1 || !bmap2)
9551 return isl_bool_error;
9552 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9553 if (is_subset != isl_bool_true)
9554 return is_subset;
9555 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9556 return isl_bool_not(is_subset);
9559 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
9560 __isl_keep isl_map *map2)
9562 isl_bool is_subset;
9564 if (!map1 || !map2)
9565 return isl_bool_error;
9566 is_subset = isl_map_is_subset(map1, map2);
9567 if (is_subset != isl_bool_true)
9568 return is_subset;
9569 is_subset = isl_map_is_subset(map2, map1);
9570 return isl_bool_not(is_subset);
9573 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
9574 __isl_keep isl_set *set2)
9576 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
9579 /* Is "bmap" obviously equal to the universe with the same space?
9581 * That is, does it not have any constraints?
9583 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
9585 if (!bmap)
9586 return isl_bool_error;
9587 return bmap->n_eq == 0 && bmap->n_ineq == 0;
9590 /* Is "bset" obviously equal to the universe with the same space?
9592 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
9594 return isl_basic_map_plain_is_universe(bset);
9597 /* If "c" does not involve any existentially quantified variables,
9598 * then set *univ to false and abort
9600 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
9602 isl_bool *univ = user;
9603 isl_size n;
9605 n = isl_constraint_dim(c, isl_dim_div);
9606 if (n < 0)
9607 c = isl_constraint_free(c);
9608 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
9609 isl_constraint_free(c);
9610 if (*univ < 0 || !*univ)
9611 return isl_stat_error;
9612 return isl_stat_ok;
9615 /* Is "bmap" equal to the universe with the same space?
9617 * First check if it is obviously equal to the universe.
9618 * If not and if there are any constraints not involving
9619 * existentially quantified variables, then it is certainly
9620 * not equal to the universe.
9621 * Otherwise, check if the universe is a subset of "bmap".
9623 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
9625 isl_size n_div;
9626 isl_bool univ;
9627 isl_basic_map *test;
9629 univ = isl_basic_map_plain_is_universe(bmap);
9630 if (univ < 0 || univ)
9631 return univ;
9632 n_div = isl_basic_map_dim(bmap, isl_dim_div);
9633 if (n_div < 0)
9634 return isl_bool_error;
9635 if (n_div == 0)
9636 return isl_bool_false;
9637 univ = isl_bool_true;
9638 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
9639 univ)
9640 return isl_bool_error;
9641 if (univ < 0 || !univ)
9642 return univ;
9643 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
9644 univ = isl_basic_map_is_subset(test, bmap);
9645 isl_basic_map_free(test);
9646 return univ;
9649 /* Is "bset" equal to the universe with the same space?
9651 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
9653 return isl_basic_map_is_universe(bset);
9656 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
9658 int i;
9660 if (!map)
9661 return isl_bool_error;
9663 for (i = 0; i < map->n; ++i) {
9664 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
9665 if (r < 0 || r)
9666 return r;
9669 return isl_bool_false;
9672 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
9674 return isl_map_plain_is_universe(set_to_map(set));
9677 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
9679 struct isl_basic_set *bset = NULL;
9680 struct isl_vec *sample = NULL;
9681 isl_bool empty, non_empty;
9683 if (!bmap)
9684 return isl_bool_error;
9686 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
9687 return isl_bool_true;
9689 if (isl_basic_map_plain_is_universe(bmap))
9690 return isl_bool_false;
9692 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
9693 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
9694 copy = isl_basic_map_remove_redundancies(copy);
9695 empty = isl_basic_map_plain_is_empty(copy);
9696 isl_basic_map_free(copy);
9697 return empty;
9700 non_empty = isl_basic_map_plain_is_non_empty(bmap);
9701 if (non_empty < 0)
9702 return isl_bool_error;
9703 if (non_empty)
9704 return isl_bool_false;
9705 isl_vec_free(bmap->sample);
9706 bmap->sample = NULL;
9707 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
9708 if (!bset)
9709 return isl_bool_error;
9710 sample = isl_basic_set_sample_vec(bset);
9711 if (!sample)
9712 return isl_bool_error;
9713 empty = sample->size == 0;
9714 isl_vec_free(bmap->sample);
9715 bmap->sample = sample;
9716 if (empty)
9717 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
9719 return empty;
9722 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
9724 if (!bmap)
9725 return isl_bool_error;
9726 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
9729 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
9731 if (!bset)
9732 return isl_bool_error;
9733 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
9736 /* Is "bmap" known to be non-empty?
9738 * That is, is the cached sample still valid?
9740 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
9742 isl_size total;
9744 if (!bmap)
9745 return isl_bool_error;
9746 if (!bmap->sample)
9747 return isl_bool_false;
9748 total = isl_basic_map_dim(bmap, isl_dim_all);
9749 if (total < 0)
9750 return isl_bool_error;
9751 if (bmap->sample->size != 1 + total)
9752 return isl_bool_false;
9753 return isl_basic_map_contains(bmap, bmap->sample);
9756 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
9758 return isl_basic_map_is_empty(bset_to_bmap(bset));
9761 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
9762 __isl_take isl_basic_map *bmap2)
9764 struct isl_map *map;
9766 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
9767 goto error;
9769 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
9770 if (!map)
9771 goto error;
9772 map = isl_map_add_basic_map(map, bmap1);
9773 map = isl_map_add_basic_map(map, bmap2);
9774 return map;
9775 error:
9776 isl_basic_map_free(bmap1);
9777 isl_basic_map_free(bmap2);
9778 return NULL;
9781 __isl_give isl_set *isl_basic_set_union(__isl_take isl_basic_set *bset1,
9782 __isl_take isl_basic_set *bset2)
9784 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
9785 bset_to_bmap(bset2)));
9788 /* Order divs such that any div only depends on previous divs */
9789 __isl_give isl_basic_map *isl_basic_map_order_divs(
9790 __isl_take isl_basic_map *bmap)
9792 int i;
9793 isl_size off;
9795 off = isl_basic_map_var_offset(bmap, isl_dim_div);
9796 if (off < 0)
9797 return isl_basic_map_free(bmap);
9799 for (i = 0; i < bmap->n_div; ++i) {
9800 int pos;
9801 if (isl_int_is_zero(bmap->div[i][0]))
9802 continue;
9803 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
9804 bmap->n_div-i);
9805 if (pos == -1)
9806 continue;
9807 if (pos == 0)
9808 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
9809 "integer division depends on itself",
9810 return isl_basic_map_free(bmap));
9811 bmap = isl_basic_map_swap_div(bmap, i, i + pos);
9812 if (!bmap)
9813 return NULL;
9814 --i;
9816 return bmap;
9819 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
9821 int i;
9823 if (!map)
9824 return 0;
9826 for (i = 0; i < map->n; ++i) {
9827 map->p[i] = isl_basic_map_order_divs(map->p[i]);
9828 if (!map->p[i])
9829 goto error;
9832 return map;
9833 error:
9834 isl_map_free(map);
9835 return NULL;
9838 /* Sort the local variables of "bset".
9840 __isl_give isl_basic_set *isl_basic_set_sort_divs(
9841 __isl_take isl_basic_set *bset)
9843 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
9846 /* Apply the expansion computed by isl_merge_divs.
9847 * The expansion itself is given by "exp" while the resulting
9848 * list of divs is given by "div".
9850 * Move the integer divisions of "bmap" into the right position
9851 * according to "exp" and then introduce the additional integer
9852 * divisions, adding div constraints.
9853 * The moving should be done first to avoid moving coefficients
9854 * in the definitions of the extra integer divisions.
9856 __isl_give isl_basic_map *isl_basic_map_expand_divs(
9857 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
9859 int i, j;
9860 int n_div;
9862 bmap = isl_basic_map_cow(bmap);
9863 if (!bmap || !div)
9864 goto error;
9866 if (div->n_row < bmap->n_div)
9867 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
9868 "not an expansion", goto error);
9870 n_div = bmap->n_div;
9871 bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,
9872 2 * (div->n_row - n_div));
9874 for (i = n_div; i < div->n_row; ++i)
9875 if (isl_basic_map_alloc_div(bmap) < 0)
9876 goto error;
9878 for (j = n_div - 1; j >= 0; --j) {
9879 if (exp[j] == j)
9880 break;
9881 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
9882 if (!bmap)
9883 goto error;
9885 j = 0;
9886 for (i = 0; i < div->n_row; ++i) {
9887 if (j < n_div && exp[j] == i) {
9888 j++;
9889 } else {
9890 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
9891 if (isl_basic_map_div_is_marked_unknown(bmap, i))
9892 continue;
9893 bmap = isl_basic_map_add_div_constraints(bmap, i);
9894 if (!bmap)
9895 goto error;
9899 isl_mat_free(div);
9900 return bmap;
9901 error:
9902 isl_basic_map_free(bmap);
9903 isl_mat_free(div);
9904 return NULL;
9907 /* Apply the expansion computed by isl_merge_divs.
9908 * The expansion itself is given by "exp" while the resulting
9909 * list of divs is given by "div".
9911 __isl_give isl_basic_set *isl_basic_set_expand_divs(
9912 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
9914 return isl_basic_map_expand_divs(bset, div, exp);
9917 /* Look for a div in dst that corresponds to the div "div" in src.
9918 * The divs before "div" in src and dst are assumed to be the same.
9920 * Return the position of the corresponding div in dst
9921 * if there is one. Otherwise, return a position beyond the integer divisions.
9922 * Return -1 on error.
9924 static int find_div(__isl_keep isl_basic_map *dst,
9925 __isl_keep isl_basic_map *src, unsigned div)
9927 int i;
9928 isl_size n_div;
9929 isl_size v_div;
9931 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9932 n_div = isl_basic_map_dim(dst, isl_dim_div);
9933 if (n_div < 0 || v_div < 0)
9934 return -1;
9935 isl_assert(dst->ctx, div <= n_div, return -1);
9936 for (i = div; i < n_div; ++i)
9937 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
9938 isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
9939 n_div - div) == -1)
9940 return i;
9941 return n_div;
9944 /* Align the divs of "dst" to those of "src", adding divs from "src"
9945 * if needed. That is, make sure that the first src->n_div divs
9946 * of the result are equal to those of src.
9947 * The integer division of "src" are assumed to be ordered.
9949 * The integer divisions are swapped into the right position
9950 * (possibly after adding them first). This may result
9951 * in the remaining integer divisions appearing in the wrong order,
9952 * i.e., with some integer division appearing before
9953 * some other integer division on which it depends.
9954 * The integer divisions therefore need to be ordered.
9955 * This will not affect the integer divisions aligned to those of "src",
9956 * since "src" is assumed to have ordered integer divisions.
9958 * The result is not finalized as by design it will have redundant
9959 * divs if any divs from "src" were copied.
9961 __isl_give isl_basic_map *isl_basic_map_align_divs(
9962 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
9964 int i;
9965 isl_bool known;
9966 int extended;
9967 isl_size v_div;
9968 isl_size dst_n_div;
9970 if (!dst || !src)
9971 return isl_basic_map_free(dst);
9973 if (src->n_div == 0)
9974 return dst;
9976 known = isl_basic_map_divs_known(src);
9977 if (known < 0)
9978 return isl_basic_map_free(dst);
9979 if (!known)
9980 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9981 "some src divs are unknown",
9982 return isl_basic_map_free(dst));
9984 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9985 if (v_div < 0)
9986 return isl_basic_map_free(dst);
9988 extended = 0;
9989 dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
9990 if (dst_n_div < 0)
9991 dst = isl_basic_map_free(dst);
9992 for (i = 0; i < src->n_div; ++i) {
9993 int j = find_div(dst, src, i);
9994 if (j < 0)
9995 dst = isl_basic_map_free(dst);
9996 if (j == dst_n_div) {
9997 if (!extended) {
9998 int extra = src->n_div - i;
9999 dst = isl_basic_map_cow(dst);
10000 if (!dst)
10001 return isl_basic_map_free(dst);
10002 dst = isl_basic_map_extend(dst,
10003 extra, 0, 2 * extra);
10004 extended = 1;
10006 j = isl_basic_map_alloc_div(dst);
10007 if (j < 0)
10008 return isl_basic_map_free(dst);
10009 isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
10010 isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
10011 dst_n_div++;
10012 dst = isl_basic_map_add_div_constraints(dst, j);
10013 if (!dst)
10014 return isl_basic_map_free(dst);
10016 if (j != i)
10017 dst = isl_basic_map_swap_div(dst, i, j);
10018 if (!dst)
10019 return isl_basic_map_free(dst);
10021 return isl_basic_map_order_divs(dst);
10024 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
10026 int i;
10028 if (!map)
10029 return NULL;
10030 if (map->n == 0)
10031 return map;
10032 map = isl_map_compute_divs(map);
10033 map = isl_map_order_divs(map);
10034 map = isl_map_cow(map);
10035 if (!map)
10036 return NULL;
10038 for (i = 1; i < map->n; ++i)
10039 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
10040 for (i = 1; i < map->n; ++i) {
10041 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
10042 if (!map->p[i])
10043 return isl_map_free(map);
10046 map = isl_map_unmark_normalized(map);
10047 return map;
10050 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
10052 return isl_map_align_divs_internal(map);
10055 __isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set)
10057 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10060 /* Align the divs of the basic maps in "map" to those
10061 * of the basic maps in "list", as well as to the other basic maps in "map".
10062 * The elements in "list" are assumed to have known divs.
10064 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
10065 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
10067 int i;
10068 isl_size n;
10070 n = isl_basic_map_list_n_basic_map(list);
10071 map = isl_map_compute_divs(map);
10072 map = isl_map_cow(map);
10073 if (!map || n < 0)
10074 return isl_map_free(map);
10075 if (map->n == 0)
10076 return map;
10078 for (i = 0; i < n; ++i) {
10079 isl_basic_map *bmap;
10081 bmap = isl_basic_map_list_get_basic_map(list, i);
10082 bmap = isl_basic_map_order_divs(bmap);
10083 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
10084 isl_basic_map_free(bmap);
10086 if (!map->p[0])
10087 return isl_map_free(map);
10089 return isl_map_align_divs_internal(map);
10092 /* Align the divs of each element of "list" to those of "bmap".
10093 * Both "bmap" and the elements of "list" are assumed to have known divs.
10095 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
10096 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
10098 int i;
10099 isl_size n;
10101 n = isl_basic_map_list_n_basic_map(list);
10102 if (n < 0 || !bmap)
10103 return isl_basic_map_list_free(list);
10105 for (i = 0; i < n; ++i) {
10106 isl_basic_map *bmap_i;
10108 bmap_i = isl_basic_map_list_get_basic_map(list, i);
10109 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
10110 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
10113 return list;
10116 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
10117 __isl_take isl_map *map)
10119 isl_bool ok;
10121 isl_map_align_params_set(&map, &set);
10122 ok = isl_map_compatible_domain(map, set);
10123 if (ok < 0)
10124 goto error;
10125 if (!ok)
10126 isl_die(isl_set_get_ctx(set), isl_error_invalid,
10127 "incompatible spaces", goto error);
10128 map = isl_map_intersect_domain(map, set);
10129 set = isl_map_range(map);
10130 return set;
10131 error:
10132 isl_set_free(set);
10133 isl_map_free(map);
10134 return NULL;
10137 /* There is no need to cow as removing empty parts doesn't change
10138 * the meaning of the set.
10140 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
10142 int i;
10144 if (!map)
10145 return NULL;
10147 for (i = map->n - 1; i >= 0; --i)
10148 map = remove_if_empty(map, i);
10150 return map;
10153 __isl_give isl_set *isl_set_remove_empty_parts(__isl_take isl_set *set)
10155 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
10158 /* Create a binary relation that maps the shared initial "pos" dimensions
10159 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
10161 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
10162 __isl_keep isl_basic_set *bset2, int pos)
10164 isl_basic_map *bmap1;
10165 isl_basic_map *bmap2;
10167 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
10168 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
10169 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
10170 isl_dim_out, 0, pos);
10171 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
10172 isl_dim_out, 0, pos);
10173 return isl_basic_map_range_product(bmap1, bmap2);
10176 /* Given two basic sets bset1 and bset2, compute the maximal difference
10177 * between the values of dimension pos in bset1 and those in bset2
10178 * for any common value of the parameters and dimensions preceding pos.
10180 static enum isl_lp_result basic_set_maximal_difference_at(
10181 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
10182 int pos, isl_int *opt)
10184 isl_basic_map *bmap1;
10185 struct isl_ctx *ctx;
10186 struct isl_vec *obj;
10187 isl_size total;
10188 isl_size nparam;
10189 isl_size dim1;
10190 enum isl_lp_result res;
10192 nparam = isl_basic_set_dim(bset1, isl_dim_param);
10193 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
10194 if (nparam < 0 || dim1 < 0 || !bset2)
10195 return isl_lp_error;
10197 bmap1 = join_initial(bset1, bset2, pos);
10198 total = isl_basic_map_dim(bmap1, isl_dim_all);
10199 if (total < 0)
10200 return isl_lp_error;
10202 ctx = bmap1->ctx;
10203 obj = isl_vec_alloc(ctx, 1 + total);
10204 if (!obj)
10205 goto error;
10206 isl_seq_clr(obj->block.data, 1 + total);
10207 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
10208 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
10209 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
10210 opt, NULL, NULL);
10211 isl_basic_map_free(bmap1);
10212 isl_vec_free(obj);
10213 return res;
10214 error:
10215 isl_basic_map_free(bmap1);
10216 return isl_lp_error;
10219 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
10220 * for any common value of the parameters and dimensions preceding pos
10221 * in both basic sets, the values of dimension pos in bset1 are
10222 * smaller or larger than those in bset2.
10224 * Returns
10225 * 1 if bset1 follows bset2
10226 * -1 if bset1 precedes bset2
10227 * 0 if bset1 and bset2 are incomparable
10228 * -2 if some error occurred.
10230 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
10231 __isl_keep isl_basic_set *bset2, int pos)
10233 isl_int opt;
10234 enum isl_lp_result res;
10235 int cmp;
10237 isl_int_init(opt);
10239 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
10241 if (res == isl_lp_empty)
10242 cmp = 0;
10243 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
10244 res == isl_lp_unbounded)
10245 cmp = 1;
10246 else if (res == isl_lp_ok && isl_int_is_neg(opt))
10247 cmp = -1;
10248 else
10249 cmp = -2;
10251 isl_int_clear(opt);
10252 return cmp;
10255 /* Given two basic sets bset1 and bset2, check whether
10256 * for any common value of the parameters and dimensions preceding pos
10257 * there is a value of dimension pos in bset1 that is larger
10258 * than a value of the same dimension in bset2.
10260 * Return
10261 * 1 if there exists such a pair
10262 * 0 if there is no such pair, but there is a pair of equal values
10263 * -1 otherwise
10264 * -2 if some error occurred.
10266 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
10267 __isl_keep isl_basic_set *bset2, int pos)
10269 isl_bool empty;
10270 isl_basic_map *bmap;
10271 isl_size dim1;
10273 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
10274 if (dim1 < 0)
10275 return -2;
10276 bmap = join_initial(bset1, bset2, pos);
10277 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
10278 isl_dim_out, dim1 - pos);
10279 empty = isl_basic_map_is_empty(bmap);
10280 if (empty < 0)
10281 goto error;
10282 if (empty) {
10283 isl_basic_map_free(bmap);
10284 return -1;
10286 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
10287 isl_dim_out, dim1 - pos);
10288 empty = isl_basic_map_is_empty(bmap);
10289 if (empty < 0)
10290 goto error;
10291 isl_basic_map_free(bmap);
10292 if (empty)
10293 return 0;
10294 return 1;
10295 error:
10296 isl_basic_map_free(bmap);
10297 return -2;
10300 /* Given two sets set1 and set2, check whether
10301 * for any common value of the parameters and dimensions preceding pos
10302 * there is a value of dimension pos in set1 that is larger
10303 * than a value of the same dimension in set2.
10305 * Return
10306 * 1 if there exists such a pair
10307 * 0 if there is no such pair, but there is a pair of equal values
10308 * -1 otherwise
10309 * -2 if some error occurred.
10311 int isl_set_follows_at(__isl_keep isl_set *set1,
10312 __isl_keep isl_set *set2, int pos)
10314 int i, j;
10315 int follows = -1;
10317 if (!set1 || !set2)
10318 return -2;
10320 for (i = 0; i < set1->n; ++i)
10321 for (j = 0; j < set2->n; ++j) {
10322 int f;
10323 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
10324 if (f == 1 || f == -2)
10325 return f;
10326 if (f > follows)
10327 follows = f;
10330 return follows;
10333 static isl_bool isl_basic_map_plain_has_fixed_var(
10334 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
10336 int i;
10337 int d;
10338 isl_size total;
10340 total = isl_basic_map_dim(bmap, isl_dim_all);
10341 if (total < 0)
10342 return isl_bool_error;
10343 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
10344 for (; d+1 > pos; --d)
10345 if (!isl_int_is_zero(bmap->eq[i][1+d]))
10346 break;
10347 if (d != pos)
10348 continue;
10349 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
10350 return isl_bool_false;
10351 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
10352 return isl_bool_false;
10353 if (!isl_int_is_one(bmap->eq[i][1+d]))
10354 return isl_bool_false;
10355 if (val)
10356 isl_int_neg(*val, bmap->eq[i][0]);
10357 return isl_bool_true;
10359 return isl_bool_false;
10362 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
10363 unsigned pos, isl_int *val)
10365 int i;
10366 isl_int v;
10367 isl_int tmp;
10368 isl_bool fixed;
10370 if (!map)
10371 return isl_bool_error;
10372 if (map->n == 0)
10373 return isl_bool_false;
10374 if (map->n == 1)
10375 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
10376 isl_int_init(v);
10377 isl_int_init(tmp);
10378 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
10379 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
10380 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
10381 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
10382 fixed = isl_bool_false;
10384 if (val)
10385 isl_int_set(*val, v);
10386 isl_int_clear(tmp);
10387 isl_int_clear(v);
10388 return fixed;
10391 static isl_bool isl_basic_set_plain_has_fixed_var(
10392 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
10394 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
10395 pos, val);
10398 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
10399 enum isl_dim_type type, unsigned pos, isl_int *val)
10401 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10402 return isl_bool_error;
10403 return isl_basic_map_plain_has_fixed_var(bmap,
10404 isl_basic_map_offset(bmap, type) - 1 + pos, val);
10407 /* If "bmap" obviously lies on a hyperplane where the given dimension
10408 * has a fixed value, then return that value.
10409 * Otherwise return NaN.
10411 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
10412 __isl_keep isl_basic_map *bmap,
10413 enum isl_dim_type type, unsigned pos)
10415 isl_ctx *ctx;
10416 isl_val *v;
10417 isl_bool fixed;
10419 if (!bmap)
10420 return NULL;
10421 ctx = isl_basic_map_get_ctx(bmap);
10422 v = isl_val_alloc(ctx);
10423 if (!v)
10424 return NULL;
10425 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
10426 if (fixed < 0)
10427 return isl_val_free(v);
10428 if (fixed) {
10429 isl_int_set_si(v->d, 1);
10430 return v;
10432 isl_val_free(v);
10433 return isl_val_nan(ctx);
10436 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
10437 enum isl_dim_type type, unsigned pos, isl_int *val)
10439 if (isl_map_check_range(map, type, pos, 1) < 0)
10440 return isl_bool_error;
10441 return isl_map_plain_has_fixed_var(map,
10442 map_offset(map, type) - 1 + pos, val);
10445 /* If "map" obviously lies on a hyperplane where the given dimension
10446 * has a fixed value, then return that value.
10447 * Otherwise return NaN.
10449 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
10450 enum isl_dim_type type, unsigned pos)
10452 isl_ctx *ctx;
10453 isl_val *v;
10454 isl_bool fixed;
10456 if (!map)
10457 return NULL;
10458 ctx = isl_map_get_ctx(map);
10459 v = isl_val_alloc(ctx);
10460 if (!v)
10461 return NULL;
10462 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
10463 if (fixed < 0)
10464 return isl_val_free(v);
10465 if (fixed) {
10466 isl_int_set_si(v->d, 1);
10467 return v;
10469 isl_val_free(v);
10470 return isl_val_nan(ctx);
10473 /* If "set" obviously lies on a hyperplane where the given dimension
10474 * has a fixed value, then return that value.
10475 * Otherwise return NaN.
10477 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
10478 enum isl_dim_type type, unsigned pos)
10480 return isl_map_plain_get_val_if_fixed(set, type, pos);
10483 /* Return a sequence of values in the same space as "set"
10484 * that are equal to the corresponding set dimensions of "set"
10485 * for those set dimensions that obviously lie on a hyperplane
10486 * where the dimension has a fixed value.
10487 * The other elements are set to NaN.
10489 __isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
10490 __isl_keep isl_set *set)
10492 int i;
10493 isl_size n;
10494 isl_space *space;
10495 isl_multi_val *mv;
10497 space = isl_space_drop_all_params(isl_set_get_space(set));
10498 mv = isl_multi_val_alloc(space);
10499 n = isl_multi_val_size(mv);
10500 if (n < 0)
10501 return isl_multi_val_free(mv);
10503 for (i = 0; i < n; ++i) {
10504 isl_val *v;
10506 v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);
10507 mv = isl_multi_val_set_val(mv, i, v);
10510 return mv;
10513 /* Check if dimension dim has fixed value and if so and if val is not NULL,
10514 * then return this fixed value in *val.
10516 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
10517 unsigned dim, isl_int *val)
10519 isl_size nparam;
10521 nparam = isl_basic_set_dim(bset, isl_dim_param);
10522 if (nparam < 0)
10523 return isl_bool_error;
10524 return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
10527 /* Return -1 if the constraint "c1" should be sorted before "c2"
10528 * and 1 if it should be sorted after "c2".
10529 * Return 0 if the two constraints are the same (up to the constant term).
10531 * In particular, if a constraint involves later variables than another
10532 * then it is sorted after this other constraint.
10533 * uset_gist depends on constraints without existentially quantified
10534 * variables sorting first.
10536 * For constraints that have the same latest variable, those
10537 * with the same coefficient for this latest variable (first in absolute value
10538 * and then in actual value) are grouped together.
10539 * This is useful for detecting pairs of constraints that can
10540 * be chained in their printed representation.
10542 * Finally, within a group, constraints are sorted according to
10543 * their coefficients (excluding the constant term).
10545 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
10547 isl_int **c1 = (isl_int **) p1;
10548 isl_int **c2 = (isl_int **) p2;
10549 int l1, l2;
10550 unsigned size = *(unsigned *) arg;
10551 int cmp;
10553 l1 = isl_seq_last_non_zero(*c1 + 1, size);
10554 l2 = isl_seq_last_non_zero(*c2 + 1, size);
10556 if (l1 != l2)
10557 return l1 - l2;
10559 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10560 if (cmp != 0)
10561 return cmp;
10562 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10563 if (cmp != 0)
10564 return -cmp;
10566 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
10569 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
10570 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
10571 * and 0 if the two constraints are the same (up to the constant term).
10573 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
10574 isl_int *c1, isl_int *c2)
10576 isl_size total;
10577 unsigned size;
10579 total = isl_basic_map_dim(bmap, isl_dim_all);
10580 if (total < 0)
10581 return -2;
10582 size = total;
10583 return sort_constraint_cmp(&c1, &c2, &size);
10586 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
10587 __isl_take isl_basic_map *bmap)
10589 isl_size total;
10590 unsigned size;
10592 if (!bmap)
10593 return NULL;
10594 if (bmap->n_ineq == 0)
10595 return bmap;
10596 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
10597 return bmap;
10598 total = isl_basic_map_dim(bmap, isl_dim_all);
10599 if (total < 0)
10600 return isl_basic_map_free(bmap);
10601 size = total;
10602 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
10603 &sort_constraint_cmp, &size) < 0)
10604 return isl_basic_map_free(bmap);
10605 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
10606 return bmap;
10609 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
10610 __isl_take isl_basic_set *bset)
10612 isl_basic_map *bmap = bset_to_bmap(bset);
10613 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
10616 __isl_give isl_basic_map *isl_basic_map_normalize(
10617 __isl_take isl_basic_map *bmap)
10619 bmap = isl_basic_map_remove_redundancies(bmap);
10620 bmap = isl_basic_map_sort_constraints(bmap);
10621 return bmap;
10623 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
10624 __isl_keep isl_basic_map *bmap2)
10626 int i, cmp;
10627 isl_size total;
10628 isl_space *space1, *space2;
10630 if (!bmap1 || !bmap2)
10631 return -1;
10633 if (bmap1 == bmap2)
10634 return 0;
10635 space1 = isl_basic_map_peek_space(bmap1);
10636 space2 = isl_basic_map_peek_space(bmap2);
10637 cmp = isl_space_cmp(space1, space2);
10638 if (cmp)
10639 return cmp;
10640 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
10641 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
10642 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
10643 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
10644 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10645 return 0;
10646 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
10647 return 1;
10648 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10649 return -1;
10650 if (bmap1->n_eq != bmap2->n_eq)
10651 return bmap1->n_eq - bmap2->n_eq;
10652 if (bmap1->n_ineq != bmap2->n_ineq)
10653 return bmap1->n_ineq - bmap2->n_ineq;
10654 if (bmap1->n_div != bmap2->n_div)
10655 return bmap1->n_div - bmap2->n_div;
10656 total = isl_basic_map_dim(bmap1, isl_dim_all);
10657 if (total < 0)
10658 return -1;
10659 for (i = 0; i < bmap1->n_eq; ++i) {
10660 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
10661 if (cmp)
10662 return cmp;
10664 for (i = 0; i < bmap1->n_ineq; ++i) {
10665 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
10666 if (cmp)
10667 return cmp;
10669 for (i = 0; i < bmap1->n_div; ++i) {
10670 isl_bool unknown1, unknown2;
10672 unknown1 = isl_basic_map_div_is_marked_unknown(bmap1, i);
10673 unknown2 = isl_basic_map_div_is_marked_unknown(bmap2, i);
10674 if (unknown1 < 0 || unknown2 < 0)
10675 return -1;
10676 if (unknown1 && unknown2)
10677 continue;
10678 if (unknown1)
10679 return 1;
10680 if (unknown2)
10681 return -1;
10682 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
10683 if (cmp)
10684 return cmp;
10686 return 0;
10689 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
10690 __isl_keep isl_basic_set *bset2)
10692 return isl_basic_map_plain_cmp(bset1, bset2);
10695 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
10697 int i, cmp;
10699 if (set1 == set2)
10700 return 0;
10701 if (set1->n != set2->n)
10702 return set1->n - set2->n;
10704 for (i = 0; i < set1->n; ++i) {
10705 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
10706 if (cmp)
10707 return cmp;
10710 return 0;
10713 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
10714 __isl_keep isl_basic_map *bmap2)
10716 if (!bmap1 || !bmap2)
10717 return isl_bool_error;
10718 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
10721 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
10722 __isl_keep isl_basic_set *bset2)
10724 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
10725 bset_to_bmap(bset2));
10728 static int qsort_bmap_cmp(const void *p1, const void *p2)
10730 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
10731 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
10733 return isl_basic_map_plain_cmp(bmap1, bmap2);
10736 /* Sort the basic maps of "map" and remove duplicate basic maps.
10738 * While removing basic maps, we make sure that the basic maps remain
10739 * sorted because isl_map_normalize expects the basic maps of the result
10740 * to be sorted.
10742 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
10744 int i, j;
10746 map = isl_map_remove_empty_parts(map);
10747 if (!map)
10748 return NULL;
10749 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
10750 for (i = map->n - 1; i >= 1; --i) {
10751 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
10752 continue;
10753 isl_basic_map_free(map->p[i-1]);
10754 for (j = i; j < map->n; ++j)
10755 map->p[j - 1] = map->p[j];
10756 map->n--;
10759 return map;
10762 /* Remove obvious duplicates among the basic maps of "map".
10764 * Unlike isl_map_normalize, this function does not remove redundant
10765 * constraints and only removes duplicates that have exactly the same
10766 * constraints in the input. It does sort the constraints and
10767 * the basic maps to ease the detection of duplicates.
10769 * If "map" has already been normalized or if the basic maps are
10770 * disjoint, then there can be no duplicates.
10772 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
10774 int i;
10775 isl_basic_map *bmap;
10777 if (!map)
10778 return NULL;
10779 if (map->n <= 1)
10780 return map;
10781 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
10782 return map;
10783 for (i = 0; i < map->n; ++i) {
10784 bmap = isl_basic_map_copy(map->p[i]);
10785 bmap = isl_basic_map_sort_constraints(bmap);
10786 if (!bmap)
10787 return isl_map_free(map);
10788 isl_basic_map_free(map->p[i]);
10789 map->p[i] = bmap;
10792 map = sort_and_remove_duplicates(map);
10793 return map;
10796 /* We normalize in place, but if anything goes wrong we need
10797 * to return NULL, so we need to make sure we don't change the
10798 * meaning of any possible other copies of map.
10800 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
10802 int i;
10803 struct isl_basic_map *bmap;
10805 if (!map)
10806 return NULL;
10807 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
10808 return map;
10809 for (i = 0; i < map->n; ++i) {
10810 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
10811 if (!bmap)
10812 goto error;
10813 isl_basic_map_free(map->p[i]);
10814 map->p[i] = bmap;
10817 map = sort_and_remove_duplicates(map);
10818 if (map)
10819 ISL_F_SET(map, ISL_MAP_NORMALIZED);
10820 return map;
10821 error:
10822 isl_map_free(map);
10823 return NULL;
10826 __isl_give isl_set *isl_set_normalize(__isl_take isl_set *set)
10828 return set_from_map(isl_map_normalize(set_to_map(set)));
10831 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
10832 __isl_keep isl_map *map2)
10834 int i;
10835 isl_bool equal;
10837 if (!map1 || !map2)
10838 return isl_bool_error;
10840 if (map1 == map2)
10841 return isl_bool_true;
10842 equal = isl_map_has_equal_space(map1, map2);
10843 if (equal < 0 || !equal)
10844 return equal;
10846 map1 = isl_map_copy(map1);
10847 map2 = isl_map_copy(map2);
10848 map1 = isl_map_normalize(map1);
10849 map2 = isl_map_normalize(map2);
10850 if (!map1 || !map2)
10851 goto error;
10852 equal = map1->n == map2->n;
10853 for (i = 0; equal && i < map1->n; ++i) {
10854 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
10855 if (equal < 0)
10856 goto error;
10858 isl_map_free(map1);
10859 isl_map_free(map2);
10860 return equal;
10861 error:
10862 isl_map_free(map1);
10863 isl_map_free(map2);
10864 return isl_bool_error;
10867 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
10868 __isl_keep isl_set *set2)
10870 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
10873 /* Return the basic maps in "map" as a list.
10875 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
10876 __isl_keep isl_map *map)
10878 int i;
10879 isl_ctx *ctx;
10880 isl_basic_map_list *list;
10882 if (!map)
10883 return NULL;
10884 ctx = isl_map_get_ctx(map);
10885 list = isl_basic_map_list_alloc(ctx, map->n);
10887 for (i = 0; i < map->n; ++i) {
10888 isl_basic_map *bmap;
10890 bmap = isl_basic_map_copy(map->p[i]);
10891 list = isl_basic_map_list_add(list, bmap);
10894 return list;
10897 /* Return the intersection of the elements in the non-empty list "list".
10898 * All elements are assumed to live in the same space.
10900 __isl_give isl_basic_map *isl_basic_map_list_intersect(
10901 __isl_take isl_basic_map_list *list)
10903 int i;
10904 isl_size n;
10905 isl_basic_map *bmap;
10907 n = isl_basic_map_list_n_basic_map(list);
10908 if (n < 0)
10909 goto error;
10910 if (n < 1)
10911 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
10912 "expecting non-empty list", goto error);
10914 bmap = isl_basic_map_list_get_basic_map(list, 0);
10915 for (i = 1; i < n; ++i) {
10916 isl_basic_map *bmap_i;
10918 bmap_i = isl_basic_map_list_get_basic_map(list, i);
10919 bmap = isl_basic_map_intersect(bmap, bmap_i);
10922 isl_basic_map_list_free(list);
10923 return bmap;
10924 error:
10925 isl_basic_map_list_free(list);
10926 return NULL;
10929 /* Return the intersection of the elements in the non-empty list "list".
10930 * All elements are assumed to live in the same space.
10932 __isl_give isl_basic_set *isl_basic_set_list_intersect(
10933 __isl_take isl_basic_set_list *list)
10935 return isl_basic_map_list_intersect(list);
10938 /* Return the union of the elements of "list".
10939 * The list is required to have at least one element.
10941 __isl_give isl_set *isl_basic_set_list_union(
10942 __isl_take isl_basic_set_list *list)
10944 int i;
10945 isl_size n;
10946 isl_space *space;
10947 isl_basic_set *bset;
10948 isl_set *set;
10950 n = isl_basic_set_list_n_basic_set(list);
10951 if (n < 0)
10952 goto error;
10953 if (n < 1)
10954 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
10955 "expecting non-empty list", goto error);
10957 bset = isl_basic_set_list_get_basic_set(list, 0);
10958 space = isl_basic_set_get_space(bset);
10959 isl_basic_set_free(bset);
10961 set = isl_set_alloc_space(space, n, 0);
10962 for (i = 0; i < n; ++i) {
10963 bset = isl_basic_set_list_get_basic_set(list, i);
10964 set = isl_set_add_basic_set(set, bset);
10967 isl_basic_set_list_free(list);
10968 return set;
10969 error:
10970 isl_basic_set_list_free(list);
10971 return NULL;
10974 /* Return the union of the elements in the non-empty list "list".
10975 * All elements are assumed to live in the same space.
10977 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
10979 int i;
10980 isl_size n;
10981 isl_set *set;
10983 n = isl_set_list_n_set(list);
10984 if (n < 0)
10985 goto error;
10986 if (n < 1)
10987 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
10988 "expecting non-empty list", goto error);
10990 set = isl_set_list_get_set(list, 0);
10991 for (i = 1; i < n; ++i) {
10992 isl_set *set_i;
10994 set_i = isl_set_list_get_set(list, i);
10995 set = isl_set_union(set, set_i);
10998 isl_set_list_free(list);
10999 return set;
11000 error:
11001 isl_set_list_free(list);
11002 return NULL;
11005 __isl_give isl_basic_map *isl_basic_map_product(
11006 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
11008 isl_space *space_result = NULL;
11009 struct isl_basic_map *bmap;
11010 unsigned in1, in2, out1, out2, nparam, total, pos;
11011 struct isl_dim_map *dim_map1, *dim_map2;
11013 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
11014 goto error;
11015 space_result = isl_space_product(isl_space_copy(bmap1->dim),
11016 isl_space_copy(bmap2->dim));
11018 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
11019 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
11020 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
11021 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
11022 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
11024 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
11025 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
11026 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
11027 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
11028 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
11029 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
11030 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
11031 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
11032 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
11033 isl_dim_map_div(dim_map1, bmap1, pos += out2);
11034 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
11036 bmap = isl_basic_map_alloc_space(space_result,
11037 bmap1->n_div + bmap2->n_div,
11038 bmap1->n_eq + bmap2->n_eq,
11039 bmap1->n_ineq + bmap2->n_ineq);
11040 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
11041 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
11042 bmap = isl_basic_map_simplify(bmap);
11043 return isl_basic_map_finalize(bmap);
11044 error:
11045 isl_basic_map_free(bmap1);
11046 isl_basic_map_free(bmap2);
11047 return NULL;
11050 __isl_give isl_basic_map *isl_basic_map_flat_product(
11051 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
11053 isl_basic_map *prod;
11055 prod = isl_basic_map_product(bmap1, bmap2);
11056 prod = isl_basic_map_flatten(prod);
11057 return prod;
11060 __isl_give isl_basic_set *isl_basic_set_flat_product(
11061 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
11063 return isl_basic_map_flat_range_product(bset1, bset2);
11066 __isl_give isl_basic_map *isl_basic_map_domain_product(
11067 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
11069 isl_space *space1, *space2;
11070 isl_space *space_result = NULL;
11071 isl_basic_map *bmap;
11072 isl_size in1, in2, out, nparam;
11073 unsigned total, pos;
11074 struct isl_dim_map *dim_map1, *dim_map2;
11076 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
11077 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
11078 out = isl_basic_map_dim(bmap1, isl_dim_out);
11079 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
11080 if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
11081 goto error;
11083 space1 = isl_basic_map_get_space(bmap1);
11084 space2 = isl_basic_map_get_space(bmap2);
11085 space_result = isl_space_domain_product(space1, space2);
11087 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
11088 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
11089 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
11090 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
11091 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
11092 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
11093 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
11094 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
11095 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
11096 isl_dim_map_div(dim_map1, bmap1, pos += out);
11097 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
11099 bmap = isl_basic_map_alloc_space(space_result,
11100 bmap1->n_div + bmap2->n_div,
11101 bmap1->n_eq + bmap2->n_eq,
11102 bmap1->n_ineq + bmap2->n_ineq);
11103 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
11104 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
11105 bmap = isl_basic_map_simplify(bmap);
11106 return isl_basic_map_finalize(bmap);
11107 error:
11108 isl_basic_map_free(bmap1);
11109 isl_basic_map_free(bmap2);
11110 return NULL;
11113 __isl_give isl_basic_map *isl_basic_map_range_product(
11114 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
11116 isl_bool rational;
11117 isl_space *space_result = NULL;
11118 isl_basic_map *bmap;
11119 isl_size in, out1, out2, nparam;
11120 unsigned total, pos;
11121 struct isl_dim_map *dim_map1, *dim_map2;
11123 rational = isl_basic_map_is_rational(bmap1);
11124 if (rational >= 0 && rational)
11125 rational = isl_basic_map_is_rational(bmap2);
11126 in = isl_basic_map_dim(bmap1, isl_dim_in);
11127 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
11128 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
11129 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
11130 if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
11131 goto error;
11133 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
11134 goto error;
11136 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
11137 isl_space_copy(bmap2->dim));
11139 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
11140 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
11141 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
11142 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
11143 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
11144 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
11145 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
11146 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
11147 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
11148 isl_dim_map_div(dim_map1, bmap1, pos += out2);
11149 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
11151 bmap = isl_basic_map_alloc_space(space_result,
11152 bmap1->n_div + bmap2->n_div,
11153 bmap1->n_eq + bmap2->n_eq,
11154 bmap1->n_ineq + bmap2->n_ineq);
11155 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
11156 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
11157 if (rational)
11158 bmap = isl_basic_map_set_rational(bmap);
11159 bmap = isl_basic_map_simplify(bmap);
11160 return isl_basic_map_finalize(bmap);
11161 error:
11162 isl_basic_map_free(bmap1);
11163 isl_basic_map_free(bmap2);
11164 return NULL;
11167 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
11168 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
11170 isl_basic_map *prod;
11172 prod = isl_basic_map_range_product(bmap1, bmap2);
11173 prod = isl_basic_map_flatten_range(prod);
11174 return prod;
11177 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
11178 * and collect the results.
11179 * The result live in the space obtained by calling "space_product"
11180 * on the spaces of "map1" and "map2".
11181 * If "remove_duplicates" is set then the result may contain duplicates
11182 * (even if the inputs do not) and so we try and remove the obvious
11183 * duplicates.
11185 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
11186 __isl_take isl_map *map2,
11187 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
11188 __isl_take isl_space *right),
11189 __isl_give isl_basic_map *(*basic_map_product)(
11190 __isl_take isl_basic_map *left,
11191 __isl_take isl_basic_map *right),
11192 int remove_duplicates)
11194 unsigned flags = 0;
11195 struct isl_map *result;
11196 int i, j;
11197 isl_bool m;
11199 m = isl_map_has_equal_params(map1, map2);
11200 if (m < 0)
11201 goto error;
11202 if (!m)
11203 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
11204 "parameters don't match", goto error);
11206 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
11207 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
11208 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
11210 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
11211 isl_space_copy(map2->dim)),
11212 map1->n * map2->n, flags);
11213 if (!result)
11214 goto error;
11215 for (i = 0; i < map1->n; ++i)
11216 for (j = 0; j < map2->n; ++j) {
11217 struct isl_basic_map *part;
11218 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
11219 isl_basic_map_copy(map2->p[j]));
11220 if (isl_basic_map_is_empty(part))
11221 isl_basic_map_free(part);
11222 else
11223 result = isl_map_add_basic_map(result, part);
11224 if (!result)
11225 goto error;
11227 if (remove_duplicates)
11228 result = isl_map_remove_obvious_duplicates(result);
11229 isl_map_free(map1);
11230 isl_map_free(map2);
11231 return result;
11232 error:
11233 isl_map_free(map1);
11234 isl_map_free(map2);
11235 return NULL;
11238 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
11240 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
11241 __isl_take isl_map *map2)
11243 isl_map_align_params_bin(&map1, &map2);
11244 return map_product(map1, map2, &isl_space_product,
11245 &isl_basic_map_product, 0);
11248 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
11250 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
11251 __isl_take isl_map *map2)
11253 isl_map *prod;
11255 prod = isl_map_product(map1, map2);
11256 prod = isl_map_flatten(prod);
11257 return prod;
11260 /* Given two set A and B, construct its Cartesian product A x B.
11262 __isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
11263 __isl_take isl_set *set2)
11265 return isl_map_range_product(set1, set2);
11268 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
11269 __isl_take isl_set *set2)
11271 return isl_map_flat_range_product(set1, set2);
11274 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
11276 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
11277 __isl_take isl_map *map2)
11279 isl_map_align_params_bin(&map1, &map2);
11280 return map_product(map1, map2, &isl_space_domain_product,
11281 &isl_basic_map_domain_product, 1);
11284 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
11286 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
11287 __isl_take isl_map *map2)
11289 isl_map_align_params_bin(&map1, &map2);
11290 return map_product(map1, map2, &isl_space_range_product,
11291 &isl_basic_map_range_product, 1);
11294 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
11296 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
11298 isl_space *space;
11299 isl_size total1, keep1, total2, keep2;
11301 total1 = isl_map_dim(map, isl_dim_in);
11302 total2 = isl_map_dim(map, isl_dim_out);
11303 if (total1 < 0 || total2 < 0)
11304 return isl_map_free(map);
11305 if (!isl_space_domain_is_wrapping(map->dim) ||
11306 !isl_space_range_is_wrapping(map->dim))
11307 isl_die(isl_map_get_ctx(map), isl_error_invalid,
11308 "not a product", return isl_map_free(map));
11310 space = isl_map_get_space(map);
11311 space = isl_space_factor_domain(space);
11312 keep1 = isl_space_dim(space, isl_dim_in);
11313 keep2 = isl_space_dim(space, isl_dim_out);
11314 if (keep1 < 0 || keep2 < 0)
11315 map = isl_map_free(map);
11316 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
11317 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
11318 map = isl_map_reset_space(map, space);
11320 return map;
11323 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
11325 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
11327 isl_space *space;
11328 isl_size total1, keep1, total2, keep2;
11330 total1 = isl_map_dim(map, isl_dim_in);
11331 total2 = isl_map_dim(map, isl_dim_out);
11332 if (total1 < 0 || total2 < 0)
11333 return isl_map_free(map);
11334 if (!isl_space_domain_is_wrapping(map->dim) ||
11335 !isl_space_range_is_wrapping(map->dim))
11336 isl_die(isl_map_get_ctx(map), isl_error_invalid,
11337 "not a product", return isl_map_free(map));
11339 space = isl_map_get_space(map);
11340 space = isl_space_factor_range(space);
11341 keep1 = isl_space_dim(space, isl_dim_in);
11342 keep2 = isl_space_dim(space, isl_dim_out);
11343 if (keep1 < 0 || keep2 < 0)
11344 map = isl_map_free(map);
11345 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
11346 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
11347 map = isl_map_reset_space(map, space);
11349 return map;
11352 /* Given a map of the form [A -> B] -> C, return the map A -> C.
11354 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
11356 isl_space *space;
11357 isl_size total, keep;
11359 total = isl_map_dim(map, isl_dim_in);
11360 if (total < 0)
11361 return isl_map_free(map);
11362 if (!isl_space_domain_is_wrapping(map->dim))
11363 isl_die(isl_map_get_ctx(map), isl_error_invalid,
11364 "domain is not a product", return isl_map_free(map));
11366 space = isl_map_get_space(map);
11367 space = isl_space_domain_factor_domain(space);
11368 keep = isl_space_dim(space, isl_dim_in);
11369 if (keep < 0)
11370 map = isl_map_free(map);
11371 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
11372 map = isl_map_reset_space(map, space);
11374 return map;
11377 /* Given a map of the form [A -> B] -> C, return the map B -> C.
11379 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
11381 isl_space *space;
11382 isl_size total, keep;
11384 total = isl_map_dim(map, isl_dim_in);
11385 if (total < 0)
11386 return isl_map_free(map);
11387 if (!isl_space_domain_is_wrapping(map->dim))
11388 isl_die(isl_map_get_ctx(map), isl_error_invalid,
11389 "domain is not a product", return isl_map_free(map));
11391 space = isl_map_get_space(map);
11392 space = isl_space_domain_factor_range(space);
11393 keep = isl_space_dim(space, isl_dim_in);
11394 if (keep < 0)
11395 map = isl_map_free(map);
11396 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
11397 map = isl_map_reset_space(map, space);
11399 return map;
11402 /* Given a map A -> [B -> C], extract the map A -> B.
11404 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
11406 isl_space *space;
11407 isl_size total, keep;
11409 total = isl_map_dim(map, isl_dim_out);
11410 if (total < 0)
11411 return isl_map_free(map);
11412 if (!isl_space_range_is_wrapping(map->dim))
11413 isl_die(isl_map_get_ctx(map), isl_error_invalid,
11414 "range is not a product", return isl_map_free(map));
11416 space = isl_map_get_space(map);
11417 space = isl_space_range_factor_domain(space);
11418 keep = isl_space_dim(space, isl_dim_out);
11419 if (keep < 0)
11420 map = isl_map_free(map);
11421 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
11422 map = isl_map_reset_space(map, space);
11424 return map;
11427 /* Given a map A -> [B -> C], extract the map A -> C.
11429 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
11431 isl_space *space;
11432 isl_size total, keep;
11434 total = isl_map_dim(map, isl_dim_out);
11435 if (total < 0)
11436 return isl_map_free(map);
11437 if (!isl_space_range_is_wrapping(map->dim))
11438 isl_die(isl_map_get_ctx(map), isl_error_invalid,
11439 "range is not a product", return isl_map_free(map));
11441 space = isl_map_get_space(map);
11442 space = isl_space_range_factor_range(space);
11443 keep = isl_space_dim(space, isl_dim_out);
11444 if (keep < 0)
11445 map = isl_map_free(map);
11446 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
11447 map = isl_map_reset_space(map, space);
11449 return map;
11452 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
11454 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
11455 __isl_take isl_map *map2)
11457 isl_map *prod;
11459 prod = isl_map_domain_product(map1, map2);
11460 prod = isl_map_flatten_domain(prod);
11461 return prod;
11464 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
11466 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
11467 __isl_take isl_map *map2)
11469 isl_map *prod;
11471 prod = isl_map_range_product(map1, map2);
11472 prod = isl_map_flatten_range(prod);
11473 return prod;
11476 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
11478 int i;
11479 uint32_t hash = isl_hash_init();
11480 isl_size total;
11482 if (!bmap)
11483 return 0;
11484 bmap = isl_basic_map_copy(bmap);
11485 bmap = isl_basic_map_normalize(bmap);
11486 total = isl_basic_map_dim(bmap, isl_dim_all);
11487 if (total < 0)
11488 return 0;
11489 isl_hash_byte(hash, bmap->n_eq & 0xFF);
11490 for (i = 0; i < bmap->n_eq; ++i) {
11491 uint32_t c_hash;
11492 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
11493 isl_hash_hash(hash, c_hash);
11495 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
11496 for (i = 0; i < bmap->n_ineq; ++i) {
11497 uint32_t c_hash;
11498 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
11499 isl_hash_hash(hash, c_hash);
11501 isl_hash_byte(hash, bmap->n_div & 0xFF);
11502 for (i = 0; i < bmap->n_div; ++i) {
11503 uint32_t c_hash;
11504 if (isl_int_is_zero(bmap->div[i][0]))
11505 continue;
11506 isl_hash_byte(hash, i & 0xFF);
11507 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
11508 isl_hash_hash(hash, c_hash);
11510 isl_basic_map_free(bmap);
11511 return hash;
11514 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
11516 return isl_basic_map_get_hash(bset_to_bmap(bset));
11519 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
11521 int i;
11522 uint32_t hash;
11524 if (!map)
11525 return 0;
11526 map = isl_map_copy(map);
11527 map = isl_map_normalize(map);
11528 if (!map)
11529 return 0;
11531 hash = isl_hash_init();
11532 for (i = 0; i < map->n; ++i) {
11533 uint32_t bmap_hash;
11534 bmap_hash = isl_basic_map_get_hash(map->p[i]);
11535 isl_hash_hash(hash, bmap_hash);
11538 isl_map_free(map);
11540 return hash;
11543 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
11545 return isl_map_get_hash(set_to_map(set));
11548 /* Return the number of basic maps in the (current) representation of "map".
11550 isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
11552 return map ? map->n : isl_size_error;
11555 isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
11557 return set ? set->n : isl_size_error;
11560 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
11561 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
11563 int i;
11565 if (!map)
11566 return isl_stat_error;
11568 for (i = 0; i < map->n; ++i)
11569 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
11570 return isl_stat_error;
11572 return isl_stat_ok;
11575 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
11576 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
11578 int i;
11580 if (!set)
11581 return isl_stat_error;
11583 for (i = 0; i < set->n; ++i)
11584 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
11585 return isl_stat_error;
11587 return isl_stat_ok;
11590 /* Does "test" succeed on every basic set in "set"?
11592 isl_bool isl_set_every_basic_set(__isl_keep isl_set *set,
11593 isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),
11594 void *user)
11596 int i;
11598 if (!set)
11599 return isl_bool_error;
11601 for (i = 0; i < set->n; ++i) {
11602 isl_bool r;
11604 r = test(set->p[i], user);
11605 if (r < 0 || !r)
11606 return r;
11609 return isl_bool_true;
11612 /* Return a list of basic sets, the union of which is equal to "set".
11614 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
11615 __isl_keep isl_set *set)
11617 int i;
11618 isl_basic_set_list *list;
11620 if (!set)
11621 return NULL;
11623 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
11624 for (i = 0; i < set->n; ++i) {
11625 isl_basic_set *bset;
11627 bset = isl_basic_set_copy(set->p[i]);
11628 list = isl_basic_set_list_add(list, bset);
11631 return list;
11634 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
11636 isl_space *space;
11638 if (!bset)
11639 return NULL;
11641 bset = isl_basic_set_cow(bset);
11642 if (!bset)
11643 return NULL;
11645 space = isl_basic_set_get_space(bset);
11646 space = isl_space_lift(space, bset->n_div);
11647 if (!space)
11648 goto error;
11649 isl_space_free(bset->dim);
11650 bset->dim = space;
11651 bset->extra -= bset->n_div;
11652 bset->n_div = 0;
11654 bset = isl_basic_set_finalize(bset);
11656 return bset;
11657 error:
11658 isl_basic_set_free(bset);
11659 return NULL;
11662 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
11664 int i;
11665 isl_space *space;
11666 unsigned n_div;
11668 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
11670 if (!set)
11671 return NULL;
11673 set = isl_set_cow(set);
11674 if (!set)
11675 return NULL;
11677 n_div = set->p[0]->n_div;
11678 space = isl_set_get_space(set);
11679 space = isl_space_lift(space, n_div);
11680 if (!space)
11681 goto error;
11682 isl_space_free(set->dim);
11683 set->dim = space;
11685 for (i = 0; i < set->n; ++i) {
11686 set->p[i] = isl_basic_set_lift(set->p[i]);
11687 if (!set->p[i])
11688 goto error;
11691 return set;
11692 error:
11693 isl_set_free(set);
11694 return NULL;
11697 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
11699 isl_size dim;
11700 int size = 0;
11702 dim = isl_basic_set_dim(bset, isl_dim_all);
11703 if (dim < 0)
11704 return -1;
11705 size += bset->n_eq * (1 + dim);
11706 size += bset->n_ineq * (1 + dim);
11707 size += bset->n_div * (2 + dim);
11709 return size;
11712 int isl_set_size(__isl_keep isl_set *set)
11714 int i;
11715 int size = 0;
11717 if (!set)
11718 return -1;
11720 for (i = 0; i < set->n; ++i)
11721 size += isl_basic_set_size(set->p[i]);
11723 return size;
11726 /* Check if there is any lower bound (if lower == 0) and/or upper
11727 * bound (if upper == 0) on the specified dim.
11729 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11730 enum isl_dim_type type, unsigned pos, int lower, int upper)
11732 int i;
11733 isl_bool involves;
11734 isl_size off;
11736 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
11737 return isl_bool_error;
11739 off = isl_basic_map_var_offset(bmap, type);
11740 if (off < 0)
11741 return isl_bool_error;
11742 involves = isl_basic_map_any_div_involves_vars(bmap, off + pos, 1);
11743 if (involves < 0 || involves)
11744 return involves;
11746 for (i = 0; i < bmap->n_eq; ++i)
11747 if (!isl_int_is_zero(bmap->eq[i][1 + off + pos]))
11748 return isl_bool_true;
11750 for (i = 0; i < bmap->n_ineq; ++i) {
11751 int sgn = isl_int_sgn(bmap->ineq[i][1 + off + pos]);
11752 if (sgn > 0)
11753 lower = 1;
11754 if (sgn < 0)
11755 upper = 1;
11758 return lower && upper;
11761 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11762 enum isl_dim_type type, unsigned pos)
11764 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
11767 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
11768 enum isl_dim_type type, unsigned pos)
11770 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
11773 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
11774 enum isl_dim_type type, unsigned pos)
11776 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
11779 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
11780 enum isl_dim_type type, unsigned pos)
11782 int i;
11784 if (!map)
11785 return isl_bool_error;
11787 for (i = 0; i < map->n; ++i) {
11788 isl_bool bounded;
11789 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
11790 if (bounded < 0 || !bounded)
11791 return bounded;
11794 return isl_bool_true;
11797 /* Return true if the specified dim is involved in both an upper bound
11798 * and a lower bound.
11800 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
11801 enum isl_dim_type type, unsigned pos)
11803 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
11806 /* Does "map" have a bound (according to "fn") for any of its basic maps?
11808 static isl_bool has_any_bound(__isl_keep isl_map *map,
11809 enum isl_dim_type type, unsigned pos,
11810 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11811 enum isl_dim_type type, unsigned pos))
11813 int i;
11815 if (!map)
11816 return isl_bool_error;
11818 for (i = 0; i < map->n; ++i) {
11819 isl_bool bounded;
11820 bounded = fn(map->p[i], type, pos);
11821 if (bounded < 0 || bounded)
11822 return bounded;
11825 return isl_bool_false;
11828 /* Return 1 if the specified dim is involved in any lower bound.
11830 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
11831 enum isl_dim_type type, unsigned pos)
11833 return has_any_bound(set, type, pos,
11834 &isl_basic_map_dim_has_lower_bound);
11837 /* Return 1 if the specified dim is involved in any upper bound.
11839 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
11840 enum isl_dim_type type, unsigned pos)
11842 return has_any_bound(set, type, pos,
11843 &isl_basic_map_dim_has_upper_bound);
11846 /* Does "map" have a bound (according to "fn") for all of its basic maps?
11848 static isl_bool has_bound(__isl_keep isl_map *map,
11849 enum isl_dim_type type, unsigned pos,
11850 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11851 enum isl_dim_type type, unsigned pos))
11853 int i;
11855 if (!map)
11856 return isl_bool_error;
11858 for (i = 0; i < map->n; ++i) {
11859 isl_bool bounded;
11860 bounded = fn(map->p[i], type, pos);
11861 if (bounded < 0 || !bounded)
11862 return bounded;
11865 return isl_bool_true;
11868 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
11870 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
11871 enum isl_dim_type type, unsigned pos)
11873 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
11876 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
11878 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
11879 enum isl_dim_type type, unsigned pos)
11881 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
11884 /* For each of the "n" variables starting at "first", determine
11885 * the sign of the variable and put the results in the first "n"
11886 * elements of the array "signs".
11887 * Sign
11888 * 1 means that the variable is non-negative
11889 * -1 means that the variable is non-positive
11890 * 0 means the variable attains both positive and negative values.
11892 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
11893 unsigned first, unsigned n, int *signs)
11895 isl_vec *bound = NULL;
11896 struct isl_tab *tab = NULL;
11897 struct isl_tab_undo *snap;
11898 int i;
11899 isl_size total;
11901 total = isl_basic_set_dim(bset, isl_dim_all);
11902 if (total < 0 || !signs)
11903 return isl_stat_error;
11905 bound = isl_vec_alloc(bset->ctx, 1 + total);
11906 tab = isl_tab_from_basic_set(bset, 0);
11907 if (!bound || !tab)
11908 goto error;
11910 isl_seq_clr(bound->el, bound->size);
11911 isl_int_set_si(bound->el[0], -1);
11913 snap = isl_tab_snap(tab);
11914 for (i = 0; i < n; ++i) {
11915 int empty;
11917 isl_int_set_si(bound->el[1 + first + i], -1);
11918 if (isl_tab_add_ineq(tab, bound->el) < 0)
11919 goto error;
11920 empty = tab->empty;
11921 isl_int_set_si(bound->el[1 + first + i], 0);
11922 if (isl_tab_rollback(tab, snap) < 0)
11923 goto error;
11925 if (empty) {
11926 signs[i] = 1;
11927 continue;
11930 isl_int_set_si(bound->el[1 + first + i], 1);
11931 if (isl_tab_add_ineq(tab, bound->el) < 0)
11932 goto error;
11933 empty = tab->empty;
11934 isl_int_set_si(bound->el[1 + first + i], 0);
11935 if (isl_tab_rollback(tab, snap) < 0)
11936 goto error;
11938 signs[i] = empty ? -1 : 0;
11941 isl_tab_free(tab);
11942 isl_vec_free(bound);
11943 return isl_stat_ok;
11944 error:
11945 isl_tab_free(tab);
11946 isl_vec_free(bound);
11947 return isl_stat_error;
11950 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
11951 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
11953 if (!bset || !signs)
11954 return isl_stat_error;
11955 if (isl_basic_set_check_range(bset, type, first, n) < 0)
11956 return isl_stat_error;
11958 first += pos(bset->dim, type) - 1;
11959 return isl_basic_set_vars_get_sign(bset, first, n, signs);
11962 /* Is it possible for the integer division "div" to depend (possibly
11963 * indirectly) on any output dimensions?
11965 * If the div is undefined, then we conservatively assume that it
11966 * may depend on them.
11967 * Otherwise, we check if it actually depends on them or on any integer
11968 * divisions that may depend on them.
11970 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
11972 int i;
11973 isl_size n_out, n_div;
11974 unsigned o_out, o_div;
11976 if (isl_int_is_zero(bmap->div[div][0]))
11977 return isl_bool_true;
11979 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11980 if (n_out < 0)
11981 return isl_bool_error;
11982 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11984 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
11985 return isl_bool_true;
11987 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11988 if (n_div < 0)
11989 return isl_bool_error;
11990 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11992 for (i = 0; i < n_div; ++i) {
11993 isl_bool may_involve;
11995 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
11996 continue;
11997 may_involve = div_may_involve_output(bmap, i);
11998 if (may_involve < 0 || may_involve)
11999 return may_involve;
12002 return isl_bool_false;
12005 /* Return the first integer division of "bmap" in the range
12006 * [first, first + n[ that may depend on any output dimensions and
12007 * that has a non-zero coefficient in "c" (where the first coefficient
12008 * in "c" corresponds to integer division "first").
12010 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
12011 isl_int *c, int first, int n)
12013 int k;
12015 if (!bmap)
12016 return -1;
12018 for (k = first; k < first + n; ++k) {
12019 isl_bool may_involve;
12021 if (isl_int_is_zero(c[k]))
12022 continue;
12023 may_involve = div_may_involve_output(bmap, k);
12024 if (may_involve < 0)
12025 return -1;
12026 if (may_involve)
12027 return k;
12030 return first + n;
12033 /* Look for a pair of inequality constraints in "bmap" of the form
12035 * -l + i >= 0 or i >= l
12036 * and
12037 * n + l - i >= 0 or i <= l + n
12039 * with n < "m" and i the output dimension at position "pos".
12040 * (Note that n >= 0 as otherwise the two constraints would conflict.)
12041 * Furthermore, "l" is only allowed to involve parameters, input dimensions
12042 * and earlier output dimensions, as well as integer divisions that do
12043 * not involve any of the output dimensions.
12045 * Return the index of the first inequality constraint or bmap->n_ineq
12046 * if no such pair can be found.
12048 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
12049 int pos, isl_int m)
12051 int i, j;
12052 isl_ctx *ctx;
12053 isl_size total;
12054 isl_size n_div, n_out;
12055 unsigned o_div, o_out;
12056 int less;
12058 total = isl_basic_map_dim(bmap, isl_dim_all);
12059 n_out = isl_basic_map_dim(bmap, isl_dim_out);
12060 n_div = isl_basic_map_dim(bmap, isl_dim_div);
12061 if (total < 0 || n_out < 0 || n_div < 0)
12062 return -1;
12064 ctx = isl_basic_map_get_ctx(bmap);
12065 o_out = isl_basic_map_offset(bmap, isl_dim_out);
12066 o_div = isl_basic_map_offset(bmap, isl_dim_div);
12067 for (i = 0; i < bmap->n_ineq; ++i) {
12068 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
12069 continue;
12070 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
12071 n_out - (pos + 1)) != -1)
12072 continue;
12073 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
12074 0, n_div) < n_div)
12075 continue;
12076 for (j = i + 1; j < bmap->n_ineq; ++j) {
12077 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
12078 ctx->one))
12079 continue;
12080 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
12081 bmap->ineq[j] + 1, total))
12082 continue;
12083 break;
12085 if (j >= bmap->n_ineq)
12086 continue;
12087 isl_int_add(bmap->ineq[i][0],
12088 bmap->ineq[i][0], bmap->ineq[j][0]);
12089 less = isl_int_abs_lt(bmap->ineq[i][0], m);
12090 isl_int_sub(bmap->ineq[i][0],
12091 bmap->ineq[i][0], bmap->ineq[j][0]);
12092 if (!less)
12093 continue;
12094 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
12095 return i;
12096 else
12097 return j;
12100 return bmap->n_ineq;
12103 /* Return the index of the equality of "bmap" that defines
12104 * the output dimension "pos" in terms of earlier dimensions.
12105 * The equality may also involve integer divisions, as long
12106 * as those integer divisions are defined in terms of
12107 * parameters or input dimensions.
12108 * In this case, *div is set to the number of integer divisions and
12109 * *ineq is set to the number of inequality constraints (provided
12110 * div and ineq are not NULL).
12112 * The equality may also involve a single integer division involving
12113 * the output dimensions (typically only output dimension "pos") as
12114 * long as the coefficient of output dimension "pos" is 1 or -1 and
12115 * there is a pair of constraints i >= l and i <= l + n, with i referring
12116 * to output dimension "pos", l an expression involving only earlier
12117 * dimensions and n smaller than the coefficient of the integer division
12118 * in the equality. In this case, the output dimension can be defined
12119 * in terms of a modulo expression that does not involve the integer division.
12120 * *div is then set to this single integer division and
12121 * *ineq is set to the index of constraint i >= l.
12123 * Return bmap->n_eq if there is no such equality.
12124 * Return -1 on error.
12126 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
12127 int pos, int *div, int *ineq)
12129 int j, k, l;
12130 isl_size n_div, n_out;
12131 unsigned o_div, o_out;
12133 n_out = isl_basic_map_dim(bmap, isl_dim_out);
12134 n_div = isl_basic_map_dim(bmap, isl_dim_div);
12135 if (n_out < 0 || n_div < 0)
12136 return -1;
12138 o_out = isl_basic_map_offset(bmap, isl_dim_out);
12139 o_div = isl_basic_map_offset(bmap, isl_dim_div);
12141 if (ineq)
12142 *ineq = bmap->n_ineq;
12143 if (div)
12144 *div = n_div;
12145 for (j = 0; j < bmap->n_eq; ++j) {
12146 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
12147 continue;
12148 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
12149 n_out - (pos + 1)) != -1)
12150 continue;
12151 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
12152 0, n_div);
12153 if (k >= n_div)
12154 return j;
12155 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
12156 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
12157 continue;
12158 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
12159 k + 1, n_div - (k+1)) < n_div)
12160 continue;
12161 l = find_modulo_constraint_pair(bmap, pos,
12162 bmap->eq[j][o_div + k]);
12163 if (l < 0)
12164 return -1;
12165 if (l >= bmap->n_ineq)
12166 continue;
12167 if (div)
12168 *div = k;
12169 if (ineq)
12170 *ineq = l;
12171 return j;
12174 return bmap->n_eq;
12177 /* Check if the given basic map is obviously single-valued.
12178 * In particular, for each output dimension, check that there is
12179 * an equality that defines the output dimension in terms of
12180 * earlier dimensions.
12182 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
12184 int i;
12185 isl_size n_out;
12187 n_out = isl_basic_map_dim(bmap, isl_dim_out);
12188 if (n_out < 0)
12189 return isl_bool_error;
12191 for (i = 0; i < n_out; ++i) {
12192 int eq;
12194 eq = isl_basic_map_output_defining_equality(bmap, i,
12195 NULL, NULL);
12196 if (eq < 0)
12197 return isl_bool_error;
12198 if (eq >= bmap->n_eq)
12199 return isl_bool_false;
12202 return isl_bool_true;
12205 /* Check if the given basic map is single-valued.
12206 * We simply compute
12208 * M \circ M^-1
12210 * and check if the result is a subset of the identity mapping.
12212 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
12214 isl_space *space;
12215 isl_basic_map *test;
12216 isl_basic_map *id;
12217 isl_bool sv;
12219 sv = isl_basic_map_plain_is_single_valued(bmap);
12220 if (sv < 0 || sv)
12221 return sv;
12223 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
12224 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
12226 space = isl_basic_map_get_space(bmap);
12227 space = isl_space_map_from_set(isl_space_range(space));
12228 id = isl_basic_map_identity(space);
12230 sv = isl_basic_map_is_subset(test, id);
12232 isl_basic_map_free(test);
12233 isl_basic_map_free(id);
12235 return sv;
12238 /* Check if the given map is obviously single-valued.
12240 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
12242 if (!map)
12243 return isl_bool_error;
12244 if (map->n == 0)
12245 return isl_bool_true;
12246 if (map->n >= 2)
12247 return isl_bool_false;
12249 return isl_basic_map_plain_is_single_valued(map->p[0]);
12252 /* Check if the given map is single-valued.
12253 * We simply compute
12255 * M \circ M^-1
12257 * and check if the result is a subset of the identity mapping.
12259 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
12261 isl_space *space;
12262 isl_map *test;
12263 isl_map *id;
12264 isl_bool sv;
12266 sv = isl_map_plain_is_single_valued(map);
12267 if (sv < 0 || sv)
12268 return sv;
12270 test = isl_map_reverse(isl_map_copy(map));
12271 test = isl_map_apply_range(test, isl_map_copy(map));
12273 space = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
12274 id = isl_map_identity(space);
12276 sv = isl_map_is_subset(test, id);
12278 isl_map_free(test);
12279 isl_map_free(id);
12281 return sv;
12284 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
12286 isl_bool in;
12288 map = isl_map_copy(map);
12289 map = isl_map_reverse(map);
12290 in = isl_map_is_single_valued(map);
12291 isl_map_free(map);
12293 return in;
12296 /* Check if the given map is obviously injective.
12298 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
12300 isl_bool in;
12302 map = isl_map_copy(map);
12303 map = isl_map_reverse(map);
12304 in = isl_map_plain_is_single_valued(map);
12305 isl_map_free(map);
12307 return in;
12310 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
12312 isl_bool sv;
12314 sv = isl_map_is_single_valued(map);
12315 if (sv < 0 || !sv)
12316 return sv;
12318 return isl_map_is_injective(map);
12321 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
12323 return isl_map_is_single_valued(set_to_map(set));
12326 /* Does "map" only map elements to themselves?
12328 * If the domain and range spaces are different, then "map"
12329 * is considered not to be an identity relation, even if it is empty.
12330 * Otherwise, construct the maximal identity relation and
12331 * check whether "map" is a subset of this relation.
12333 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
12335 isl_map *id;
12336 isl_bool equal, is_identity;
12338 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
12339 if (equal < 0 || !equal)
12340 return equal;
12342 id = isl_map_identity(isl_map_get_space(map));
12343 is_identity = isl_map_is_subset(map, id);
12344 isl_map_free(id);
12346 return is_identity;
12349 int isl_map_is_translation(__isl_keep isl_map *map)
12351 int ok;
12352 isl_set *delta;
12354 delta = isl_map_deltas(isl_map_copy(map));
12355 ok = isl_set_is_singleton(delta);
12356 isl_set_free(delta);
12358 return ok;
12361 static int unique(isl_int *p, unsigned pos, unsigned len)
12363 if (isl_seq_first_non_zero(p, pos) != -1)
12364 return 0;
12365 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
12366 return 0;
12367 return 1;
12370 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
12372 int i, j;
12373 isl_size nvar, ovar, n_div;
12375 n_div = isl_basic_set_dim(bset, isl_dim_div);
12376 if (n_div < 0)
12377 return isl_bool_error;
12378 if (n_div != 0)
12379 return isl_bool_false;
12381 nvar = isl_basic_set_dim(bset, isl_dim_set);
12382 ovar = isl_space_offset(bset->dim, isl_dim_set);
12383 if (nvar < 0 || ovar < 0)
12384 return isl_bool_error;
12385 for (j = 0; j < nvar; ++j) {
12386 int lower = 0, upper = 0;
12387 for (i = 0; i < bset->n_eq; ++i) {
12388 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
12389 continue;
12390 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
12391 return isl_bool_false;
12392 break;
12394 if (i < bset->n_eq)
12395 continue;
12396 for (i = 0; i < bset->n_ineq; ++i) {
12397 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
12398 continue;
12399 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
12400 return isl_bool_false;
12401 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
12402 lower = 1;
12403 else
12404 upper = 1;
12406 if (!lower || !upper)
12407 return isl_bool_false;
12410 return isl_bool_true;
12413 isl_bool isl_set_is_box(__isl_keep isl_set *set)
12415 if (!set)
12416 return isl_bool_error;
12417 if (set->n != 1)
12418 return isl_bool_false;
12420 return isl_basic_set_is_box(set->p[0]);
12423 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
12425 if (!bset)
12426 return isl_bool_error;
12428 return isl_space_is_wrapping(bset->dim);
12431 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
12433 if (!set)
12434 return isl_bool_error;
12436 return isl_space_is_wrapping(set->dim);
12439 /* Modify the space of "map" through a call to "change".
12440 * If "can_change" is set (not NULL), then first call it to check
12441 * if the modification is allowed, printing the error message "cannot_change"
12442 * if it is not.
12444 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
12445 isl_bool (*can_change)(__isl_keep isl_map *map),
12446 const char *cannot_change,
12447 __isl_give isl_space *(*change)(__isl_take isl_space *space))
12449 isl_bool ok;
12450 isl_space *space;
12452 if (!map)
12453 return NULL;
12455 ok = can_change ? can_change(map) : isl_bool_true;
12456 if (ok < 0)
12457 return isl_map_free(map);
12458 if (!ok)
12459 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
12460 return isl_map_free(map));
12462 space = change(isl_map_get_space(map));
12463 map = isl_map_reset_space(map, space);
12465 return map;
12468 /* Is the domain of "map" a wrapped relation?
12470 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
12472 if (!map)
12473 return isl_bool_error;
12475 return isl_space_domain_is_wrapping(map->dim);
12478 /* Does "map" have a wrapped relation in both domain and range?
12480 isl_bool isl_map_is_product(__isl_keep isl_map *map)
12482 return isl_space_is_product(isl_map_peek_space(map));
12485 /* Is the range of "map" a wrapped relation?
12487 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
12489 if (!map)
12490 return isl_bool_error;
12492 return isl_space_range_is_wrapping(map->dim);
12495 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
12497 isl_space *space;
12499 space = isl_basic_map_take_space(bmap);
12500 space = isl_space_wrap(space);
12501 bmap = isl_basic_map_restore_space(bmap, space);
12503 bmap = isl_basic_map_finalize(bmap);
12505 return bset_from_bmap(bmap);
12508 /* Given a map A -> B, return the set (A -> B).
12510 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
12512 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
12515 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
12517 bset = isl_basic_set_cow(bset);
12518 if (!bset)
12519 return NULL;
12521 bset->dim = isl_space_unwrap(bset->dim);
12522 if (!bset->dim)
12523 goto error;
12525 bset = isl_basic_set_finalize(bset);
12527 return bset_to_bmap(bset);
12528 error:
12529 isl_basic_set_free(bset);
12530 return NULL;
12533 /* Given a set (A -> B), return the map A -> B.
12534 * Error out if "set" is not of the form (A -> B).
12536 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
12538 return isl_map_change_space(set, &isl_set_is_wrapping,
12539 "not a wrapping set", &isl_space_unwrap);
12542 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
12543 enum isl_dim_type type)
12545 isl_space *space;
12547 space = isl_basic_map_take_space(bmap);
12548 space = isl_space_reset(space, type);
12549 bmap = isl_basic_map_restore_space(bmap, space);
12551 bmap = isl_basic_map_mark_final(bmap);
12553 return bmap;
12556 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
12557 enum isl_dim_type type)
12559 int i;
12560 isl_space *space;
12562 if (!map)
12563 return NULL;
12565 if (!isl_space_is_named_or_nested(map->dim, type))
12566 return map;
12568 map = isl_map_cow(map);
12569 if (!map)
12570 return NULL;
12572 for (i = 0; i < map->n; ++i) {
12573 map->p[i] = isl_basic_map_reset(map->p[i], type);
12574 if (!map->p[i])
12575 goto error;
12578 space = isl_map_take_space(map);
12579 space = isl_space_reset(space, type);
12580 map = isl_map_restore_space(map, space);
12582 return map;
12583 error:
12584 isl_map_free(map);
12585 return NULL;
12588 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
12590 isl_space *space;
12592 space = isl_basic_map_take_space(bmap);
12593 space = isl_space_flatten(space);
12594 bmap = isl_basic_map_restore_space(bmap, space);
12596 bmap = isl_basic_map_mark_final(bmap);
12598 return bmap;
12601 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
12603 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
12606 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
12607 __isl_take isl_basic_map *bmap)
12609 isl_space *space;
12611 space = isl_basic_map_take_space(bmap);
12612 space = isl_space_flatten_domain(space);
12613 bmap = isl_basic_map_restore_space(bmap, space);
12615 bmap = isl_basic_map_mark_final(bmap);
12617 return bmap;
12620 __isl_give isl_basic_map *isl_basic_map_flatten_range(
12621 __isl_take isl_basic_map *bmap)
12623 isl_space *space;
12625 space = isl_basic_map_take_space(bmap);
12626 space = isl_space_flatten_range(space);
12627 bmap = isl_basic_map_restore_space(bmap, space);
12629 bmap = isl_basic_map_mark_final(bmap);
12631 return bmap;
12634 /* Remove any internal structure from the spaces of domain and range of "map".
12636 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
12638 if (!map)
12639 return NULL;
12641 if (!map->dim->nested[0] && !map->dim->nested[1])
12642 return map;
12644 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
12647 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
12649 return set_from_map(isl_map_flatten(set_to_map(set)));
12652 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
12654 isl_space *space, *flat_space;
12655 isl_map *map;
12657 space = isl_set_get_space(set);
12658 flat_space = isl_space_flatten(isl_space_copy(space));
12659 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
12660 flat_space));
12661 map = isl_map_intersect_domain(map, set);
12663 return map;
12666 /* Remove any internal structure from the space of the domain of "map".
12668 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
12670 if (!map)
12671 return NULL;
12673 if (!map->dim->nested[0])
12674 return map;
12676 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
12679 /* Remove any internal structure from the space of the range of "map".
12681 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
12683 if (!map)
12684 return NULL;
12686 if (!map->dim->nested[1])
12687 return map;
12689 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
12692 /* Reorder the dimensions of "bmap" according to the given dim_map
12693 * and set the dimension specification to "space" and
12694 * perform Gaussian elimination on the result.
12696 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
12697 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
12699 isl_basic_map *res;
12700 unsigned flags;
12701 isl_size n_div;
12703 n_div = isl_basic_map_dim(bmap, isl_dim_div);
12704 if (n_div < 0 || !space || !dim_map)
12705 goto error;
12707 flags = bmap->flags;
12708 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
12709 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
12710 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
12711 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
12712 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
12713 if (res)
12714 res->flags = flags;
12715 res = isl_basic_map_gauss(res, NULL);
12716 res = isl_basic_map_finalize(res);
12717 return res;
12718 error:
12719 isl_dim_map_free(dim_map);
12720 isl_basic_map_free(bmap);
12721 isl_space_free(space);
12722 return NULL;
12725 /* Reorder the dimensions of "map" according to given reordering.
12727 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
12728 __isl_take isl_reordering *r)
12730 int i;
12731 struct isl_dim_map *dim_map;
12733 map = isl_map_cow(map);
12734 dim_map = isl_dim_map_from_reordering(r);
12735 if (!map || !r || !dim_map)
12736 goto error;
12738 for (i = 0; i < map->n; ++i) {
12739 struct isl_dim_map *dim_map_i;
12740 isl_space *space;
12742 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
12744 space = isl_reordering_get_space(r);
12745 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
12747 if (!map->p[i])
12748 goto error;
12751 map = isl_map_reset_space(map, isl_reordering_get_space(r));
12752 map = isl_map_unmark_normalized(map);
12754 isl_reordering_free(r);
12755 isl_dim_map_free(dim_map);
12756 return map;
12757 error:
12758 isl_dim_map_free(dim_map);
12759 isl_map_free(map);
12760 isl_reordering_free(r);
12761 return NULL;
12764 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
12765 __isl_take isl_reordering *r)
12767 return set_from_map(isl_map_realign(set_to_map(set), r));
12770 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
12771 __isl_take isl_space *model)
12773 isl_ctx *ctx;
12774 isl_bool aligned;
12776 if (!map || !model)
12777 goto error;
12779 ctx = isl_space_get_ctx(model);
12780 if (!isl_space_has_named_params(model))
12781 isl_die(ctx, isl_error_invalid,
12782 "model has unnamed parameters", goto error);
12783 if (isl_map_check_named_params(map) < 0)
12784 goto error;
12785 aligned = isl_map_space_has_equal_params(map, model);
12786 if (aligned < 0)
12787 goto error;
12788 if (!aligned) {
12789 isl_space *space;
12790 isl_reordering *exp;
12792 space = isl_map_peek_space(map);
12793 exp = isl_parameter_alignment_reordering(space, model);
12794 map = isl_map_realign(map, exp);
12797 isl_space_free(model);
12798 return map;
12799 error:
12800 isl_space_free(model);
12801 isl_map_free(map);
12802 return NULL;
12805 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
12806 __isl_take isl_space *model)
12808 return isl_map_align_params(set, model);
12811 /* Align the parameters of "bmap" to those of "model", introducing
12812 * additional parameters if needed.
12814 __isl_give isl_basic_map *isl_basic_map_align_params(
12815 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
12817 isl_ctx *ctx;
12818 isl_bool equal_params;
12819 isl_space *bmap_space;
12821 if (!bmap || !model)
12822 goto error;
12824 ctx = isl_space_get_ctx(model);
12825 if (!isl_space_has_named_params(model))
12826 isl_die(ctx, isl_error_invalid,
12827 "model has unnamed parameters", goto error);
12828 if (isl_basic_map_check_named_params(bmap) < 0)
12829 goto error;
12830 bmap_space = isl_basic_map_peek_space(bmap);
12831 equal_params = isl_space_has_equal_params(bmap_space, model);
12832 if (equal_params < 0)
12833 goto error;
12834 if (!equal_params) {
12835 isl_reordering *exp;
12836 struct isl_dim_map *dim_map;
12838 exp = isl_parameter_alignment_reordering(bmap_space, model);
12839 dim_map = isl_dim_map_from_reordering(exp);
12840 bmap = isl_basic_map_realign(bmap,
12841 isl_reordering_get_space(exp),
12842 isl_dim_map_extend(dim_map, bmap));
12843 isl_reordering_free(exp);
12844 isl_dim_map_free(dim_map);
12847 isl_space_free(model);
12848 return bmap;
12849 error:
12850 isl_space_free(model);
12851 isl_basic_map_free(bmap);
12852 return NULL;
12855 /* Do "bset" and "space" have the same parameters?
12857 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
12858 __isl_keep isl_space *space)
12860 isl_space *bset_space;
12862 bset_space = isl_basic_set_peek_space(bset);
12863 return isl_space_has_equal_params(bset_space, space);
12866 /* Do "map" and "space" have the same parameters?
12868 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
12869 __isl_keep isl_space *space)
12871 isl_space *map_space;
12873 map_space = isl_map_peek_space(map);
12874 return isl_space_has_equal_params(map_space, space);
12877 /* Do "set" and "space" have the same parameters?
12879 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
12880 __isl_keep isl_space *space)
12882 return isl_map_space_has_equal_params(set_to_map(set), space);
12885 /* Align the parameters of "bset" to those of "model", introducing
12886 * additional parameters if needed.
12888 __isl_give isl_basic_set *isl_basic_set_align_params(
12889 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
12891 return isl_basic_map_align_params(bset, model);
12894 #undef TYPE
12895 #define TYPE isl_map
12896 #define isl_map_drop_dims isl_map_drop
12897 #include "isl_drop_unused_params_templ.c"
12899 /* Drop all parameters not referenced by "set".
12901 __isl_give isl_set *isl_set_drop_unused_params(
12902 __isl_take isl_set *set)
12904 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
12907 #undef TYPE
12908 #define TYPE isl_basic_map
12909 #define isl_basic_map_drop_dims isl_basic_map_drop
12910 #include "isl_drop_unused_params_templ.c"
12912 /* Drop all parameters not referenced by "bset".
12914 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
12915 __isl_take isl_basic_set *bset)
12917 return bset_from_bmap(isl_basic_map_drop_unused_params(
12918 bset_to_bmap(bset)));
12921 /* Given a tuple of identifiers "tuple" in a space that corresponds
12922 * to that of "set", if any of those identifiers appear as parameters
12923 * in "set", then equate those parameters with the corresponding
12924 * set dimensions and project out the parameters.
12925 * The result therefore has no such parameters.
12927 static __isl_give isl_set *equate_params(__isl_take isl_set *set,
12928 __isl_keep isl_multi_id *tuple)
12930 int i;
12931 isl_size n;
12932 isl_space *set_space, *tuple_space;
12934 set_space = isl_set_peek_space(set);
12935 tuple_space = isl_multi_id_peek_space(tuple);
12936 if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
12937 return isl_set_free(set);
12938 n = isl_multi_id_size(tuple);
12939 if (n < 0)
12940 return isl_set_free(set);
12941 for (i = 0; i < n; ++i) {
12942 isl_id *id;
12943 int pos;
12945 id = isl_multi_id_get_at(tuple, i);
12946 if (!id)
12947 return isl_set_free(set);
12948 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
12949 isl_id_free(id);
12950 if (pos < 0)
12951 continue;
12952 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
12953 set = isl_set_project_out(set, isl_dim_param, pos, 1);
12955 return set;
12958 /* Bind the set dimensions of "set" to parameters with identifiers
12959 * specified by "tuple", living in the same space as "set".
12961 * If no parameters with these identifiers appear in "set" already,
12962 * then the set dimensions are simply reinterpreted as parameters.
12963 * Otherwise, the parameters are first equated to the corresponding
12964 * set dimensions.
12966 __isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
12967 __isl_take isl_multi_id *tuple)
12969 isl_space *space;
12971 set = equate_params(set, tuple);
12972 space = isl_set_get_space(set);
12973 space = isl_space_bind_set(space, tuple);
12974 isl_multi_id_free(tuple);
12975 set = isl_set_reset_space(set, space);
12977 return set;
12980 /* Given a tuple of identifiers "tuple" in a space that corresponds
12981 * to the domain of "map", if any of those identifiers appear as parameters
12982 * in "map", then equate those parameters with the corresponding
12983 * input dimensions and project out the parameters.
12984 * The result therefore has no such parameters.
12986 static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
12987 __isl_keep isl_multi_id *tuple)
12989 int i;
12990 isl_size n;
12991 isl_space *map_space, *tuple_space;
12993 map_space = isl_map_peek_space(map);
12994 tuple_space = isl_multi_id_peek_space(tuple);
12995 if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
12996 return isl_map_free(map);
12997 n = isl_multi_id_size(tuple);
12998 if (n < 0)
12999 return isl_map_free(map);
13000 for (i = 0; i < n; ++i) {
13001 isl_id *id;
13002 int pos;
13004 id = isl_multi_id_get_at(tuple, i);
13005 if (!id)
13006 return isl_map_free(map);
13007 pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
13008 isl_id_free(id);
13009 if (pos < 0)
13010 continue;
13011 map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
13012 map = isl_map_project_out(map, isl_dim_param, pos, 1);
13014 return map;
13017 /* Bind the input dimensions of "map" to parameters with identifiers
13018 * specified by "tuple", living in the domain space of "map".
13020 * If no parameters with these identifiers appear in "map" already,
13021 * then the input dimensions are simply reinterpreted as parameters.
13022 * Otherwise, the parameters are first equated to the corresponding
13023 * input dimensions.
13025 __isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
13026 __isl_take isl_multi_id *tuple)
13028 isl_space *space;
13029 isl_set *set;
13031 map = map_equate_params(map, tuple);
13032 space = isl_map_get_space(map);
13033 space = isl_space_bind_map_domain(space, tuple);
13034 isl_multi_id_free(tuple);
13035 set = set_from_map(isl_map_reset_space(map, space));
13037 return set;
13040 /* Bind the output dimensions of "map" to parameters with identifiers
13041 * specified by "tuple", living in the range space of "map".
13043 * Since binding is more easily implemented on the domain,
13044 * bind the input dimensions of the inverse of "map".
13046 __isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
13047 __isl_take isl_multi_id *tuple)
13049 return isl_map_bind_domain(isl_map_reverse(map), tuple);
13052 /* Insert a domain corresponding to "tuple"
13053 * into the nullary or unary relation "set".
13054 * The result has an extra initial tuple and is therefore
13055 * either a unary or binary relation.
13056 * Any parameters with identifiers in "tuple" are reinterpreted
13057 * as the corresponding domain dimensions.
13059 static __isl_give isl_map *unbind_params_insert_domain(
13060 __isl_take isl_set *set, __isl_take isl_multi_id *tuple)
13062 isl_space *space;
13063 isl_reordering *r;
13065 space = isl_set_peek_space(set);
13066 r = isl_reordering_unbind_params_insert_domain(space, tuple);
13067 isl_multi_id_free(tuple);
13069 return isl_map_realign(set_to_map(set), r);
13072 /* Construct a set with "tuple" as domain from the parameter domain "set".
13073 * Any parameters with identifiers in "tuple" are reinterpreted
13074 * as the corresponding set dimensions.
13076 __isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
13077 __isl_take isl_multi_id *tuple)
13079 isl_bool is_params;
13081 is_params = isl_set_is_params(set);
13082 if (is_params < 0)
13083 set = isl_set_free(set);
13084 else if (!is_params)
13085 isl_die(isl_set_get_ctx(set), isl_error_invalid,
13086 "expecting parameter domain", set = isl_set_free(set));
13087 return set_from_map(unbind_params_insert_domain(set, tuple));
13090 /* Check that "set" is a proper set, i.e., that it is not a parameter domain.
13092 static isl_stat isl_set_check_is_set(__isl_keep isl_set *set)
13094 isl_bool is_params;
13096 is_params = isl_set_is_params(set);
13097 if (is_params < 0)
13098 return isl_stat_error;
13099 else if (is_params)
13100 isl_die(isl_set_get_ctx(set), isl_error_invalid,
13101 "expecting proper set", return isl_stat_error);
13103 return isl_stat_ok;
13106 /* Construct a map with "domain" as domain and "set" as range.
13107 * Any parameters with identifiers in "domain" are reinterpreted
13108 * as the corresponding domain dimensions.
13110 __isl_give isl_map *isl_set_unbind_params_insert_domain(
13111 __isl_take isl_set *set, __isl_take isl_multi_id *domain)
13113 if (isl_set_check_is_set(set) < 0)
13114 set = isl_set_free(set);
13115 return unbind_params_insert_domain(set, domain);
13118 /* Construct a map with "domain" as domain and "set" as range.
13120 __isl_give isl_map *isl_set_insert_domain(__isl_take isl_set *set,
13121 __isl_take isl_space *domain)
13123 isl_size dim;
13124 isl_space *space;
13125 isl_map *map;
13127 if (isl_set_check_is_set(set) < 0 || isl_space_check_is_set(domain) < 0)
13128 domain = isl_space_free(domain);
13129 dim = isl_space_dim(domain, isl_dim_set);
13130 if (dim < 0)
13131 domain = isl_space_free(domain);
13132 space = isl_set_get_space(set);
13133 domain = isl_space_replace_params(domain, space);
13134 space = isl_space_map_from_domain_and_range(domain, space);
13136 map = isl_map_from_range(set);
13137 map = isl_map_add_dims(map, isl_dim_in, dim);
13138 map = isl_map_reset_space(map, space);
13140 return map;
13143 __isl_give isl_mat *isl_basic_map_equalities_matrix(
13144 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
13145 enum isl_dim_type c2, enum isl_dim_type c3,
13146 enum isl_dim_type c4, enum isl_dim_type c5)
13148 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
13149 struct isl_mat *mat;
13150 int i, j, k;
13151 int pos;
13152 isl_size total;
13154 total = isl_basic_map_dim(bmap, isl_dim_all);
13155 if (total < 0)
13156 return NULL;
13157 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
13158 if (!mat)
13159 return NULL;
13160 for (i = 0; i < bmap->n_eq; ++i)
13161 for (j = 0, pos = 0; j < 5; ++j) {
13162 int off = isl_basic_map_offset(bmap, c[j]);
13163 isl_size dim = isl_basic_map_dim(bmap, c[j]);
13164 if (dim < 0)
13165 return isl_mat_free(mat);
13166 for (k = 0; k < dim; ++k) {
13167 isl_int_set(mat->row[i][pos],
13168 bmap->eq[i][off + k]);
13169 ++pos;
13173 return mat;
13176 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
13177 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
13178 enum isl_dim_type c2, enum isl_dim_type c3,
13179 enum isl_dim_type c4, enum isl_dim_type c5)
13181 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
13182 struct isl_mat *mat;
13183 int i, j, k;
13184 int pos;
13185 isl_size total;
13187 total = isl_basic_map_dim(bmap, isl_dim_all);
13188 if (total < 0)
13189 return NULL;
13190 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
13191 if (!mat)
13192 return NULL;
13193 for (i = 0; i < bmap->n_ineq; ++i)
13194 for (j = 0, pos = 0; j < 5; ++j) {
13195 int off = isl_basic_map_offset(bmap, c[j]);
13196 isl_size dim = isl_basic_map_dim(bmap, c[j]);
13197 if (dim < 0)
13198 return isl_mat_free(mat);
13199 for (k = 0; k < dim; ++k) {
13200 isl_int_set(mat->row[i][pos],
13201 bmap->ineq[i][off + k]);
13202 ++pos;
13206 return mat;
13209 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
13210 __isl_take isl_space *space,
13211 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
13212 enum isl_dim_type c2, enum isl_dim_type c3,
13213 enum isl_dim_type c4, enum isl_dim_type c5)
13215 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
13216 isl_basic_map *bmap = NULL;
13217 isl_size dim;
13218 unsigned total;
13219 unsigned extra;
13220 int i, j, k, l;
13221 int pos;
13223 dim = isl_space_dim(space, isl_dim_all);
13224 if (dim < 0 || !eq || !ineq)
13225 goto error;
13227 if (eq->n_col != ineq->n_col)
13228 isl_die(space->ctx, isl_error_invalid,
13229 "equalities and inequalities matrices should have "
13230 "same number of columns", goto error);
13232 total = 1 + dim;
13234 if (eq->n_col < total)
13235 isl_die(space->ctx, isl_error_invalid,
13236 "number of columns too small", goto error);
13238 extra = eq->n_col - total;
13240 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
13241 eq->n_row, ineq->n_row);
13242 if (!bmap)
13243 goto error;
13244 for (i = 0; i < extra; ++i) {
13245 k = isl_basic_map_alloc_div(bmap);
13246 if (k < 0)
13247 goto error;
13248 isl_int_set_si(bmap->div[k][0], 0);
13250 for (i = 0; i < eq->n_row; ++i) {
13251 l = isl_basic_map_alloc_equality(bmap);
13252 if (l < 0)
13253 goto error;
13254 for (j = 0, pos = 0; j < 5; ++j) {
13255 int off = isl_basic_map_offset(bmap, c[j]);
13256 isl_size dim = isl_basic_map_dim(bmap, c[j]);
13257 if (dim < 0)
13258 goto error;
13259 for (k = 0; k < dim; ++k) {
13260 isl_int_set(bmap->eq[l][off + k],
13261 eq->row[i][pos]);
13262 ++pos;
13266 for (i = 0; i < ineq->n_row; ++i) {
13267 l = isl_basic_map_alloc_inequality(bmap);
13268 if (l < 0)
13269 goto error;
13270 for (j = 0, pos = 0; j < 5; ++j) {
13271 int off = isl_basic_map_offset(bmap, c[j]);
13272 isl_size dim = isl_basic_map_dim(bmap, c[j]);
13273 if (dim < 0)
13274 goto error;
13275 for (k = 0; k < dim; ++k) {
13276 isl_int_set(bmap->ineq[l][off + k],
13277 ineq->row[i][pos]);
13278 ++pos;
13283 isl_space_free(space);
13284 isl_mat_free(eq);
13285 isl_mat_free(ineq);
13287 bmap = isl_basic_map_simplify(bmap);
13288 return isl_basic_map_finalize(bmap);
13289 error:
13290 isl_space_free(space);
13291 isl_mat_free(eq);
13292 isl_mat_free(ineq);
13293 isl_basic_map_free(bmap);
13294 return NULL;
13297 __isl_give isl_mat *isl_basic_set_equalities_matrix(
13298 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
13299 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
13301 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
13302 c1, c2, c3, c4, isl_dim_in);
13305 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
13306 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
13307 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
13309 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
13310 c1, c2, c3, c4, isl_dim_in);
13313 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
13314 __isl_take isl_space *space,
13315 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
13316 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
13318 isl_basic_map *bmap;
13319 bmap = isl_basic_map_from_constraint_matrices(space, eq, ineq,
13320 c1, c2, c3, c4, isl_dim_in);
13321 return bset_from_bmap(bmap);
13324 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
13326 if (!bmap)
13327 return isl_bool_error;
13329 return isl_space_can_zip(bmap->dim);
13332 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
13334 if (!map)
13335 return isl_bool_error;
13337 return isl_space_can_zip(map->dim);
13340 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
13341 * (A -> C) -> (B -> D).
13343 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
13345 unsigned pos;
13346 isl_size n_in;
13347 isl_size n1;
13348 isl_size n2;
13350 if (!bmap)
13351 return NULL;
13353 if (!isl_basic_map_can_zip(bmap))
13354 isl_die(bmap->ctx, isl_error_invalid,
13355 "basic map cannot be zipped", goto error);
13356 n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
13357 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
13358 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
13359 if (n_in < 0 || n1 < 0 || n2 < 0)
13360 return isl_basic_map_free(bmap);
13361 pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
13362 bmap = isl_basic_map_cow(bmap);
13363 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
13364 if (!bmap)
13365 return NULL;
13366 bmap->dim = isl_space_zip(bmap->dim);
13367 if (!bmap->dim)
13368 goto error;
13369 bmap = isl_basic_map_mark_final(bmap);
13370 return bmap;
13371 error:
13372 isl_basic_map_free(bmap);
13373 return NULL;
13376 /* Given a map (A -> B) -> (C -> D), return the corresponding map
13377 * (A -> C) -> (B -> D).
13379 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
13381 if (!map)
13382 return NULL;
13384 if (!isl_map_can_zip(map))
13385 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
13386 goto error);
13388 return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);
13389 error:
13390 isl_map_free(map);
13391 return NULL;
13394 /* Can we apply isl_basic_map_curry to "bmap"?
13395 * That is, does it have a nested relation in its domain?
13397 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
13399 if (!bmap)
13400 return isl_bool_error;
13402 return isl_space_can_curry(bmap->dim);
13405 /* Can we apply isl_map_curry to "map"?
13406 * That is, does it have a nested relation in its domain?
13408 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
13410 if (!map)
13411 return isl_bool_error;
13413 return isl_space_can_curry(map->dim);
13416 /* Given a basic map (A -> B) -> C, return the corresponding basic map
13417 * A -> (B -> C).
13419 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
13422 if (!bmap)
13423 return NULL;
13425 if (!isl_basic_map_can_curry(bmap))
13426 isl_die(bmap->ctx, isl_error_invalid,
13427 "basic map cannot be curried", goto error);
13428 bmap = isl_basic_map_cow(bmap);
13429 if (!bmap)
13430 return NULL;
13431 bmap->dim = isl_space_curry(bmap->dim);
13432 if (!bmap->dim)
13433 goto error;
13434 bmap = isl_basic_map_mark_final(bmap);
13435 return bmap;
13436 error:
13437 isl_basic_map_free(bmap);
13438 return NULL;
13441 /* Given a map (A -> B) -> C, return the corresponding map
13442 * A -> (B -> C).
13444 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
13446 return isl_map_change_space(map, &isl_map_can_curry,
13447 "map cannot be curried", &isl_space_curry);
13450 /* Can isl_map_range_curry be applied to "map"?
13451 * That is, does it have a nested relation in its range,
13452 * the domain of which is itself a nested relation?
13454 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
13456 if (!map)
13457 return isl_bool_error;
13459 return isl_space_can_range_curry(map->dim);
13462 /* Given a map A -> ((B -> C) -> D), return the corresponding map
13463 * A -> (B -> (C -> D)).
13465 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
13467 return isl_map_change_space(map, &isl_map_can_range_curry,
13468 "map range cannot be curried",
13469 &isl_space_range_curry);
13472 /* Can we apply isl_basic_map_uncurry to "bmap"?
13473 * That is, does it have a nested relation in its domain?
13475 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
13477 if (!bmap)
13478 return isl_bool_error;
13480 return isl_space_can_uncurry(bmap->dim);
13483 /* Can we apply isl_map_uncurry to "map"?
13484 * That is, does it have a nested relation in its domain?
13486 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
13488 if (!map)
13489 return isl_bool_error;
13491 return isl_space_can_uncurry(map->dim);
13494 /* Given a basic map A -> (B -> C), return the corresponding basic map
13495 * (A -> B) -> C.
13497 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
13500 if (!bmap)
13501 return NULL;
13503 if (!isl_basic_map_can_uncurry(bmap))
13504 isl_die(bmap->ctx, isl_error_invalid,
13505 "basic map cannot be uncurried",
13506 return isl_basic_map_free(bmap));
13507 bmap = isl_basic_map_cow(bmap);
13508 if (!bmap)
13509 return NULL;
13510 bmap->dim = isl_space_uncurry(bmap->dim);
13511 if (!bmap->dim)
13512 return isl_basic_map_free(bmap);
13513 bmap = isl_basic_map_mark_final(bmap);
13514 return bmap;
13517 /* Given a map A -> (B -> C), return the corresponding map
13518 * (A -> B) -> C.
13520 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
13522 return isl_map_change_space(map, &isl_map_can_uncurry,
13523 "map cannot be uncurried", &isl_space_uncurry);
13526 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
13527 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13529 return isl_map_equate(set, type1, pos1, type2, pos2);
13532 /* Construct a basic map where the given dimensions are equal to each other.
13534 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
13535 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13537 isl_basic_map *bmap = NULL;
13538 int i;
13539 isl_size total;
13541 total = isl_space_dim(space, isl_dim_all);
13542 if (total < 0 ||
13543 isl_space_check_range(space, type1, pos1, 1) < 0 ||
13544 isl_space_check_range(space, type2, pos2, 1) < 0)
13545 goto error;
13547 if (type1 == type2 && pos1 == pos2)
13548 return isl_basic_map_universe(space);
13550 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
13551 i = isl_basic_map_alloc_equality(bmap);
13552 if (i < 0)
13553 goto error;
13554 isl_seq_clr(bmap->eq[i], 1 + total);
13555 pos1 += isl_basic_map_offset(bmap, type1);
13556 pos2 += isl_basic_map_offset(bmap, type2);
13557 isl_int_set_si(bmap->eq[i][pos1], -1);
13558 isl_int_set_si(bmap->eq[i][pos2], 1);
13559 bmap = isl_basic_map_finalize(bmap);
13560 isl_space_free(space);
13561 return bmap;
13562 error:
13563 isl_space_free(space);
13564 isl_basic_map_free(bmap);
13565 return NULL;
13568 /* Add a constraint imposing that the given two dimensions are equal.
13570 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
13571 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13573 isl_basic_map *eq;
13575 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13577 bmap = isl_basic_map_intersect(bmap, eq);
13579 return bmap;
13582 /* Add a constraint imposing that the given two dimensions are equal.
13584 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
13585 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13587 isl_basic_map *bmap;
13589 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
13591 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13593 return map;
13596 /* Add a constraint imposing that the given two dimensions have opposite values.
13598 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
13599 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13601 isl_basic_map *bmap = NULL;
13602 int i;
13603 isl_size total;
13605 if (isl_map_check_range(map, type1, pos1, 1) < 0)
13606 return isl_map_free(map);
13607 if (isl_map_check_range(map, type2, pos2, 1) < 0)
13608 return isl_map_free(map);
13610 total = isl_map_dim(map, isl_dim_all);
13611 if (total < 0)
13612 return isl_map_free(map);
13613 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
13614 i = isl_basic_map_alloc_equality(bmap);
13615 if (i < 0)
13616 goto error;
13617 isl_seq_clr(bmap->eq[i], 1 + total);
13618 pos1 += isl_basic_map_offset(bmap, type1);
13619 pos2 += isl_basic_map_offset(bmap, type2);
13620 isl_int_set_si(bmap->eq[i][pos1], 1);
13621 isl_int_set_si(bmap->eq[i][pos2], 1);
13622 bmap = isl_basic_map_finalize(bmap);
13624 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13626 return map;
13627 error:
13628 isl_basic_map_free(bmap);
13629 isl_map_free(map);
13630 return NULL;
13633 /* Construct a constraint imposing that the value of the first dimension is
13634 * greater than or equal to that of the second.
13636 static __isl_give isl_constraint *constraint_order_ge(
13637 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
13638 enum isl_dim_type type2, int pos2)
13640 isl_constraint *c;
13642 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13643 isl_space_check_range(space, type2, pos2, 1) < 0)
13644 space = isl_space_free(space);
13645 if (!space)
13646 return NULL;
13648 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
13650 if (type1 == type2 && pos1 == pos2)
13651 return c;
13653 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
13654 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
13656 return c;
13659 /* Add a constraint imposing that the value of the first dimension is
13660 * greater than or equal to that of the second.
13662 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
13663 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13665 isl_constraint *c;
13666 isl_space *space;
13668 if (type1 == type2 && pos1 == pos2)
13669 return bmap;
13670 space = isl_basic_map_get_space(bmap);
13671 c = constraint_order_ge(space, type1, pos1, type2, pos2);
13672 bmap = isl_basic_map_add_constraint(bmap, c);
13674 return bmap;
13677 /* Add a constraint imposing that the value of the first dimension is
13678 * greater than or equal to that of the second.
13680 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
13681 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13683 isl_constraint *c;
13684 isl_space *space;
13686 if (type1 == type2 && pos1 == pos2)
13687 return map;
13688 space = isl_map_get_space(map);
13689 c = constraint_order_ge(space, type1, pos1, type2, pos2);
13690 map = isl_map_add_constraint(map, c);
13692 return map;
13695 /* Add a constraint imposing that the value of the first dimension is
13696 * less than or equal to that of the second.
13698 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
13699 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13701 return isl_map_order_ge(map, type2, pos2, type1, pos1);
13704 /* Construct a basic map where the value of the first dimension is
13705 * greater than that of the second.
13707 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
13708 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13710 isl_basic_map *bmap = NULL;
13711 int i;
13712 isl_size total;
13714 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13715 isl_space_check_range(space, type2, pos2, 1) < 0)
13716 goto error;
13718 if (type1 == type2 && pos1 == pos2)
13719 return isl_basic_map_empty(space);
13721 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
13722 total = isl_basic_map_dim(bmap, isl_dim_all);
13723 i = isl_basic_map_alloc_inequality(bmap);
13724 if (total < 0 || i < 0)
13725 return isl_basic_map_free(bmap);
13726 isl_seq_clr(bmap->ineq[i], 1 + total);
13727 pos1 += isl_basic_map_offset(bmap, type1);
13728 pos2 += isl_basic_map_offset(bmap, type2);
13729 isl_int_set_si(bmap->ineq[i][pos1], 1);
13730 isl_int_set_si(bmap->ineq[i][pos2], -1);
13731 isl_int_set_si(bmap->ineq[i][0], -1);
13732 bmap = isl_basic_map_finalize(bmap);
13734 return bmap;
13735 error:
13736 isl_space_free(space);
13737 isl_basic_map_free(bmap);
13738 return NULL;
13741 /* Add a constraint imposing that the value of the first dimension is
13742 * greater than that of the second.
13744 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
13745 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13747 isl_basic_map *gt;
13749 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13751 bmap = isl_basic_map_intersect(bmap, gt);
13753 return bmap;
13756 /* Add a constraint imposing that the value of the first dimension is
13757 * greater than that of the second.
13759 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
13760 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13762 isl_basic_map *bmap;
13764 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
13766 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13768 return map;
13771 /* Add a constraint imposing that the value of the first dimension is
13772 * smaller than that of the second.
13774 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
13775 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13777 return isl_map_order_gt(map, type2, pos2, type1, pos1);
13780 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
13781 int pos)
13783 isl_aff *div;
13784 isl_local_space *ls;
13786 if (!bmap)
13787 return NULL;
13789 if (!isl_basic_map_divs_known(bmap))
13790 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13791 "some divs are unknown", return NULL);
13793 ls = isl_basic_map_get_local_space(bmap);
13794 div = isl_local_space_get_div(ls, pos);
13795 isl_local_space_free(ls);
13797 return div;
13800 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
13801 int pos)
13803 return isl_basic_map_get_div(bset, pos);
13806 /* Plug in "subs" for set dimension "pos" of "set".
13808 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
13809 unsigned pos, __isl_keep isl_aff *subs)
13811 isl_multi_aff *ma;
13813 if (set && isl_set_plain_is_empty(set))
13814 return set;
13816 ma = isl_multi_aff_identity_on_domain_space(isl_set_get_space(set));
13817 ma = isl_multi_aff_set_aff(ma, pos, isl_aff_copy(subs));
13818 return isl_set_preimage_multi_aff(set, ma);
13821 /* Check if the range of "ma" is compatible with the domain or range
13822 * (depending on "type") of "bmap".
13824 static isl_stat check_basic_map_compatible_range_multi_aff(
13825 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
13826 __isl_keep isl_multi_aff *ma)
13828 isl_bool m;
13829 isl_space *ma_space;
13831 ma_space = isl_multi_aff_get_space(ma);
13833 m = isl_space_has_equal_params(bmap->dim, ma_space);
13834 if (m < 0)
13835 goto error;
13836 if (!m)
13837 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13838 "parameters don't match", goto error);
13839 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
13840 if (m < 0)
13841 goto error;
13842 if (!m)
13843 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13844 "spaces don't match", goto error);
13846 isl_space_free(ma_space);
13847 return isl_stat_ok;
13848 error:
13849 isl_space_free(ma_space);
13850 return isl_stat_error;
13853 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
13854 * coefficients before the transformed range of dimensions,
13855 * the "n_after" coefficients after the transformed range of dimensions
13856 * and the coefficients of the other divs in "bmap".
13858 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
13859 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
13861 int i;
13862 isl_size n_param;
13863 isl_size n_set;
13864 isl_local_space *ls;
13866 if (n_div == 0)
13867 return bmap;
13869 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
13870 n_param = isl_local_space_dim(ls, isl_dim_param);
13871 n_set = isl_local_space_dim(ls, isl_dim_set);
13872 if (n_param < 0 || n_set < 0)
13873 return isl_basic_map_free(bmap);
13875 for (i = 0; i < n_div; ++i) {
13876 int o_bmap = 0, o_ls = 0;
13878 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
13879 o_bmap += 1 + 1 + n_param;
13880 o_ls += 1 + 1 + n_param;
13881 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
13882 o_bmap += n_before;
13883 isl_seq_cpy(bmap->div[i] + o_bmap,
13884 ls->div->row[i] + o_ls, n_set);
13885 o_bmap += n_set;
13886 o_ls += n_set;
13887 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
13888 o_bmap += n_after;
13889 isl_seq_cpy(bmap->div[i] + o_bmap,
13890 ls->div->row[i] + o_ls, n_div);
13891 o_bmap += n_div;
13892 o_ls += n_div;
13893 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
13894 bmap = isl_basic_map_add_div_constraints(bmap, i);
13895 if (!bmap)
13896 goto error;
13899 isl_local_space_free(ls);
13900 return bmap;
13901 error:
13902 isl_local_space_free(ls);
13903 return isl_basic_map_free(bmap);
13906 /* How many stride constraints does "ma" enforce?
13907 * That is, how many of the affine expressions have a denominator
13908 * different from one?
13910 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
13912 int i;
13913 int strides = 0;
13915 for (i = 0; i < ma->n; ++i)
13916 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
13917 strides++;
13919 return strides;
13922 /* For each affine expression in ma of the form
13924 * x_i = (f_i y + h_i)/m_i
13926 * with m_i different from one, add a constraint to "bmap"
13927 * of the form
13929 * f_i y + h_i = m_i alpha_i
13931 * with alpha_i an additional existentially quantified variable.
13933 * The input variables of "ma" correspond to a subset of the variables
13934 * of "bmap". There are "n_before" variables in "bmap" before this
13935 * subset and "n_after" variables after this subset.
13936 * The integer divisions of the affine expressions in "ma" are assumed
13937 * to have been aligned. There are "n_div_ma" of them and
13938 * they appear first in "bmap", straight after the "n_after" variables.
13940 static __isl_give isl_basic_map *add_ma_strides(
13941 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
13942 int n_before, int n_after, int n_div_ma)
13944 int i, k;
13945 int div;
13946 isl_size total;
13947 isl_size n_param;
13948 isl_size n_in;
13950 total = isl_basic_map_dim(bmap, isl_dim_all);
13951 n_param = isl_multi_aff_dim(ma, isl_dim_param);
13952 n_in = isl_multi_aff_dim(ma, isl_dim_in);
13953 if (total < 0 || n_param < 0 || n_in < 0)
13954 return isl_basic_map_free(bmap);
13955 for (i = 0; i < ma->n; ++i) {
13956 int o_bmap = 0, o_ma = 1;
13958 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
13959 continue;
13960 div = isl_basic_map_alloc_div(bmap);
13961 k = isl_basic_map_alloc_equality(bmap);
13962 if (div < 0 || k < 0)
13963 goto error;
13964 isl_int_set_si(bmap->div[div][0], 0);
13965 isl_seq_cpy(bmap->eq[k] + o_bmap,
13966 ma->u.p[i]->v->el + o_ma, 1 + n_param);
13967 o_bmap += 1 + n_param;
13968 o_ma += 1 + n_param;
13969 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
13970 o_bmap += n_before;
13971 isl_seq_cpy(bmap->eq[k] + o_bmap,
13972 ma->u.p[i]->v->el + o_ma, n_in);
13973 o_bmap += n_in;
13974 o_ma += n_in;
13975 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
13976 o_bmap += n_after;
13977 isl_seq_cpy(bmap->eq[k] + o_bmap,
13978 ma->u.p[i]->v->el + o_ma, n_div_ma);
13979 o_bmap += n_div_ma;
13980 o_ma += n_div_ma;
13981 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
13982 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
13983 total++;
13986 return bmap;
13987 error:
13988 isl_basic_map_free(bmap);
13989 return NULL;
13992 /* Replace the domain or range space (depending on "type) of "space" by "set".
13994 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
13995 enum isl_dim_type type, __isl_take isl_space *set)
13997 if (type == isl_dim_in) {
13998 space = isl_space_range(space);
13999 space = isl_space_map_from_domain_and_range(set, space);
14000 } else {
14001 space = isl_space_domain(space);
14002 space = isl_space_map_from_domain_and_range(space, set);
14005 return space;
14008 /* Compute the preimage of the domain or range (depending on "type")
14009 * of "bmap" under the function represented by "ma".
14010 * In other words, plug in "ma" in the domain or range of "bmap".
14011 * The result is a basic map that lives in the same space as "bmap"
14012 * except that the domain or range has been replaced by
14013 * the domain space of "ma".
14015 * If bmap is represented by
14017 * A(p) + S u + B x + T v + C(divs) >= 0,
14019 * where u and x are input and output dimensions if type == isl_dim_out
14020 * while x and v are input and output dimensions if type == isl_dim_in,
14021 * and ma is represented by
14023 * x = D(p) + F(y) + G(divs')
14025 * then the result is
14027 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
14029 * The divs in the input set are similarly adjusted.
14030 * In particular
14032 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
14034 * becomes
14036 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
14037 * B_i G(divs') + c_i(divs))/n_i)
14039 * If bmap is not a rational map and if F(y) involves any denominators
14041 * x_i = (f_i y + h_i)/m_i
14043 * then additional constraints are added to ensure that we only
14044 * map back integer points. That is we enforce
14046 * f_i y + h_i = m_i alpha_i
14048 * with alpha_i an additional existentially quantified variable.
14050 * We first copy over the divs from "ma".
14051 * Then we add the modified constraints and divs from "bmap".
14052 * Finally, we add the stride constraints, if needed.
14054 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
14055 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
14056 __isl_take isl_multi_aff *ma)
14058 int i, k;
14059 isl_space *space;
14060 isl_basic_map *res = NULL;
14061 isl_size n_before, n_after, n_div_bmap, n_div_ma;
14062 isl_int f, c1, c2, g;
14063 isl_bool rational;
14064 int strides;
14066 isl_int_init(f);
14067 isl_int_init(c1);
14068 isl_int_init(c2);
14069 isl_int_init(g);
14071 ma = isl_multi_aff_align_divs(ma);
14072 if (!bmap || !ma)
14073 goto error;
14074 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
14075 goto error;
14077 if (type == isl_dim_in) {
14078 n_before = 0;
14079 n_after = isl_basic_map_dim(bmap, isl_dim_out);
14080 } else {
14081 n_before = isl_basic_map_dim(bmap, isl_dim_in);
14082 n_after = 0;
14084 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
14085 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
14086 if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
14087 goto error;
14089 space = isl_multi_aff_get_domain_space(ma);
14090 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
14091 rational = isl_basic_map_is_rational(bmap);
14092 strides = rational ? 0 : multi_aff_strides(ma);
14093 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
14094 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
14095 if (rational)
14096 res = isl_basic_map_set_rational(res);
14098 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
14099 if (isl_basic_map_alloc_div(res) < 0)
14100 goto error;
14102 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
14103 if (!res)
14104 goto error;
14106 for (i = 0; i < bmap->n_eq; ++i) {
14107 k = isl_basic_map_alloc_equality(res);
14108 if (k < 0)
14109 goto error;
14110 if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
14111 n_after, n_div_ma, n_div_bmap,
14112 f, c1, c2, g, 0) < 0)
14113 goto error;
14116 for (i = 0; i < bmap->n_ineq; ++i) {
14117 k = isl_basic_map_alloc_inequality(res);
14118 if (k < 0)
14119 goto error;
14120 if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
14121 n_after, n_div_ma, n_div_bmap,
14122 f, c1, c2, g, 0) < 0)
14123 goto error;
14126 for (i = 0; i < bmap->n_div; ++i) {
14127 if (isl_int_is_zero(bmap->div[i][0])) {
14128 isl_int_set_si(res->div[n_div_ma + i][0], 0);
14129 continue;
14131 if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
14132 n_before, n_after, n_div_ma, n_div_bmap,
14133 f, c1, c2, g, 1) < 0)
14134 goto error;
14137 if (strides)
14138 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
14140 isl_int_clear(f);
14141 isl_int_clear(c1);
14142 isl_int_clear(c2);
14143 isl_int_clear(g);
14144 isl_basic_map_free(bmap);
14145 isl_multi_aff_free(ma);
14146 res = isl_basic_map_simplify(res);
14147 return isl_basic_map_finalize(res);
14148 error:
14149 isl_int_clear(f);
14150 isl_int_clear(c1);
14151 isl_int_clear(c2);
14152 isl_int_clear(g);
14153 isl_basic_map_free(bmap);
14154 isl_multi_aff_free(ma);
14155 isl_basic_map_free(res);
14156 return NULL;
14159 /* Compute the preimage of "bset" under the function represented by "ma".
14160 * In other words, plug in "ma" in "bset". The result is a basic set
14161 * that lives in the domain space of "ma".
14163 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
14164 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
14166 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
14169 /* Compute the preimage of the domain of "bmap" under the function
14170 * represented by "ma".
14171 * In other words, plug in "ma" in the domain of "bmap".
14172 * The result is a basic map that lives in the same space as "bmap"
14173 * except that the domain has been replaced by the domain space of "ma".
14175 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
14176 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
14178 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
14181 /* Compute the preimage of the range of "bmap" under the function
14182 * represented by "ma".
14183 * In other words, plug in "ma" in the range of "bmap".
14184 * The result is a basic map that lives in the same space as "bmap"
14185 * except that the range has been replaced by the domain space of "ma".
14187 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
14188 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
14190 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
14193 /* Check if the range of "ma" is compatible with the domain or range
14194 * (depending on "type") of "map".
14195 * Return isl_stat_error if anything is wrong.
14197 static isl_stat check_map_compatible_range_multi_aff(
14198 __isl_keep isl_map *map, enum isl_dim_type type,
14199 __isl_keep isl_multi_aff *ma)
14201 isl_bool m;
14202 isl_space *ma_space;
14204 ma_space = isl_multi_aff_get_space(ma);
14205 m = isl_map_space_tuple_is_equal(map, type, ma_space, isl_dim_out);
14206 isl_space_free(ma_space);
14207 if (m < 0)
14208 return isl_stat_error;
14209 if (!m)
14210 isl_die(isl_map_get_ctx(map), isl_error_invalid,
14211 "spaces don't match", return isl_stat_error);
14212 return isl_stat_ok;
14215 /* Compute the preimage of the domain or range (depending on "type")
14216 * of "map" under the function represented by "ma".
14217 * In other words, plug in "ma" in the domain or range of "map".
14218 * The result is a map that lives in the same space as "map"
14219 * except that the domain or range has been replaced by
14220 * the domain space of "ma".
14222 * The parameters are assumed to have been aligned.
14224 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
14225 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
14227 int i;
14228 isl_space *space;
14230 map = isl_map_cow(map);
14231 ma = isl_multi_aff_align_divs(ma);
14232 if (!map || !ma)
14233 goto error;
14234 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
14235 goto error;
14237 for (i = 0; i < map->n; ++i) {
14238 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
14239 isl_multi_aff_copy(ma));
14240 if (!map->p[i])
14241 goto error;
14244 space = isl_multi_aff_get_domain_space(ma);
14245 space = isl_space_set(isl_map_get_space(map), type, space);
14247 isl_space_free(isl_map_take_space(map));
14248 map = isl_map_restore_space(map, space);
14249 if (!map)
14250 goto error;
14252 isl_multi_aff_free(ma);
14253 if (map->n > 1)
14254 ISL_F_CLR(map, ISL_MAP_DISJOINT);
14255 ISL_F_CLR(map, ISL_SET_NORMALIZED);
14256 return map;
14257 error:
14258 isl_multi_aff_free(ma);
14259 isl_map_free(map);
14260 return NULL;
14263 /* Compute the preimage of the domain or range (depending on "type")
14264 * of "map" under the function represented by "ma".
14265 * In other words, plug in "ma" in the domain or range of "map".
14266 * The result is a map that lives in the same space as "map"
14267 * except that the domain or range has been replaced by
14268 * the domain space of "ma".
14270 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
14271 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
14273 isl_bool aligned;
14275 if (!map || !ma)
14276 goto error;
14278 aligned = isl_map_space_has_equal_params(map, ma->space);
14279 if (aligned < 0)
14280 goto error;
14281 if (aligned)
14282 return map_preimage_multi_aff(map, type, ma);
14284 if (isl_map_check_named_params(map) < 0)
14285 goto error;
14286 if (!isl_space_has_named_params(ma->space))
14287 isl_die(map->ctx, isl_error_invalid,
14288 "unaligned unnamed parameters", goto error);
14289 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
14290 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
14292 return map_preimage_multi_aff(map, type, ma);
14293 error:
14294 isl_multi_aff_free(ma);
14295 return isl_map_free(map);
14298 /* Compute the preimage of "set" under the function represented by "ma".
14299 * In other words, plug in "ma" in "set". The result is a set
14300 * that lives in the domain space of "ma".
14302 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
14303 __isl_take isl_multi_aff *ma)
14305 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
14308 /* Compute the preimage of the domain of "map" under the function
14309 * represented by "ma".
14310 * In other words, plug in "ma" in the domain of "map".
14311 * The result is a map that lives in the same space as "map"
14312 * except that the domain has been replaced by the domain space of "ma".
14314 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
14315 __isl_take isl_multi_aff *ma)
14317 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
14320 /* Compute the preimage of the range of "map" under the function
14321 * represented by "ma".
14322 * In other words, plug in "ma" in the range of "map".
14323 * The result is a map that lives in the same space as "map"
14324 * except that the range has been replaced by the domain space of "ma".
14326 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
14327 __isl_take isl_multi_aff *ma)
14329 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
14332 /* Compute the preimage of "map" under the function represented by "pma".
14333 * In other words, plug in "pma" in the domain or range of "map".
14334 * The result is a map that lives in the same space as "map",
14335 * except that the space of type "type" has been replaced by
14336 * the domain space of "pma".
14338 * The parameters of "map" and "pma" are assumed to have been aligned.
14340 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
14341 __isl_take isl_map *map, enum isl_dim_type type,
14342 __isl_take isl_pw_multi_aff *pma)
14344 int i;
14345 isl_map *res;
14347 if (!pma)
14348 goto error;
14350 if (pma->n == 0) {
14351 isl_space *space;
14353 space = isl_pw_multi_aff_get_domain_space(pma);
14354 isl_pw_multi_aff_free(pma);
14355 space = isl_space_set(isl_map_get_space(map), type, space);
14356 isl_map_free(map);
14357 return isl_map_empty(space);
14360 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14361 isl_multi_aff_copy(pma->p[0].maff));
14362 if (type == isl_dim_in)
14363 res = isl_map_intersect_domain(res,
14364 isl_map_copy(pma->p[0].set));
14365 else
14366 res = isl_map_intersect_range(res,
14367 isl_map_copy(pma->p[0].set));
14369 for (i = 1; i < pma->n; ++i) {
14370 isl_map *res_i;
14372 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14373 isl_multi_aff_copy(pma->p[i].maff));
14374 if (type == isl_dim_in)
14375 res_i = isl_map_intersect_domain(res_i,
14376 isl_map_copy(pma->p[i].set));
14377 else
14378 res_i = isl_map_intersect_range(res_i,
14379 isl_map_copy(pma->p[i].set));
14380 res = isl_map_union(res, res_i);
14383 isl_pw_multi_aff_free(pma);
14384 isl_map_free(map);
14385 return res;
14386 error:
14387 isl_pw_multi_aff_free(pma);
14388 isl_map_free(map);
14389 return NULL;
14392 /* Compute the preimage of "map" under the function represented by "pma".
14393 * In other words, plug in "pma" in the domain or range of "map".
14394 * The result is a map that lives in the same space as "map",
14395 * except that the space of type "type" has been replaced by
14396 * the domain space of "pma".
14398 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
14399 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
14401 isl_bool aligned;
14403 if (!map || !pma)
14404 goto error;
14406 aligned = isl_map_space_has_equal_params(map, pma->dim);
14407 if (aligned < 0)
14408 goto error;
14409 if (aligned)
14410 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14412 if (isl_map_check_named_params(map) < 0)
14413 goto error;
14414 if (isl_pw_multi_aff_check_named_params(pma) < 0)
14415 goto error;
14416 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
14417 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
14419 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14420 error:
14421 isl_pw_multi_aff_free(pma);
14422 return isl_map_free(map);
14425 /* Compute the preimage of "set" under the function represented by "pma".
14426 * In other words, plug in "pma" in "set". The result is a set
14427 * that lives in the domain space of "pma".
14429 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
14430 __isl_take isl_pw_multi_aff *pma)
14432 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
14435 /* Compute the preimage of the domain of "map" under the function
14436 * represented by "pma".
14437 * In other words, plug in "pma" in the domain of "map".
14438 * The result is a map that lives in the same space as "map",
14439 * except that domain space has been replaced by the domain space of "pma".
14441 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
14442 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14444 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
14447 /* Compute the preimage of the range of "map" under the function
14448 * represented by "pma".
14449 * In other words, plug in "pma" in the range of "map".
14450 * The result is a map that lives in the same space as "map",
14451 * except that range space has been replaced by the domain space of "pma".
14453 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
14454 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14456 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
14459 /* Compute the preimage of "map" under the function represented by "mpa".
14460 * In other words, plug in "mpa" in the domain or range of "map".
14461 * The result is a map that lives in the same space as "map",
14462 * except that the space of type "type" has been replaced by
14463 * the domain space of "mpa".
14465 * If the map does not involve any constraints that refer to the
14466 * dimensions of the substituted space, then the only possible
14467 * effect of "mpa" on the map is to map the space to a different space.
14468 * We create a separate isl_multi_aff to effectuate this change
14469 * in order to avoid spurious splitting of the map along the pieces
14470 * of "mpa".
14471 * If "mpa" has a non-trivial explicit domain, however,
14472 * then the full substitution should be performed.
14474 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
14475 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
14477 isl_size n;
14478 isl_bool full;
14479 isl_pw_multi_aff *pma;
14481 n = isl_map_dim(map, type);
14482 if (n < 0 || !mpa)
14483 goto error;
14485 full = isl_map_involves_dims(map, type, 0, n);
14486 if (full >= 0 && !full)
14487 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
14488 if (full < 0)
14489 goto error;
14490 if (!full) {
14491 isl_space *space;
14492 isl_multi_aff *ma;
14494 space = isl_multi_pw_aff_get_space(mpa);
14495 isl_multi_pw_aff_free(mpa);
14496 ma = isl_multi_aff_zero(space);
14497 return isl_map_preimage_multi_aff(map, type, ma);
14500 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
14501 return isl_map_preimage_pw_multi_aff(map, type, pma);
14502 error:
14503 isl_map_free(map);
14504 isl_multi_pw_aff_free(mpa);
14505 return NULL;
14508 /* Compute the preimage of "map" under the function represented by "mpa".
14509 * In other words, plug in "mpa" in the domain "map".
14510 * The result is a map that lives in the same space as "map",
14511 * except that domain space has been replaced by the domain space of "mpa".
14513 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
14514 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
14516 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
14519 /* Compute the preimage of "set" by the function represented by "mpa".
14520 * In other words, plug in "mpa" in "set".
14522 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
14523 __isl_take isl_multi_pw_aff *mpa)
14525 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
14528 /* Given that inequality "ineq" of "bmap" expresses an upper bound
14529 * on the output dimension "pos" in terms of the parameters,
14530 * the input dimensions and possibly some integer divisions,
14531 * but not any other output dimensions, extract this upper bound
14532 * as a function of all dimensions (with zero coefficients
14533 * for the output dimensions).
14535 * That is, the inequality is of the form
14537 * e(...) + c - m x >= 0
14539 * where e does not depend on any other output dimensions.
14540 * Return (e(...) + c) / m, with the denominator m in the first position.
14542 __isl_give isl_vec *isl_basic_map_inequality_extract_output_upper_bound(
14543 __isl_keep isl_basic_map *bmap, int ineq, int pos)
14545 isl_ctx *ctx;
14546 isl_size v_out, total;
14548 v_out = isl_basic_map_var_offset(bmap, isl_dim_out);
14549 total = isl_basic_map_dim(bmap, isl_dim_all);
14550 if (v_out < 0 || total < 0)
14551 return NULL;
14552 ctx = isl_basic_map_get_ctx(bmap);
14553 return extract_bound_from_constraint(ctx, bmap->ineq[ineq],
14554 total, v_out + pos);
14557 /* Is constraint "c" of "bmap" of the form
14559 * e(...) + c1 - m x >= 0
14561 * or
14563 * -e(...) + c2 + m x >= 0
14565 * where m > 1 and e does not involve any other output variables?
14567 * "v_out" is the offset to the output variables.
14568 * "d" is the position of x among the output variables.
14569 * "v_div" is the offset to the local variables.
14570 * "total" is the total number of variables.
14572 * Since the purpose of this function is to use the constraint
14573 * to express the output variable as an integer division,
14574 * do not allow the constraint to involve any local variables
14575 * that do not have an explicit representation.
14577 static isl_bool is_potential_div_constraint(__isl_keep isl_basic_map *bmap,
14578 isl_int *c, int v_out, int d, int v_div, int total)
14580 int i = 0;
14582 if (isl_int_is_zero(c[1 + v_out + d]))
14583 return isl_bool_false;
14584 if (isl_int_is_one(c[1 + v_out + d]))
14585 return isl_bool_false;
14586 if (isl_int_is_negone(c[1 + v_out + d]))
14587 return isl_bool_false;
14588 if (isl_seq_first_non_zero(c + 1 + v_out, d) != -1)
14589 return isl_bool_false;
14590 if (isl_seq_first_non_zero(c + 1 + v_out + d + 1,
14591 v_div - (v_out + d + 1)) != -1)
14592 return isl_bool_false;
14593 for (i = 0; v_div + i < total; ++i) {
14594 isl_bool known, involves;
14596 if (isl_int_is_zero(c[1 + v_div + i]))
14597 continue;
14598 known = isl_basic_map_div_is_known(bmap, i);
14599 if (known < 0 || !known)
14600 return known;
14601 involves = div_involves_vars(bmap, i, v_out, v_div - v_out);
14602 if (involves < 0 || involves)
14603 return isl_bool_not(involves);
14605 return isl_bool_true;
14608 /* Look for a pair of constraints
14610 * e(...) + c1 - m x >= 0 i.e., m x <= e(...) + c1
14612 * and
14614 * -e(...) + c2 + m x >= 0 i.e., m x >= e(...) - c2
14616 * that express that the output dimension x at position "pos"
14617 * is some integer division of an expression in terms of the parameters,
14618 * input dimensions and integer divisions.
14619 * If such a pair can be found, then return the index
14620 * of the upper bound constraint, m x <= e(...) + c1.
14621 * Otherwise, return an index beyond the number of constraints.
14623 * The constraints of "bmap" are assumed to have been sorted.
14625 * In order for the constraints above to express an integer division,
14626 * m needs to be greater than 1 and such that
14628 * c1 + c2 < m i.e., -c2 >= c1 - (m - 1)
14630 * In particular, this ensures that
14632 * x = floor((e(...) + c1) / m)
14634 isl_size isl_basic_map_find_output_upper_div_constraint(
14635 __isl_keep isl_basic_map *bmap, int pos)
14637 int i;
14638 isl_size j;
14639 isl_size n_ineq;
14640 isl_size v_out, v_div;
14641 isl_size total;
14642 isl_int sum;
14644 total = isl_basic_map_dim(bmap, isl_dim_all);
14645 v_out = isl_basic_map_var_offset(bmap, isl_dim_out);
14646 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
14647 n_ineq = isl_basic_map_n_inequality(bmap);
14648 if (total < 0 || v_out < 0 || v_div < 0 || n_ineq < 0)
14649 return isl_size_error;
14651 isl_int_init(sum);
14652 for (i = 0; i < n_ineq; ++i) {
14653 isl_bool potential;
14655 potential = is_potential_div_constraint(bmap, bmap->ineq[i],
14656 v_out, pos, v_div, total);
14657 if (potential < 0)
14658 goto error;
14659 if (!potential)
14660 continue;
14662 j = find_later_constraint_in_pair(bmap, i, v_out + pos, total,
14663 bmap->ineq[i][1 + v_out + pos], &sum);
14664 if (j < 0)
14665 goto error;
14666 if (j < n_ineq)
14667 break;
14669 isl_int_clear(sum);
14671 if (i >= n_ineq)
14672 return n_ineq;
14673 if (isl_int_is_pos(bmap->ineq[j][1 + v_out + pos]))
14674 return i;
14675 else
14676 return j;
14677 error:
14678 isl_int_clear(sum);
14679 return isl_size_error;
14682 /* Return a copy of the equality constraints of "bset" as a matrix.
14684 __isl_give isl_mat *isl_basic_set_extract_equalities(
14685 __isl_keep isl_basic_set *bset)
14687 isl_ctx *ctx;
14688 isl_size total;
14690 total = isl_basic_set_dim(bset, isl_dim_all);
14691 if (total < 0)
14692 return NULL;
14694 ctx = isl_basic_set_get_ctx(bset);
14695 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
14698 /* Are the "n" "coefficients" starting at "first" of the integer division
14699 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
14700 * to each other?
14701 * The "coefficient" at position 0 is the denominator.
14702 * The "coefficient" at position 1 is the constant term.
14704 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
14705 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
14706 unsigned first, unsigned n)
14708 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
14709 return isl_bool_error;
14710 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
14711 return isl_bool_error;
14712 return isl_seq_eq(bmap1->div[pos1] + first,
14713 bmap2->div[pos2] + first, n);
14716 /* Are the integer division expressions at position "pos1" in "bmap1" and
14717 * "pos2" in "bmap2" equal to each other, except that the constant terms
14718 * are different?
14720 isl_bool isl_basic_map_equal_div_expr_except_constant(
14721 __isl_keep isl_basic_map *bmap1, int pos1,
14722 __isl_keep isl_basic_map *bmap2, int pos2)
14724 isl_bool equal;
14725 isl_size total, total2;
14727 total = isl_basic_map_dim(bmap1, isl_dim_all);
14728 total2 = isl_basic_map_dim(bmap2, isl_dim_all);
14729 if (total < 0 || total2 < 0)
14730 return isl_bool_error;
14731 if (total != total2)
14732 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
14733 "incomparable div expressions", return isl_bool_error);
14734 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14735 0, 1);
14736 if (equal < 0 || !equal)
14737 return equal;
14738 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14739 1, 1);
14740 if (equal < 0 || equal)
14741 return isl_bool_not(equal);
14742 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14743 2, total);
14746 /* Replace the numerator of the constant term of the integer division
14747 * expression at position "div" in "bmap" by "value".
14748 * The caller guarantees that this does not change the meaning
14749 * of the input.
14751 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
14752 __isl_take isl_basic_map *bmap, int div, int value)
14754 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
14755 return isl_basic_map_free(bmap);
14757 isl_int_set_si(bmap->div[div][1], value);
14759 return bmap;
14762 /* Is the point "inner" internal to inequality constraint "ineq"
14763 * of "bset"?
14764 * The point is considered to be internal to the inequality constraint,
14765 * if it strictly lies on the positive side of the inequality constraint,
14766 * or if it lies on the constraint and the constraint is lexico-positive.
14768 static isl_bool is_internal(__isl_keep isl_vec *inner,
14769 __isl_keep isl_basic_set *bset, int ineq)
14771 isl_ctx *ctx;
14772 int pos;
14773 isl_size total;
14775 if (!inner || !bset)
14776 return isl_bool_error;
14778 ctx = isl_basic_set_get_ctx(bset);
14779 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
14780 &ctx->normalize_gcd);
14781 if (!isl_int_is_zero(ctx->normalize_gcd))
14782 return isl_int_is_nonneg(ctx->normalize_gcd);
14784 total = isl_basic_set_dim(bset, isl_dim_all);
14785 if (total < 0)
14786 return isl_bool_error;
14787 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
14788 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
14791 /* Tighten the inequality constraints of "bset" that are outward with respect
14792 * to the point "vec".
14793 * That is, tighten the constraints that are not satisfied by "vec".
14795 * "vec" is a point internal to some superset S of "bset" that is used
14796 * to make the subsets of S disjoint, by tightening one half of the constraints
14797 * that separate two subsets. In particular, the constraints of S
14798 * are all satisfied by "vec" and should not be tightened.
14799 * Of the internal constraints, those that have "vec" on the outside
14800 * are tightened. The shared facet is included in the adjacent subset
14801 * with the opposite constraint.
14802 * For constraints that saturate "vec", this criterion cannot be used
14803 * to determine which of the two sides should be tightened.
14804 * Instead, the sign of the first non-zero coefficient is used
14805 * to make this choice. Note that this second criterion is never used
14806 * on the constraints of S since "vec" is interior to "S".
14808 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
14809 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
14811 int j;
14813 bset = isl_basic_set_cow(bset);
14814 if (!bset)
14815 return NULL;
14816 for (j = 0; j < bset->n_ineq; ++j) {
14817 isl_bool internal;
14819 internal = is_internal(vec, bset, j);
14820 if (internal < 0)
14821 return isl_basic_set_free(bset);
14822 if (internal)
14823 continue;
14824 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
14827 return bset;
14830 /* Replace the variables x of type "type" starting at "first" in "bmap"
14831 * by x' with x = M x' with M the matrix trans.
14832 * That is, replace the corresponding coefficients c by c M.
14834 * The transformation matrix should be a square matrix.
14836 __isl_give isl_basic_map *isl_basic_map_transform_dims(
14837 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
14838 __isl_take isl_mat *trans)
14840 unsigned pos;
14842 bmap = isl_basic_map_cow(bmap);
14843 if (!bmap || !trans)
14844 goto error;
14846 if (trans->n_row != trans->n_col)
14847 isl_die(trans->ctx, isl_error_invalid,
14848 "expecting square transformation matrix", goto error);
14849 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
14850 goto error;
14852 pos = isl_basic_map_offset(bmap, type) + first;
14854 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
14855 isl_mat_copy(trans)) < 0)
14856 goto error;
14857 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
14858 isl_mat_copy(trans)) < 0)
14859 goto error;
14860 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
14861 isl_mat_copy(trans)) < 0)
14862 goto error;
14864 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
14865 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
14866 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
14868 isl_mat_free(trans);
14869 return bmap;
14870 error:
14871 isl_mat_free(trans);
14872 isl_basic_map_free(bmap);
14873 return NULL;
14876 /* Replace the variables x of type "type" starting at "first" in "bset"
14877 * by x' with x = M x' with M the matrix trans.
14878 * That is, replace the corresponding coefficients c by c M.
14880 * The transformation matrix should be a square matrix.
14882 __isl_give isl_basic_set *isl_basic_set_transform_dims(
14883 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
14884 __isl_take isl_mat *trans)
14886 return isl_basic_map_transform_dims(bset, type, first, trans);