isl_val_ne: use isl_bool_ok
[isl.git] / isl_map.c
blobdf387247e62fd9b75637699be642ebbcadc1225a
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2014 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
6 * Copyright 2016 INRIA Paris
7 * Copyright 2016 Sven Verdoolaege
9 * Use of this software is governed by the MIT license
11 * Written by Sven Verdoolaege, K.U.Leuven, Departement
12 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
13 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
14 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
15 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
16 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
17 * B.P. 105 - 78153 Le Chesnay, France
18 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
19 * CS 42112, 75589 Paris Cedex 12, France
22 #include <string.h>
23 #include <isl_ctx_private.h>
24 #include <isl_map_private.h>
25 #include <isl_blk.h>
26 #include <isl/id.h>
27 #include <isl/constraint.h>
28 #include "isl_space_private.h"
29 #include "isl_equalities.h"
30 #include <isl_lp_private.h>
31 #include <isl_seq.h>
32 #include <isl/set.h>
33 #include <isl/map.h>
34 #include <isl_reordering.h>
35 #include "isl_sample.h"
36 #include <isl_sort.h>
37 #include "isl_tab.h"
38 #include <isl/vec.h>
39 #include <isl_mat_private.h>
40 #include <isl_vec_private.h>
41 #include <isl_dim_map.h>
42 #include <isl_local_space_private.h>
43 #include <isl_aff_private.h>
44 #include <isl_options_private.h>
45 #include <isl_morph.h>
46 #include <isl_val_private.h>
47 #include <isl_printer_private.h>
49 #include <bset_to_bmap.c>
50 #include <bset_from_bmap.c>
51 #include <set_to_map.c>
52 #include <set_from_map.c>
54 /* Treat "bset" as a basic map.
55 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
56 * this function performs a redundant cast.
58 static __isl_keep const isl_basic_map *const_bset_to_bmap(
59 __isl_keep const isl_basic_set *bset)
61 return (const isl_basic_map *) bset;
64 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
66 switch (type) {
67 case isl_dim_param: return 1;
68 case isl_dim_in: return 1 + dim->nparam;
69 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
70 default: return 0;
74 unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
75 enum isl_dim_type type)
77 if (!bmap)
78 return 0;
79 switch (type) {
80 case isl_dim_cst: return 1;
81 case isl_dim_param:
82 case isl_dim_in:
83 case isl_dim_out: return isl_space_dim(bmap->dim, type);
84 case isl_dim_div: return bmap->n_div;
85 case isl_dim_all: return isl_basic_map_total_dim(bmap);
86 default: return 0;
90 /* Return the space of "map".
92 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
94 return map ? map->dim : NULL;
97 /* Return the space of "set".
99 __isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
101 return isl_map_peek_space(set_to_map(set));
104 unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
106 return isl_space_dim(isl_map_peek_space(map), type);
109 unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
111 return isl_map_dim(set_to_map(set), type);
114 /* Return the position of the variables of the given type
115 * within the sequence of variables of "bmap".
117 int isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
118 enum isl_dim_type type)
120 isl_space *space;
122 space = isl_basic_map_peek_space(bmap);
123 if (!space)
124 return -1;
126 switch (type) {
127 case isl_dim_param:
128 case isl_dim_in:
129 case isl_dim_out: return isl_space_offset(space, type);
130 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
131 case isl_dim_cst:
132 default:
133 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
134 "invalid dimension type", return -1);
138 /* Return the position of the variables of the given type
139 * within the sequence of variables of "bset".
141 int isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
142 enum isl_dim_type type)
144 return isl_basic_map_var_offset(bset_to_bmap(bset), type);
147 /* Return the position of the coefficients of the variables of the given type
148 * within the sequence of coefficients of "bmap".
150 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
151 enum isl_dim_type type)
153 switch (type) {
154 case isl_dim_cst: return 0;
155 case isl_dim_param:
156 case isl_dim_in:
157 case isl_dim_out:
158 case isl_dim_div: return 1 + isl_basic_map_var_offset(bmap, type);
159 default: return 0;
163 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
164 enum isl_dim_type type)
166 return isl_basic_map_offset(bset, type);
169 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
171 return pos(map->dim, type);
174 unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
175 enum isl_dim_type type)
177 return isl_basic_map_dim(bset, type);
180 unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
182 return isl_basic_set_dim(bset, isl_dim_set);
185 unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
187 return isl_basic_set_dim(bset, isl_dim_param);
190 unsigned isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
192 return isl_basic_map_total_dim(const_bset_to_bmap(bset));
195 unsigned isl_set_n_dim(__isl_keep isl_set *set)
197 return isl_set_dim(set, isl_dim_set);
200 unsigned isl_set_n_param(__isl_keep isl_set *set)
202 return isl_set_dim(set, isl_dim_param);
205 unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap)
207 return bmap ? bmap->dim->n_in : 0;
210 unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap)
212 return bmap ? bmap->dim->n_out : 0;
215 unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap)
217 return bmap ? bmap->dim->nparam : 0;
220 unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap)
222 return bmap ? bmap->n_div : 0;
225 unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
227 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
230 unsigned isl_map_n_in(__isl_keep const isl_map *map)
232 return map ? map->dim->n_in : 0;
235 unsigned isl_map_n_out(__isl_keep const isl_map *map)
237 return map ? map->dim->n_out : 0;
240 unsigned isl_map_n_param(__isl_keep const isl_map *map)
242 return map ? map->dim->nparam : 0;
245 /* Return the number of equality constraints in the description of "bmap".
246 * Return -1 on error.
248 int isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
250 if (!bmap)
251 return -1;
252 return bmap->n_eq;
255 /* Return the number of equality constraints in the description of "bset".
256 * Return -1 on error.
258 int isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
260 return isl_basic_map_n_equality(bset_to_bmap(bset));
263 /* Return the number of inequality constraints in the description of "bmap".
264 * Return -1 on error.
266 int isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
268 if (!bmap)
269 return -1;
270 return bmap->n_ineq;
273 /* Return the number of inequality constraints in the description of "bset".
274 * Return -1 on error.
276 int isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
278 return isl_basic_map_n_inequality(bset_to_bmap(bset));
281 /* Do "bmap1" and "bmap2" have the same parameters?
283 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
284 __isl_keep isl_basic_map *bmap2)
286 isl_space *space1, *space2;
288 space1 = isl_basic_map_peek_space(bmap1);
289 space2 = isl_basic_map_peek_space(bmap2);
290 return isl_space_has_equal_params(space1, space2);
293 /* Do "map1" and "map2" have the same parameters?
295 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
296 __isl_keep isl_map *map2)
298 isl_space *space1, *space2;
300 space1 = isl_map_peek_space(map1);
301 space2 = isl_map_peek_space(map2);
302 return isl_space_has_equal_params(space1, space2);
305 /* Do "map" and "set" have the same parameters?
307 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
308 __isl_keep isl_set *set)
310 return isl_map_has_equal_params(map, set_to_map(set));
313 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
314 __isl_keep isl_set *set)
316 isl_bool m;
317 if (!map || !set)
318 return isl_bool_error;
319 m = isl_map_has_equal_params(map, set_to_map(set));
320 if (m < 0 || !m)
321 return m;
322 return isl_space_tuple_is_equal(map->dim, isl_dim_in,
323 set->dim, isl_dim_set);
326 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
327 __isl_keep isl_basic_set *bset)
329 isl_bool m;
330 if (!bmap || !bset)
331 return isl_bool_error;
332 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
333 if (m < 0 || !m)
334 return m;
335 return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
336 bset->dim, isl_dim_set);
339 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
340 __isl_keep isl_set *set)
342 isl_bool m;
343 if (!map || !set)
344 return isl_bool_error;
345 m = isl_map_has_equal_params(map, set_to_map(set));
346 if (m < 0 || !m)
347 return m;
348 return isl_space_tuple_is_equal(map->dim, isl_dim_out,
349 set->dim, isl_dim_set);
352 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
353 __isl_keep isl_basic_set *bset)
355 isl_bool m;
356 if (!bmap || !bset)
357 return isl_bool_error;
358 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
359 if (m < 0 || !m)
360 return m;
361 return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
362 bset->dim, isl_dim_set);
365 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
367 return bmap ? bmap->ctx : NULL;
370 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
372 return bset ? bset->ctx : NULL;
375 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
377 return map ? map->ctx : NULL;
380 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
382 return set ? set->ctx : NULL;
385 /* Return the space of "bmap".
387 __isl_keep isl_space *isl_basic_map_peek_space(
388 __isl_keep const isl_basic_map *bmap)
390 return bmap ? bmap->dim : NULL;
393 /* Return the space of "bset".
395 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
397 return isl_basic_map_peek_space(bset_to_bmap(bset));
400 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
402 return isl_space_copy(isl_basic_map_peek_space(bmap));
405 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
407 return isl_basic_map_get_space(bset_to_bmap(bset));
410 /* Extract the divs in "bmap" as a matrix.
412 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
414 int i;
415 isl_ctx *ctx;
416 isl_mat *div;
417 int v_div;
418 unsigned cols;
420 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
421 if (v_div < 0)
422 return NULL;
424 ctx = isl_basic_map_get_ctx(bmap);
425 cols = 1 + 1 + v_div + bmap->n_div;
426 div = isl_mat_alloc(ctx, bmap->n_div, cols);
427 if (!div)
428 return NULL;
430 for (i = 0; i < bmap->n_div; ++i)
431 isl_seq_cpy(div->row[i], bmap->div[i], cols);
433 return div;
436 /* Extract the divs in "bset" as a matrix.
438 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
440 return isl_basic_map_get_divs(bset);
443 __isl_give isl_local_space *isl_basic_map_get_local_space(
444 __isl_keep isl_basic_map *bmap)
446 isl_mat *div;
448 if (!bmap)
449 return NULL;
451 div = isl_basic_map_get_divs(bmap);
452 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
455 __isl_give isl_local_space *isl_basic_set_get_local_space(
456 __isl_keep isl_basic_set *bset)
458 return isl_basic_map_get_local_space(bset);
461 /* For each known div d = floor(f/m), add the constraints
463 * f - m d >= 0
464 * -(f-(m-1)) + m d >= 0
466 * Do not finalize the result.
468 static __isl_give isl_basic_map *add_known_div_constraints(
469 __isl_take isl_basic_map *bmap)
471 int i;
472 unsigned n_div;
474 if (!bmap)
475 return NULL;
476 n_div = isl_basic_map_dim(bmap, isl_dim_div);
477 if (n_div == 0)
478 return bmap;
479 bmap = isl_basic_map_cow(bmap);
480 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
481 if (!bmap)
482 return NULL;
483 for (i = 0; i < n_div; ++i) {
484 if (isl_int_is_zero(bmap->div[i][0]))
485 continue;
486 bmap = isl_basic_map_add_div_constraints(bmap, i);
489 return bmap;
492 __isl_give isl_basic_map *isl_basic_map_from_local_space(
493 __isl_take isl_local_space *ls)
495 int i;
496 int n_div;
497 isl_basic_map *bmap;
499 if (!ls)
500 return NULL;
502 n_div = isl_local_space_dim(ls, isl_dim_div);
503 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
504 n_div, 0, 2 * n_div);
506 for (i = 0; i < n_div; ++i)
507 if (isl_basic_map_alloc_div(bmap) < 0)
508 goto error;
510 for (i = 0; i < n_div; ++i)
511 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
512 bmap = add_known_div_constraints(bmap);
514 isl_local_space_free(ls);
515 return bmap;
516 error:
517 isl_local_space_free(ls);
518 isl_basic_map_free(bmap);
519 return NULL;
522 __isl_give isl_basic_set *isl_basic_set_from_local_space(
523 __isl_take isl_local_space *ls)
525 return isl_basic_map_from_local_space(ls);
528 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
530 return isl_space_copy(isl_map_peek_space(map));
533 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
535 if (!set)
536 return NULL;
537 return isl_space_copy(set->dim);
540 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
541 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
543 bmap = isl_basic_map_cow(bmap);
544 if (!bmap)
545 return NULL;
546 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
547 if (!bmap->dim)
548 goto error;
549 bmap = isl_basic_map_finalize(bmap);
550 return bmap;
551 error:
552 isl_basic_map_free(bmap);
553 return NULL;
556 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
557 __isl_take isl_basic_set *bset, const char *s)
559 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
562 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
563 enum isl_dim_type type)
565 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
568 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
569 enum isl_dim_type type, const char *s)
571 int i;
573 map = isl_map_cow(map);
574 if (!map)
575 return NULL;
577 map->dim = isl_space_set_tuple_name(map->dim, type, s);
578 if (!map->dim)
579 goto error;
581 for (i = 0; i < map->n; ++i) {
582 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
583 if (!map->p[i])
584 goto error;
587 return map;
588 error:
589 isl_map_free(map);
590 return NULL;
593 /* Replace the identifier of the tuple of type "type" by "id".
595 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
596 __isl_take isl_basic_map *bmap,
597 enum isl_dim_type type, __isl_take isl_id *id)
599 bmap = isl_basic_map_cow(bmap);
600 if (!bmap)
601 goto error;
602 bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
603 if (!bmap->dim)
604 return isl_basic_map_free(bmap);
605 bmap = isl_basic_map_finalize(bmap);
606 return bmap;
607 error:
608 isl_id_free(id);
609 return NULL;
612 /* Replace the identifier of the tuple by "id".
614 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
615 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
617 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
620 /* Does the input or output tuple have a name?
622 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
624 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
627 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
628 enum isl_dim_type type)
630 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
633 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
634 const char *s)
636 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
637 isl_dim_set, s));
640 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
641 enum isl_dim_type type, __isl_take isl_id *id)
643 map = isl_map_cow(map);
644 if (!map)
645 goto error;
647 map->dim = isl_space_set_tuple_id(map->dim, type, id);
649 return isl_map_reset_space(map, isl_space_copy(map->dim));
650 error:
651 isl_id_free(id);
652 return NULL;
655 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
656 __isl_take isl_id *id)
658 return isl_map_set_tuple_id(set, isl_dim_set, id);
661 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
662 enum isl_dim_type type)
664 map = isl_map_cow(map);
665 if (!map)
666 return NULL;
668 map->dim = isl_space_reset_tuple_id(map->dim, type);
670 return isl_map_reset_space(map, isl_space_copy(map->dim));
673 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
675 return isl_map_reset_tuple_id(set, isl_dim_set);
678 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
680 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
683 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
684 enum isl_dim_type type)
686 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
689 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
691 return isl_map_has_tuple_id(set, isl_dim_set);
694 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
696 return isl_map_get_tuple_id(set, isl_dim_set);
699 /* Does the set tuple have a name?
701 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
703 if (!set)
704 return isl_bool_error;
705 return isl_space_has_tuple_name(set->dim, isl_dim_set);
709 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
711 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
714 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
716 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
719 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
720 enum isl_dim_type type, unsigned pos)
722 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
725 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
726 enum isl_dim_type type, unsigned pos)
728 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
731 /* Does the given dimension have a name?
733 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
734 enum isl_dim_type type, unsigned pos)
736 if (!map)
737 return isl_bool_error;
738 return isl_space_has_dim_name(map->dim, type, pos);
741 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
742 enum isl_dim_type type, unsigned pos)
744 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
747 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
748 enum isl_dim_type type, unsigned pos)
750 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
753 /* Does the given dimension have a name?
755 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
756 enum isl_dim_type type, unsigned pos)
758 if (!set)
759 return isl_bool_error;
760 return isl_space_has_dim_name(set->dim, type, pos);
763 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
764 __isl_take isl_basic_map *bmap,
765 enum isl_dim_type type, unsigned pos, const char *s)
767 bmap = isl_basic_map_cow(bmap);
768 if (!bmap)
769 return NULL;
770 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
771 if (!bmap->dim)
772 goto error;
773 return isl_basic_map_finalize(bmap);
774 error:
775 isl_basic_map_free(bmap);
776 return NULL;
779 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
780 enum isl_dim_type type, unsigned pos, const char *s)
782 int i;
784 map = isl_map_cow(map);
785 if (!map)
786 return NULL;
788 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
789 if (!map->dim)
790 goto error;
792 for (i = 0; i < map->n; ++i) {
793 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
794 if (!map->p[i])
795 goto error;
798 return map;
799 error:
800 isl_map_free(map);
801 return NULL;
804 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
805 __isl_take isl_basic_set *bset,
806 enum isl_dim_type type, unsigned pos, const char *s)
808 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
809 type, pos, s));
812 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
813 enum isl_dim_type type, unsigned pos, const char *s)
815 return set_from_map(isl_map_set_dim_name(set_to_map(set),
816 type, pos, s));
819 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
820 enum isl_dim_type type, unsigned pos)
822 if (!bmap)
823 return isl_bool_error;
824 return isl_space_has_dim_id(bmap->dim, type, pos);
827 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
828 enum isl_dim_type type, unsigned pos)
830 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
833 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
834 enum isl_dim_type type, unsigned pos)
836 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
839 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
840 enum isl_dim_type type, unsigned pos)
842 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
845 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
846 enum isl_dim_type type, unsigned pos)
848 return isl_map_has_dim_id(set, type, pos);
851 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
852 enum isl_dim_type type, unsigned pos)
854 return isl_map_get_dim_id(set, type, pos);
857 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
858 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
860 map = isl_map_cow(map);
861 if (!map)
862 goto error;
864 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
866 return isl_map_reset_space(map, isl_space_copy(map->dim));
867 error:
868 isl_id_free(id);
869 return NULL;
872 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
873 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
875 return isl_map_set_dim_id(set, type, pos, id);
878 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
879 __isl_keep isl_id *id)
881 if (!map)
882 return -1;
883 return isl_space_find_dim_by_id(map->dim, type, id);
886 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
887 __isl_keep isl_id *id)
889 return isl_map_find_dim_by_id(set, type, id);
892 /* Return the position of the dimension of the given type and name
893 * in "bmap".
894 * Return -1 if no such dimension can be found.
896 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
897 enum isl_dim_type type, const char *name)
899 if (!bmap)
900 return -1;
901 return isl_space_find_dim_by_name(bmap->dim, type, name);
904 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
905 const char *name)
907 if (!map)
908 return -1;
909 return isl_space_find_dim_by_name(map->dim, type, name);
912 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
913 const char *name)
915 return isl_map_find_dim_by_name(set, type, name);
918 /* Check whether equality i of bset is a pure stride constraint
919 * on a single dimension, i.e., of the form
921 * v = k e
923 * with k a constant and e an existentially quantified variable.
925 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
927 unsigned nparam;
928 unsigned d;
929 unsigned n_div;
930 int pos1;
931 int pos2;
933 if (!bset)
934 return isl_bool_error;
936 if (!isl_int_is_zero(bset->eq[i][0]))
937 return isl_bool_false;
939 nparam = isl_basic_set_dim(bset, isl_dim_param);
940 d = isl_basic_set_dim(bset, isl_dim_set);
941 n_div = isl_basic_set_dim(bset, isl_dim_div);
943 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
944 return isl_bool_false;
945 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
946 if (pos1 == -1)
947 return isl_bool_false;
948 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
949 d - pos1 - 1) != -1)
950 return isl_bool_false;
952 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
953 if (pos2 == -1)
954 return isl_bool_false;
955 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
956 n_div - pos2 - 1) != -1)
957 return isl_bool_false;
958 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
959 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
960 return isl_bool_false;
962 return isl_bool_true;
965 /* Reset the user pointer on all identifiers of parameters and tuples
966 * of the space of "map".
968 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
970 isl_space *space;
972 space = isl_map_get_space(map);
973 space = isl_space_reset_user(space);
974 map = isl_map_reset_space(map, space);
976 return map;
979 /* Reset the user pointer on all identifiers of parameters and tuples
980 * of the space of "set".
982 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
984 return isl_map_reset_user(set);
987 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
989 if (!bmap)
990 return isl_bool_error;
991 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
994 /* Has "map" been marked as a rational map?
995 * In particular, have all basic maps in "map" been marked this way?
996 * An empty map is not considered to be rational.
997 * Maps where only some of the basic maps are marked rational
998 * are not allowed.
1000 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
1002 int i;
1003 isl_bool rational;
1005 if (!map)
1006 return isl_bool_error;
1007 if (map->n == 0)
1008 return isl_bool_false;
1009 rational = isl_basic_map_is_rational(map->p[0]);
1010 if (rational < 0)
1011 return rational;
1012 for (i = 1; i < map->n; ++i) {
1013 isl_bool rational_i;
1015 rational_i = isl_basic_map_is_rational(map->p[i]);
1016 if (rational_i < 0)
1017 return rational_i;
1018 if (rational != rational_i)
1019 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1020 "mixed rational and integer basic maps "
1021 "not supported", return isl_bool_error);
1024 return rational;
1027 /* Has "set" been marked as a rational set?
1028 * In particular, have all basic set in "set" been marked this way?
1029 * An empty set is not considered to be rational.
1030 * Sets where only some of the basic sets are marked rational
1031 * are not allowed.
1033 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1035 return isl_map_is_rational(set);
1038 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1040 return isl_basic_map_is_rational(bset);
1043 /* Does "bmap" contain any rational points?
1045 * If "bmap" has an equality for each dimension, equating the dimension
1046 * to an integer constant, then it has no rational points, even if it
1047 * is marked as rational.
1049 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1051 isl_bool has_rational = isl_bool_true;
1052 unsigned total;
1054 if (!bmap)
1055 return isl_bool_error;
1056 if (isl_basic_map_plain_is_empty(bmap))
1057 return isl_bool_false;
1058 if (!isl_basic_map_is_rational(bmap))
1059 return isl_bool_false;
1060 bmap = isl_basic_map_copy(bmap);
1061 bmap = isl_basic_map_implicit_equalities(bmap);
1062 if (!bmap)
1063 return isl_bool_error;
1064 total = isl_basic_map_total_dim(bmap);
1065 if (bmap->n_eq == total) {
1066 int i, j;
1067 for (i = 0; i < bmap->n_eq; ++i) {
1068 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1069 if (j < 0)
1070 break;
1071 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1072 !isl_int_is_negone(bmap->eq[i][1 + j]))
1073 break;
1074 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1075 total - j - 1);
1076 if (j >= 0)
1077 break;
1079 if (i == bmap->n_eq)
1080 has_rational = isl_bool_false;
1082 isl_basic_map_free(bmap);
1084 return has_rational;
1087 /* Does "map" contain any rational points?
1089 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1091 int i;
1092 isl_bool has_rational;
1094 if (!map)
1095 return isl_bool_error;
1096 for (i = 0; i < map->n; ++i) {
1097 has_rational = isl_basic_map_has_rational(map->p[i]);
1098 if (has_rational < 0 || has_rational)
1099 return has_rational;
1101 return isl_bool_false;
1104 /* Does "set" contain any rational points?
1106 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1108 return isl_map_has_rational(set);
1111 /* Is this basic set a parameter domain?
1113 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1115 if (!bset)
1116 return isl_bool_error;
1117 return isl_space_is_params(bset->dim);
1120 /* Is this set a parameter domain?
1122 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1124 if (!set)
1125 return isl_bool_error;
1126 return isl_space_is_params(set->dim);
1129 /* Is this map actually a parameter domain?
1130 * Users should never call this function. Outside of isl,
1131 * a map can never be a parameter domain.
1133 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1135 if (!map)
1136 return isl_bool_error;
1137 return isl_space_is_params(map->dim);
1140 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1141 __isl_take isl_basic_map *bmap, unsigned extra,
1142 unsigned n_eq, unsigned n_ineq)
1144 int i;
1145 isl_space *space = isl_basic_map_peek_space(bmap);
1146 unsigned n_var = isl_space_dim(space, isl_dim_all);
1147 size_t row_size = 1 + n_var + extra;
1149 bmap->ctx = ctx;
1150 isl_ctx_ref(ctx);
1152 if (!space)
1153 return isl_basic_map_free(bmap);
1155 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1156 if (isl_blk_is_error(bmap->block))
1157 goto error;
1159 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1160 if ((n_ineq + n_eq) && !bmap->ineq)
1161 goto error;
1163 if (extra == 0) {
1164 bmap->block2 = isl_blk_empty();
1165 bmap->div = NULL;
1166 } else {
1167 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1168 if (isl_blk_is_error(bmap->block2))
1169 goto error;
1171 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1172 if (!bmap->div)
1173 goto error;
1176 for (i = 0; i < n_ineq + n_eq; ++i)
1177 bmap->ineq[i] = bmap->block.data + i * row_size;
1179 for (i = 0; i < extra; ++i)
1180 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1182 bmap->ref = 1;
1183 bmap->flags = 0;
1184 bmap->c_size = n_eq + n_ineq;
1185 bmap->eq = bmap->ineq + n_ineq;
1186 bmap->extra = extra;
1187 bmap->n_eq = 0;
1188 bmap->n_ineq = 0;
1189 bmap->n_div = 0;
1190 bmap->sample = NULL;
1192 return bmap;
1193 error:
1194 isl_basic_map_free(bmap);
1195 return NULL;
1198 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1199 unsigned nparam, unsigned dim, unsigned extra,
1200 unsigned n_eq, unsigned n_ineq)
1202 struct isl_basic_map *bmap;
1203 isl_space *space;
1205 space = isl_space_set_alloc(ctx, nparam, dim);
1206 if (!space)
1207 return NULL;
1209 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1210 return bset_from_bmap(bmap);
1213 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1214 unsigned extra, unsigned n_eq, unsigned n_ineq)
1216 struct isl_basic_map *bmap;
1217 if (!dim)
1218 return NULL;
1219 isl_assert(dim->ctx, dim->n_in == 0, goto error);
1220 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1221 return bset_from_bmap(bmap);
1222 error:
1223 isl_space_free(dim);
1224 return NULL;
1227 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1228 unsigned extra, unsigned n_eq, unsigned n_ineq)
1230 struct isl_basic_map *bmap;
1232 if (!space)
1233 return NULL;
1234 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1235 if (!bmap)
1236 goto error;
1237 bmap->dim = space;
1239 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1240 error:
1241 isl_space_free(space);
1242 return NULL;
1245 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1246 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1247 unsigned n_eq, unsigned n_ineq)
1249 struct isl_basic_map *bmap;
1250 isl_space *dim;
1252 dim = isl_space_alloc(ctx, nparam, in, out);
1253 if (!dim)
1254 return NULL;
1256 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1257 return bmap;
1260 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1261 __isl_keep isl_basic_map *src)
1263 int i;
1264 unsigned total = isl_basic_map_total_dim(src);
1266 if (!dst)
1267 return NULL;
1269 for (i = 0; i < src->n_eq; ++i) {
1270 int j = isl_basic_map_alloc_equality(dst);
1271 if (j < 0)
1272 return isl_basic_map_free(dst);
1273 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1276 for (i = 0; i < src->n_ineq; ++i) {
1277 int j = isl_basic_map_alloc_inequality(dst);
1278 if (j < 0)
1279 return isl_basic_map_free(dst);
1280 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1283 for (i = 0; i < src->n_div; ++i) {
1284 int j = isl_basic_map_alloc_div(dst);
1285 if (j < 0)
1286 return isl_basic_map_free(dst);
1287 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1289 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1290 return dst;
1293 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1295 struct isl_basic_map *dup;
1297 if (!bmap)
1298 return NULL;
1299 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1300 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1301 dup = dup_constraints(dup, bmap);
1302 if (!dup)
1303 return NULL;
1304 dup->flags = bmap->flags;
1305 dup->sample = isl_vec_copy(bmap->sample);
1306 return dup;
1309 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1311 struct isl_basic_map *dup;
1313 dup = isl_basic_map_dup(bset_to_bmap(bset));
1314 return bset_from_bmap(dup);
1317 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1319 if (!bset)
1320 return NULL;
1322 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1323 bset->ref++;
1324 return bset;
1326 return isl_basic_set_dup(bset);
1329 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1331 if (!set)
1332 return NULL;
1334 set->ref++;
1335 return set;
1338 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1340 if (!bmap)
1341 return NULL;
1343 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1344 bmap->ref++;
1345 return bmap;
1347 bmap = isl_basic_map_dup(bmap);
1348 if (bmap)
1349 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1350 return bmap;
1353 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1355 if (!map)
1356 return NULL;
1358 map->ref++;
1359 return map;
1362 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1364 if (!bmap)
1365 return NULL;
1367 if (--bmap->ref > 0)
1368 return NULL;
1370 isl_ctx_deref(bmap->ctx);
1371 free(bmap->div);
1372 isl_blk_free(bmap->ctx, bmap->block2);
1373 free(bmap->ineq);
1374 isl_blk_free(bmap->ctx, bmap->block);
1375 isl_vec_free(bmap->sample);
1376 isl_space_free(bmap->dim);
1377 free(bmap);
1379 return NULL;
1382 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1384 return isl_basic_map_free(bset_to_bmap(bset));
1387 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1389 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1392 /* Check that "bset" does not involve any parameters.
1394 isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1396 if (!bset)
1397 return isl_stat_error;
1398 if (isl_basic_set_dim(bset, isl_dim_param) != 0)
1399 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1400 "basic set should not have any parameters",
1401 return isl_stat_error);
1402 return isl_stat_ok;
1405 /* Check that "bset" does not involve any local variables.
1407 isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1409 if (!bset)
1410 return isl_stat_error;
1411 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
1412 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1413 "basic set should not have any local variables",
1414 return isl_stat_error);
1415 return isl_stat_ok;
1418 /* Check that "map" has only named parameters, reporting an error
1419 * if it does not.
1421 isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1423 return isl_space_check_named_params(isl_map_peek_space(map));
1426 /* Check that "bmap" has only named parameters, reporting an error
1427 * if it does not.
1429 static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
1431 return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
1434 /* Check that "bmap1" and "bmap2" have the same parameters,
1435 * reporting an error if they do not.
1437 static isl_stat isl_basic_map_check_equal_params(
1438 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1440 isl_bool match;
1442 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1443 if (match < 0)
1444 return isl_stat_error;
1445 if (!match)
1446 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1447 "parameters don't match", return isl_stat_error);
1448 return isl_stat_ok;
1451 __isl_give isl_map *isl_map_align_params_map_map_and(
1452 __isl_take isl_map *map1, __isl_take isl_map *map2,
1453 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1454 __isl_take isl_map *map2))
1456 if (!map1 || !map2)
1457 goto error;
1458 if (isl_map_has_equal_params(map1, map2))
1459 return fn(map1, map2);
1460 if (isl_map_check_named_params(map1) < 0)
1461 goto error;
1462 if (isl_map_check_named_params(map2) < 0)
1463 goto error;
1464 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1465 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1466 return fn(map1, map2);
1467 error:
1468 isl_map_free(map1);
1469 isl_map_free(map2);
1470 return NULL;
1473 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1474 __isl_keep isl_map *map2,
1475 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1477 isl_bool r;
1479 if (!map1 || !map2)
1480 return isl_bool_error;
1481 if (isl_map_has_equal_params(map1, map2))
1482 return fn(map1, map2);
1483 if (isl_map_check_named_params(map1) < 0)
1484 return isl_bool_error;
1485 if (isl_map_check_named_params(map2) < 0)
1486 return isl_bool_error;
1487 map1 = isl_map_copy(map1);
1488 map2 = isl_map_copy(map2);
1489 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1490 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1491 r = fn(map1, map2);
1492 isl_map_free(map1);
1493 isl_map_free(map2);
1494 return r;
1497 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1499 struct isl_ctx *ctx;
1500 if (!bmap)
1501 return -1;
1502 ctx = bmap->ctx;
1503 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1504 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1505 return -1);
1506 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1507 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1508 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1509 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1510 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1511 isl_int *t;
1512 int j = isl_basic_map_alloc_inequality(bmap);
1513 if (j < 0)
1514 return -1;
1515 t = bmap->ineq[j];
1516 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1517 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1518 bmap->eq[-1] = t;
1519 bmap->n_eq++;
1520 bmap->n_ineq--;
1521 bmap->eq--;
1522 return 0;
1524 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1525 bmap->extra - bmap->n_div);
1526 return bmap->n_eq++;
1529 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1531 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1534 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1536 if (!bmap)
1537 return -1;
1538 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1539 bmap->n_eq -= n;
1540 return 0;
1543 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1545 return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1548 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1550 isl_int *t;
1551 if (!bmap)
1552 return -1;
1553 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1555 if (pos != bmap->n_eq - 1) {
1556 t = bmap->eq[pos];
1557 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1558 bmap->eq[bmap->n_eq - 1] = t;
1560 bmap->n_eq--;
1561 return 0;
1564 /* Turn inequality "pos" of "bmap" into an equality.
1566 * In particular, we move the inequality in front of the equalities
1567 * and move the last inequality in the position of the moved inequality.
1568 * Note that isl_tab_make_equalities_explicit depends on this particular
1569 * change in the ordering of the constraints.
1571 void isl_basic_map_inequality_to_equality(
1572 struct isl_basic_map *bmap, unsigned pos)
1574 isl_int *t;
1576 t = bmap->ineq[pos];
1577 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1578 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1579 bmap->eq[-1] = t;
1580 bmap->n_eq++;
1581 bmap->n_ineq--;
1582 bmap->eq--;
1583 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1584 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1585 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1586 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1589 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1591 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1594 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1596 struct isl_ctx *ctx;
1597 if (!bmap)
1598 return -1;
1599 ctx = bmap->ctx;
1600 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1601 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1602 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1603 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1604 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1605 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1606 1 + isl_basic_map_total_dim(bmap),
1607 bmap->extra - bmap->n_div);
1608 return bmap->n_ineq++;
1611 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1613 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1616 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1618 if (!bmap)
1619 return -1;
1620 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1621 bmap->n_ineq -= n;
1622 return 0;
1625 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1627 return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1630 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1632 isl_int *t;
1633 if (!bmap)
1634 return -1;
1635 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1637 if (pos != bmap->n_ineq - 1) {
1638 t = bmap->ineq[pos];
1639 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1640 bmap->ineq[bmap->n_ineq - 1] = t;
1641 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1643 bmap->n_ineq--;
1644 return 0;
1647 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1649 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1652 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1653 isl_int *eq)
1655 isl_bool empty;
1656 int k;
1658 empty = isl_basic_map_plain_is_empty(bmap);
1659 if (empty < 0)
1660 return isl_basic_map_free(bmap);
1661 if (empty)
1662 return bmap;
1664 bmap = isl_basic_map_cow(bmap);
1665 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1666 if (!bmap)
1667 return NULL;
1668 k = isl_basic_map_alloc_equality(bmap);
1669 if (k < 0)
1670 goto error;
1671 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1672 return bmap;
1673 error:
1674 isl_basic_map_free(bmap);
1675 return NULL;
1678 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1679 isl_int *eq)
1681 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1684 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1685 isl_int *ineq)
1687 int k;
1689 bmap = isl_basic_map_cow(bmap);
1690 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1691 if (!bmap)
1692 return NULL;
1693 k = isl_basic_map_alloc_inequality(bmap);
1694 if (k < 0)
1695 goto error;
1696 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1697 return bmap;
1698 error:
1699 isl_basic_map_free(bmap);
1700 return NULL;
1703 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1704 isl_int *ineq)
1706 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1709 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1711 if (!bmap)
1712 return -1;
1713 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1714 isl_seq_clr(bmap->div[bmap->n_div] +
1715 1 + 1 + isl_basic_map_total_dim(bmap),
1716 bmap->extra - bmap->n_div);
1717 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1718 return bmap->n_div++;
1721 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1723 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1726 #undef TYPE
1727 #define TYPE isl_basic_map
1728 #include "check_type_range_templ.c"
1730 /* Check that there are "n" dimensions of type "type" starting at "first"
1731 * in "bset".
1733 isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1734 enum isl_dim_type type, unsigned first, unsigned n)
1736 return isl_basic_map_check_range(bset_to_bmap(bset),
1737 type, first, n);
1740 /* Insert an extra integer division, prescribed by "div", to "bmap"
1741 * at (integer division) position "pos".
1743 * The integer division is first added at the end and then moved
1744 * into the right position.
1746 __isl_give isl_basic_map *isl_basic_map_insert_div(
1747 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1749 int i, k;
1751 bmap = isl_basic_map_cow(bmap);
1752 if (!bmap || !div)
1753 return isl_basic_map_free(bmap);
1755 if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1756 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1757 "unexpected size", return isl_basic_map_free(bmap));
1758 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1759 return isl_basic_map_free(bmap);
1761 bmap = isl_basic_map_extend_space(bmap,
1762 isl_basic_map_get_space(bmap), 1, 0, 2);
1763 k = isl_basic_map_alloc_div(bmap);
1764 if (k < 0)
1765 return isl_basic_map_free(bmap);
1766 isl_seq_cpy(bmap->div[k], div->el, div->size);
1767 isl_int_set_si(bmap->div[k][div->size], 0);
1769 for (i = k; i > pos; --i)
1770 bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1772 return bmap;
1775 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1777 if (!bmap)
1778 return isl_stat_error;
1779 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1780 bmap->n_div -= n;
1781 return isl_stat_ok;
1784 static __isl_give isl_basic_map *add_constraints(
1785 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1786 unsigned i_pos, unsigned o_pos)
1788 unsigned total, n_param, n_in, o_in, n_out, o_out, n_div;
1789 isl_ctx *ctx;
1790 isl_space *space;
1791 struct isl_dim_map *dim_map;
1793 space = isl_basic_map_peek_space(bmap2);
1794 if (!bmap1 || !space)
1795 goto error;
1797 total = isl_basic_map_dim(bmap1, isl_dim_all);
1798 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1799 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1800 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1801 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1802 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1803 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1804 ctx = isl_basic_map_get_ctx(bmap1);
1805 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1806 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1807 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1808 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1809 isl_dim_map_div(dim_map, bmap2, total);
1811 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1812 error:
1813 isl_basic_map_free(bmap1);
1814 isl_basic_map_free(bmap2);
1815 return NULL;
1818 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1819 struct isl_basic_set *bset2, unsigned pos)
1821 return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1822 bset_to_bmap(bset2), 0, pos));
1825 __isl_give isl_basic_map *isl_basic_map_extend_space(
1826 __isl_take isl_basic_map *base, __isl_take isl_space *space,
1827 unsigned extra, unsigned n_eq, unsigned n_ineq)
1829 struct isl_basic_map *ext;
1830 unsigned flags;
1831 int dims_ok;
1833 if (!space)
1834 goto error;
1836 if (!base)
1837 goto error;
1839 dims_ok = isl_space_is_equal(base->dim, space) &&
1840 base->extra >= base->n_div + extra;
1842 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1843 room_for_ineq(base, n_ineq)) {
1844 isl_space_free(space);
1845 return base;
1848 isl_assert(base->ctx, base->dim->nparam <= space->nparam, goto error);
1849 isl_assert(base->ctx, base->dim->n_in <= space->n_in, goto error);
1850 isl_assert(base->ctx, base->dim->n_out <= space->n_out, goto error);
1851 extra += base->extra;
1852 n_eq += base->n_eq;
1853 n_ineq += base->n_ineq;
1855 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1856 space = NULL;
1857 if (!ext)
1858 goto error;
1860 if (dims_ok)
1861 ext->sample = isl_vec_copy(base->sample);
1862 flags = base->flags;
1863 ext = add_constraints(ext, base, 0, 0);
1864 if (ext) {
1865 ext->flags = flags;
1866 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1869 return ext;
1871 error:
1872 isl_space_free(space);
1873 isl_basic_map_free(base);
1874 return NULL;
1877 __isl_give isl_basic_set *isl_basic_set_extend_space(
1878 __isl_take isl_basic_set *base,
1879 __isl_take isl_space *dim, unsigned extra,
1880 unsigned n_eq, unsigned n_ineq)
1882 return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1883 dim, extra, n_eq, n_ineq));
1886 struct isl_basic_map *isl_basic_map_extend_constraints(
1887 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1889 if (!base)
1890 return NULL;
1891 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1892 0, n_eq, n_ineq);
1895 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1896 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1897 unsigned n_eq, unsigned n_ineq)
1899 struct isl_basic_map *bmap;
1900 isl_space *dim;
1902 if (!base)
1903 return NULL;
1904 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1905 if (!dim)
1906 goto error;
1908 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1909 return bmap;
1910 error:
1911 isl_basic_map_free(base);
1912 return NULL;
1915 struct isl_basic_set *isl_basic_set_extend_constraints(
1916 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1918 isl_basic_map *bmap = bset_to_bmap(base);
1919 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1920 return bset_from_bmap(bmap);
1923 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1925 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1928 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1930 if (!bmap)
1931 return NULL;
1933 if (bmap->ref > 1) {
1934 bmap->ref--;
1935 bmap = isl_basic_map_dup(bmap);
1937 if (bmap) {
1938 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1939 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1941 return bmap;
1944 /* Clear all cached information in "map", either because it is about
1945 * to be modified or because it is being freed.
1946 * Always return the same pointer that is passed in.
1947 * This is needed for the use in isl_map_free.
1949 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1951 isl_basic_map_free(map->cached_simple_hull[0]);
1952 isl_basic_map_free(map->cached_simple_hull[1]);
1953 map->cached_simple_hull[0] = NULL;
1954 map->cached_simple_hull[1] = NULL;
1955 return map;
1958 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
1960 return isl_map_cow(set);
1963 /* Return an isl_map that is equal to "map" and that has only
1964 * a single reference.
1966 * If the original input already has only one reference, then
1967 * simply return it, but clear all cached information, since
1968 * it may be rendered invalid by the operations that will be
1969 * performed on the result.
1971 * Otherwise, create a duplicate (without any cached information).
1973 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
1975 if (!map)
1976 return NULL;
1978 if (map->ref == 1)
1979 return clear_caches(map);
1980 map->ref--;
1981 return isl_map_dup(map);
1984 static void swap_vars(struct isl_blk blk, isl_int *a,
1985 unsigned a_len, unsigned b_len)
1987 isl_seq_cpy(blk.data, a+a_len, b_len);
1988 isl_seq_cpy(blk.data+b_len, a, a_len);
1989 isl_seq_cpy(a, blk.data, b_len+a_len);
1992 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1993 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1995 int i;
1996 struct isl_blk blk;
1998 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
1999 goto error;
2001 if (n1 == 0 || n2 == 0)
2002 return bmap;
2004 bmap = isl_basic_map_cow(bmap);
2005 if (!bmap)
2006 return NULL;
2008 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2009 if (isl_blk_is_error(blk))
2010 goto error;
2012 for (i = 0; i < bmap->n_eq; ++i)
2013 swap_vars(blk,
2014 bmap->eq[i] + pos, n1, n2);
2016 for (i = 0; i < bmap->n_ineq; ++i)
2017 swap_vars(blk,
2018 bmap->ineq[i] + pos, n1, n2);
2020 for (i = 0; i < bmap->n_div; ++i)
2021 swap_vars(blk,
2022 bmap->div[i]+1 + pos, n1, n2);
2024 isl_blk_free(bmap->ctx, blk);
2026 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2027 bmap = isl_basic_map_gauss(bmap, NULL);
2028 return isl_basic_map_finalize(bmap);
2029 error:
2030 isl_basic_map_free(bmap);
2031 return NULL;
2034 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2035 __isl_take isl_basic_map *bmap)
2037 int i = 0;
2038 unsigned total;
2039 if (!bmap)
2040 goto error;
2041 total = isl_basic_map_total_dim(bmap);
2042 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2043 return isl_basic_map_free(bmap);
2044 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2045 if (bmap->n_eq > 0)
2046 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
2047 else {
2048 i = isl_basic_map_alloc_equality(bmap);
2049 if (i < 0)
2050 goto error;
2052 isl_int_set_si(bmap->eq[i][0], 1);
2053 isl_seq_clr(bmap->eq[i]+1, total);
2054 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2055 isl_vec_free(bmap->sample);
2056 bmap->sample = NULL;
2057 return isl_basic_map_finalize(bmap);
2058 error:
2059 isl_basic_map_free(bmap);
2060 return NULL;
2063 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2064 __isl_take isl_basic_set *bset)
2066 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2069 __isl_give isl_basic_map *isl_basic_map_set_rational(
2070 __isl_take isl_basic_map *bmap)
2072 if (!bmap)
2073 return NULL;
2075 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2076 return bmap;
2078 bmap = isl_basic_map_cow(bmap);
2079 if (!bmap)
2080 return NULL;
2082 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2084 return isl_basic_map_finalize(bmap);
2087 __isl_give isl_basic_set *isl_basic_set_set_rational(
2088 __isl_take isl_basic_set *bset)
2090 return isl_basic_map_set_rational(bset);
2093 __isl_give isl_basic_set *isl_basic_set_set_integral(
2094 __isl_take isl_basic_set *bset)
2096 if (!bset)
2097 return NULL;
2099 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2100 return bset;
2102 bset = isl_basic_set_cow(bset);
2103 if (!bset)
2104 return NULL;
2106 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2108 return isl_basic_set_finalize(bset);
2111 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2113 int i;
2115 map = isl_map_cow(map);
2116 if (!map)
2117 return NULL;
2118 for (i = 0; i < map->n; ++i) {
2119 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2120 if (!map->p[i])
2121 goto error;
2123 return map;
2124 error:
2125 isl_map_free(map);
2126 return NULL;
2129 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2131 return isl_map_set_rational(set);
2134 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2135 * of "bmap").
2137 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2139 isl_int *t = bmap->div[a];
2140 bmap->div[a] = bmap->div[b];
2141 bmap->div[b] = t;
2144 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2145 * div definitions accordingly.
2147 __isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2148 int a, int b)
2150 int i;
2151 int off;
2153 off = isl_basic_map_var_offset(bmap, isl_dim_div);
2154 if (off < 0)
2155 return isl_basic_map_free(bmap);
2157 swap_div(bmap, a, b);
2159 for (i = 0; i < bmap->n_eq; ++i)
2160 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2162 for (i = 0; i < bmap->n_ineq; ++i)
2163 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2165 for (i = 0; i < bmap->n_div; ++i)
2166 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2167 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2169 return bmap;
2172 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2174 isl_seq_cpy(c, c + n, rem);
2175 isl_seq_clr(c + rem, n);
2178 /* Drop n dimensions starting at first.
2180 * In principle, this frees up some extra variables as the number
2181 * of columns remains constant, but we would have to extend
2182 * the div array too as the number of rows in this array is assumed
2183 * to be equal to extra.
2185 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2186 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2188 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2191 /* Move "n" divs starting at "first" to the end of the list of divs.
2193 static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
2194 unsigned first, unsigned n)
2196 isl_int **div;
2197 int i;
2199 if (first + n == bmap->n_div)
2200 return bmap;
2202 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2203 if (!div)
2204 goto error;
2205 for (i = 0; i < n; ++i)
2206 div[i] = bmap->div[first + i];
2207 for (i = 0; i < bmap->n_div - first - n; ++i)
2208 bmap->div[first + i] = bmap->div[first + n + i];
2209 for (i = 0; i < n; ++i)
2210 bmap->div[bmap->n_div - n + i] = div[i];
2211 free(div);
2212 return bmap;
2213 error:
2214 isl_basic_map_free(bmap);
2215 return NULL;
2218 #undef TYPE
2219 #define TYPE isl_map
2220 static
2221 #include "check_type_range_templ.c"
2223 /* Check that there are "n" dimensions of type "type" starting at "first"
2224 * in "set".
2226 static isl_stat isl_set_check_range(__isl_keep isl_set *set,
2227 enum isl_dim_type type, unsigned first, unsigned n)
2229 return isl_map_check_range(set_to_map(set), type, first, n);
2232 /* Drop "n" dimensions of type "type" starting at "first".
2233 * Perform the core computation, without cowing or
2234 * simplifying and finalizing the result.
2236 * In principle, this frees up some extra variables as the number
2237 * of columns remains constant, but we would have to extend
2238 * the div array too as the number of rows in this array is assumed
2239 * to be equal to extra.
2241 __isl_give isl_basic_map *isl_basic_map_drop_core(
2242 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2243 unsigned first, unsigned n)
2245 int i;
2246 unsigned offset;
2247 unsigned left;
2249 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2250 return isl_basic_map_free(bmap);
2252 offset = isl_basic_map_offset(bmap, type) + first;
2253 left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
2254 for (i = 0; i < bmap->n_eq; ++i)
2255 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2257 for (i = 0; i < bmap->n_ineq; ++i)
2258 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2260 for (i = 0; i < bmap->n_div; ++i)
2261 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2263 if (type == isl_dim_div) {
2264 bmap = move_divs_last(bmap, first, n);
2265 if (!bmap)
2266 return NULL;
2267 if (isl_basic_map_free_div(bmap, n) < 0)
2268 return isl_basic_map_free(bmap);
2269 } else
2270 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2271 if (!bmap->dim)
2272 return isl_basic_map_free(bmap);
2274 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2275 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2276 return bmap;
2279 /* Drop "n" dimensions of type "type" starting at "first".
2281 * In principle, this frees up some extra variables as the number
2282 * of columns remains constant, but we would have to extend
2283 * the div array too as the number of rows in this array is assumed
2284 * to be equal to extra.
2286 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2287 enum isl_dim_type type, unsigned first, unsigned n)
2289 if (!bmap)
2290 return NULL;
2291 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2292 return bmap;
2294 bmap = isl_basic_map_cow(bmap);
2295 if (!bmap)
2296 return NULL;
2298 bmap = isl_basic_map_drop_core(bmap, type, first, n);
2300 bmap = isl_basic_map_simplify(bmap);
2301 return isl_basic_map_finalize(bmap);
2304 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2305 enum isl_dim_type type, unsigned first, unsigned n)
2307 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2308 type, first, n));
2311 /* No longer consider "map" to be normalized.
2313 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2315 if (!map)
2316 return NULL;
2317 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2318 return map;
2321 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2322 enum isl_dim_type type, unsigned first, unsigned n)
2324 int i;
2326 if (isl_map_check_range(map, type, first, n) < 0)
2327 return isl_map_free(map);
2329 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2330 return map;
2331 map = isl_map_cow(map);
2332 if (!map)
2333 goto error;
2334 map->dim = isl_space_drop_dims(map->dim, type, first, n);
2335 if (!map->dim)
2336 goto error;
2338 for (i = 0; i < map->n; ++i) {
2339 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2340 if (!map->p[i])
2341 goto error;
2343 map = isl_map_unmark_normalized(map);
2345 return map;
2346 error:
2347 isl_map_free(map);
2348 return NULL;
2351 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2352 enum isl_dim_type type, unsigned first, unsigned n)
2354 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2357 /* Drop the integer division at position "div", which is assumed
2358 * not to appear in any of the constraints or
2359 * in any of the other integer divisions.
2361 * Since the integer division is redundant, there is no need to cow.
2363 __isl_give isl_basic_map *isl_basic_map_drop_div(
2364 __isl_take isl_basic_map *bmap, unsigned div)
2366 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2369 /* Eliminate the specified n dimensions starting at first from the
2370 * constraints, without removing the dimensions from the space.
2371 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2373 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2374 enum isl_dim_type type, unsigned first, unsigned n)
2376 int i;
2378 if (n == 0)
2379 return map;
2381 if (isl_map_check_range(map, type, first, n) < 0)
2382 return isl_map_free(map);
2384 map = isl_map_cow(map);
2385 if (!map)
2386 return NULL;
2388 for (i = 0; i < map->n; ++i) {
2389 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2390 if (!map->p[i])
2391 goto error;
2393 return map;
2394 error:
2395 isl_map_free(map);
2396 return NULL;
2399 /* Eliminate the specified n dimensions starting at first from the
2400 * constraints, without removing the dimensions from the space.
2401 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2403 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2404 enum isl_dim_type type, unsigned first, unsigned n)
2406 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2409 /* Eliminate the specified n dimensions starting at first from the
2410 * constraints, without removing the dimensions from the space.
2411 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2413 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2414 unsigned first, unsigned n)
2416 return isl_set_eliminate(set, isl_dim_set, first, n);
2419 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2420 __isl_take isl_basic_map *bmap)
2422 int v_div;
2424 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2425 if (v_div < 0)
2426 return isl_basic_map_free(bmap);
2427 bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);
2428 if (!bmap)
2429 return NULL;
2430 bmap->n_div = 0;
2431 return isl_basic_map_finalize(bmap);
2434 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2435 __isl_take isl_basic_set *bset)
2437 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2440 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2442 int i;
2444 if (!map)
2445 return NULL;
2446 if (map->n == 0)
2447 return map;
2449 map = isl_map_cow(map);
2450 if (!map)
2451 return NULL;
2453 for (i = 0; i < map->n; ++i) {
2454 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2455 if (!map->p[i])
2456 goto error;
2458 return map;
2459 error:
2460 isl_map_free(map);
2461 return NULL;
2464 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2466 return isl_map_remove_divs(set);
2469 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2470 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2471 unsigned first, unsigned n)
2473 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2474 return isl_basic_map_free(bmap);
2475 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2476 return bmap;
2477 bmap = isl_basic_map_eliminate_vars(bmap,
2478 isl_basic_map_offset(bmap, type) - 1 + first, n);
2479 if (!bmap)
2480 return bmap;
2481 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2482 return bmap;
2483 bmap = isl_basic_map_drop(bmap, type, first, n);
2484 return bmap;
2487 /* Return true if the definition of the given div (recursively) involves
2488 * any of the given variables.
2490 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2491 unsigned first, unsigned n)
2493 int i;
2494 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2496 if (isl_int_is_zero(bmap->div[div][0]))
2497 return isl_bool_false;
2498 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2499 return isl_bool_true;
2501 for (i = bmap->n_div - 1; i >= 0; --i) {
2502 isl_bool involves;
2504 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2505 continue;
2506 involves = div_involves_vars(bmap, i, first, n);
2507 if (involves < 0 || involves)
2508 return involves;
2511 return isl_bool_false;
2514 /* Try and add a lower and/or upper bound on "div" to "bmap"
2515 * based on inequality "i".
2516 * "total" is the total number of variables (excluding the divs).
2517 * "v" is a temporary object that can be used during the calculations.
2518 * If "lb" is set, then a lower bound should be constructed.
2519 * If "ub" is set, then an upper bound should be constructed.
2521 * The calling function has already checked that the inequality does not
2522 * reference "div", but we still need to check that the inequality is
2523 * of the right form. We'll consider the case where we want to construct
2524 * a lower bound. The construction of upper bounds is similar.
2526 * Let "div" be of the form
2528 * q = floor((a + f(x))/d)
2530 * We essentially check if constraint "i" is of the form
2532 * b + f(x) >= 0
2534 * so that we can use it to derive a lower bound on "div".
2535 * However, we allow a slightly more general form
2537 * b + g(x) >= 0
2539 * with the condition that the coefficients of g(x) - f(x) are all
2540 * divisible by d.
2541 * Rewriting this constraint as
2543 * 0 >= -b - g(x)
2545 * adding a + f(x) to both sides and dividing by d, we obtain
2547 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2549 * Taking the floor on both sides, we obtain
2551 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2553 * or
2555 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2557 * In the case of an upper bound, we construct the constraint
2559 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2562 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2563 __isl_take isl_basic_map *bmap, int div, int i,
2564 unsigned total, isl_int v, int lb, int ub)
2566 int j;
2568 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2569 if (lb) {
2570 isl_int_sub(v, bmap->ineq[i][1 + j],
2571 bmap->div[div][1 + 1 + j]);
2572 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2574 if (ub) {
2575 isl_int_add(v, bmap->ineq[i][1 + j],
2576 bmap->div[div][1 + 1 + j]);
2577 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2580 if (!lb && !ub)
2581 return bmap;
2583 bmap = isl_basic_map_cow(bmap);
2584 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2585 if (lb) {
2586 int k = isl_basic_map_alloc_inequality(bmap);
2587 if (k < 0)
2588 goto error;
2589 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2590 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2591 bmap->div[div][1 + j]);
2592 isl_int_cdiv_q(bmap->ineq[k][j],
2593 bmap->ineq[k][j], bmap->div[div][0]);
2595 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2597 if (ub) {
2598 int k = isl_basic_map_alloc_inequality(bmap);
2599 if (k < 0)
2600 goto error;
2601 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2602 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2603 bmap->div[div][1 + j]);
2604 isl_int_fdiv_q(bmap->ineq[k][j],
2605 bmap->ineq[k][j], bmap->div[div][0]);
2607 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2610 return bmap;
2611 error:
2612 isl_basic_map_free(bmap);
2613 return NULL;
2616 /* This function is called right before "div" is eliminated from "bmap"
2617 * using Fourier-Motzkin.
2618 * Look through the constraints of "bmap" for constraints on the argument
2619 * of the integer division and use them to construct constraints on the
2620 * integer division itself. These constraints can then be combined
2621 * during the Fourier-Motzkin elimination.
2622 * Note that it is only useful to introduce lower bounds on "div"
2623 * if "bmap" already contains upper bounds on "div" as the newly
2624 * introduce lower bounds can then be combined with the pre-existing
2625 * upper bounds. Similarly for upper bounds.
2626 * We therefore first check if "bmap" contains any lower and/or upper bounds
2627 * on "div".
2629 * It is interesting to note that the introduction of these constraints
2630 * can indeed lead to more accurate results, even when compared to
2631 * deriving constraints on the argument of "div" from constraints on "div".
2632 * Consider, for example, the set
2634 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2636 * The second constraint can be rewritten as
2638 * 2 * [(-i-2j+3)/4] + k >= 0
2640 * from which we can derive
2642 * -i - 2j + 3 >= -2k
2644 * or
2646 * i + 2j <= 3 + 2k
2648 * Combined with the first constraint, we obtain
2650 * -3 <= 3 + 2k or k >= -3
2652 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2653 * the first constraint, we obtain
2655 * [(i + 2j)/4] >= [-3/4] = -1
2657 * Combining this constraint with the second constraint, we obtain
2659 * k >= -2
2661 static __isl_give isl_basic_map *insert_bounds_on_div(
2662 __isl_take isl_basic_map *bmap, int div)
2664 int i;
2665 int check_lb, check_ub;
2666 isl_int v;
2667 int v_div;
2669 if (!bmap)
2670 return NULL;
2672 if (isl_int_is_zero(bmap->div[div][0]))
2673 return bmap;
2675 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2676 if (v_div < 0)
2677 return isl_basic_map_free(bmap);
2679 check_lb = 0;
2680 check_ub = 0;
2681 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2682 int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);
2683 if (s > 0)
2684 check_ub = 1;
2685 if (s < 0)
2686 check_lb = 1;
2689 if (!check_lb && !check_ub)
2690 return bmap;
2692 isl_int_init(v);
2694 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2695 if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))
2696 continue;
2698 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,
2699 check_lb, check_ub);
2702 isl_int_clear(v);
2704 return bmap;
2707 /* Remove all divs (recursively) involving any of the given dimensions
2708 * in their definitions.
2710 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2711 __isl_take isl_basic_map *bmap,
2712 enum isl_dim_type type, unsigned first, unsigned n)
2714 int i;
2716 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2717 return isl_basic_map_free(bmap);
2718 first += isl_basic_map_offset(bmap, type);
2720 for (i = bmap->n_div - 1; i >= 0; --i) {
2721 isl_bool involves;
2723 involves = div_involves_vars(bmap, i, first, n);
2724 if (involves < 0)
2725 return isl_basic_map_free(bmap);
2726 if (!involves)
2727 continue;
2728 bmap = insert_bounds_on_div(bmap, i);
2729 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2730 if (!bmap)
2731 return NULL;
2732 i = bmap->n_div;
2735 return bmap;
2738 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2739 __isl_take isl_basic_set *bset,
2740 enum isl_dim_type type, unsigned first, unsigned n)
2742 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2745 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2746 enum isl_dim_type type, unsigned first, unsigned n)
2748 int i;
2750 if (!map)
2751 return NULL;
2752 if (map->n == 0)
2753 return map;
2755 map = isl_map_cow(map);
2756 if (!map)
2757 return NULL;
2759 for (i = 0; i < map->n; ++i) {
2760 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2761 type, first, n);
2762 if (!map->p[i])
2763 goto error;
2765 return map;
2766 error:
2767 isl_map_free(map);
2768 return NULL;
2771 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2772 enum isl_dim_type type, unsigned first, unsigned n)
2774 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2775 type, first, n));
2778 /* Does the description of "bmap" depend on the specified dimensions?
2779 * We also check whether the dimensions appear in any of the div definitions.
2780 * In principle there is no need for this check. If the dimensions appear
2781 * in a div definition, they also appear in the defining constraints of that
2782 * div.
2784 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2785 enum isl_dim_type type, unsigned first, unsigned n)
2787 int i;
2789 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2790 return isl_bool_error;
2792 first += isl_basic_map_offset(bmap, type);
2793 for (i = 0; i < bmap->n_eq; ++i)
2794 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2795 return isl_bool_true;
2796 for (i = 0; i < bmap->n_ineq; ++i)
2797 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2798 return isl_bool_true;
2799 for (i = 0; i < bmap->n_div; ++i) {
2800 if (isl_int_is_zero(bmap->div[i][0]))
2801 continue;
2802 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2803 return isl_bool_true;
2806 return isl_bool_false;
2809 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2810 enum isl_dim_type type, unsigned first, unsigned n)
2812 int i;
2814 if (isl_map_check_range(map, type, first, n) < 0)
2815 return isl_bool_error;
2817 for (i = 0; i < map->n; ++i) {
2818 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2819 type, first, n);
2820 if (involves < 0 || involves)
2821 return involves;
2824 return isl_bool_false;
2827 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2828 enum isl_dim_type type, unsigned first, unsigned n)
2830 return isl_basic_map_involves_dims(bset, type, first, n);
2833 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2834 enum isl_dim_type type, unsigned first, unsigned n)
2836 return isl_map_involves_dims(set, type, first, n);
2839 /* Drop all constraints in bmap that involve any of the dimensions
2840 * first to first+n-1.
2841 * This function only performs the actual removal of constraints.
2843 * This function should not call finalize since it is used by
2844 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
2846 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2847 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2849 int i;
2851 if (n == 0)
2852 return bmap;
2854 bmap = isl_basic_map_cow(bmap);
2856 if (!bmap)
2857 return NULL;
2859 for (i = bmap->n_eq - 1; i >= 0; --i) {
2860 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2861 continue;
2862 isl_basic_map_drop_equality(bmap, i);
2865 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2866 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2867 continue;
2868 isl_basic_map_drop_inequality(bmap, i);
2871 return bmap;
2874 /* Drop all constraints in bset that involve any of the dimensions
2875 * first to first+n-1.
2876 * This function only performs the actual removal of constraints.
2878 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2879 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2881 return isl_basic_map_drop_constraints_involving(bset, first, n);
2884 /* Drop all constraints in bmap that do not involve any of the dimensions
2885 * first to first + n - 1 of the given type.
2887 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2888 __isl_take isl_basic_map *bmap,
2889 enum isl_dim_type type, unsigned first, unsigned n)
2891 int i;
2893 if (n == 0) {
2894 isl_space *space = isl_basic_map_get_space(bmap);
2895 isl_basic_map_free(bmap);
2896 return isl_basic_map_universe(space);
2898 bmap = isl_basic_map_cow(bmap);
2899 if (!bmap)
2900 return NULL;
2902 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2903 return isl_basic_map_free(bmap);
2905 first += isl_basic_map_offset(bmap, type) - 1;
2907 for (i = bmap->n_eq - 1; i >= 0; --i) {
2908 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2909 continue;
2910 isl_basic_map_drop_equality(bmap, i);
2913 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2914 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2915 continue;
2916 isl_basic_map_drop_inequality(bmap, i);
2919 bmap = isl_basic_map_add_known_div_constraints(bmap);
2920 return bmap;
2923 /* Drop all constraints in bset that do not involve any of the dimensions
2924 * first to first + n - 1 of the given type.
2926 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2927 __isl_take isl_basic_set *bset,
2928 enum isl_dim_type type, unsigned first, unsigned n)
2930 return isl_basic_map_drop_constraints_not_involving_dims(bset,
2931 type, first, n);
2934 /* Drop all constraints in bmap that involve any of the dimensions
2935 * first to first + n - 1 of the given type.
2937 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2938 __isl_take isl_basic_map *bmap,
2939 enum isl_dim_type type, unsigned first, unsigned n)
2941 if (!bmap)
2942 return NULL;
2943 if (n == 0)
2944 return bmap;
2946 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2947 return isl_basic_map_free(bmap);
2949 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2950 first += isl_basic_map_offset(bmap, type) - 1;
2951 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
2952 bmap = isl_basic_map_add_known_div_constraints(bmap);
2953 return bmap;
2956 /* Drop all constraints in bset that involve any of the dimensions
2957 * first to first + n - 1 of the given type.
2959 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2960 __isl_take isl_basic_set *bset,
2961 enum isl_dim_type type, unsigned first, unsigned n)
2963 return isl_basic_map_drop_constraints_involving_dims(bset,
2964 type, first, n);
2967 /* Drop constraints from "map" by applying "drop" to each basic map.
2969 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2970 enum isl_dim_type type, unsigned first, unsigned n,
2971 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2972 enum isl_dim_type type, unsigned first, unsigned n))
2974 int i;
2976 if (isl_map_check_range(map, type, first, n) < 0)
2977 return isl_map_free(map);
2979 map = isl_map_cow(map);
2980 if (!map)
2981 return NULL;
2983 for (i = 0; i < map->n; ++i) {
2984 map->p[i] = drop(map->p[i], type, first, n);
2985 if (!map->p[i])
2986 return isl_map_free(map);
2989 if (map->n > 1)
2990 ISL_F_CLR(map, ISL_MAP_DISJOINT);
2992 return map;
2995 /* Drop all constraints in map that involve any of the dimensions
2996 * first to first + n - 1 of the given type.
2998 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
2999 __isl_take isl_map *map,
3000 enum isl_dim_type type, unsigned first, unsigned n)
3002 if (n == 0)
3003 return map;
3004 return drop_constraints(map, type, first, n,
3005 &isl_basic_map_drop_constraints_involving_dims);
3008 /* Drop all constraints in "map" that do not involve any of the dimensions
3009 * first to first + n - 1 of the given type.
3011 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3012 __isl_take isl_map *map,
3013 enum isl_dim_type type, unsigned first, unsigned n)
3015 if (n == 0) {
3016 isl_space *space = isl_map_get_space(map);
3017 isl_map_free(map);
3018 return isl_map_universe(space);
3020 return drop_constraints(map, type, first, n,
3021 &isl_basic_map_drop_constraints_not_involving_dims);
3024 /* Drop all constraints in set that involve any of the dimensions
3025 * first to first + n - 1 of the given type.
3027 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3028 __isl_take isl_set *set,
3029 enum isl_dim_type type, unsigned first, unsigned n)
3031 return isl_map_drop_constraints_involving_dims(set, type, first, n);
3034 /* Drop all constraints in "set" that do not involve any of the dimensions
3035 * first to first + n - 1 of the given type.
3037 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3038 __isl_take isl_set *set,
3039 enum isl_dim_type type, unsigned first, unsigned n)
3041 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3044 /* Does local variable "div" of "bmap" have a complete explicit representation?
3045 * Having a complete explicit representation requires not only
3046 * an explicit representation, but also that all local variables
3047 * that appear in this explicit representation in turn have
3048 * a complete explicit representation.
3050 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3052 int i;
3053 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3054 isl_bool marked;
3056 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3057 if (marked < 0 || marked)
3058 return isl_bool_not(marked);
3060 for (i = bmap->n_div - 1; i >= 0; --i) {
3061 isl_bool known;
3063 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3064 continue;
3065 known = isl_basic_map_div_is_known(bmap, i);
3066 if (known < 0 || !known)
3067 return known;
3070 return isl_bool_true;
3073 /* Remove all divs that are unknown or defined in terms of unknown divs.
3075 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3076 __isl_take isl_basic_map *bmap)
3078 int i;
3080 if (!bmap)
3081 return NULL;
3083 for (i = bmap->n_div - 1; i >= 0; --i) {
3084 if (isl_basic_map_div_is_known(bmap, i))
3085 continue;
3086 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3087 if (!bmap)
3088 return NULL;
3089 i = bmap->n_div;
3092 return bmap;
3095 /* Remove all divs that are unknown or defined in terms of unknown divs.
3097 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3098 __isl_take isl_basic_set *bset)
3100 return isl_basic_map_remove_unknown_divs(bset);
3103 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3105 int i;
3107 if (!map)
3108 return NULL;
3109 if (map->n == 0)
3110 return map;
3112 map = isl_map_cow(map);
3113 if (!map)
3114 return NULL;
3116 for (i = 0; i < map->n; ++i) {
3117 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3118 if (!map->p[i])
3119 goto error;
3121 return map;
3122 error:
3123 isl_map_free(map);
3124 return NULL;
3127 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3129 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3132 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3133 __isl_take isl_basic_set *bset,
3134 enum isl_dim_type type, unsigned first, unsigned n)
3136 isl_basic_map *bmap = bset_to_bmap(bset);
3137 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3138 return bset_from_bmap(bmap);
3141 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3142 enum isl_dim_type type, unsigned first, unsigned n)
3144 int i;
3146 if (n == 0)
3147 return map;
3149 map = isl_map_cow(map);
3150 if (isl_map_check_range(map, type, first, n) < 0)
3151 return isl_map_free(map);
3153 for (i = 0; i < map->n; ++i) {
3154 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3155 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3156 if (!map->p[i])
3157 goto error;
3159 map = isl_map_drop(map, type, first, n);
3160 return map;
3161 error:
3162 isl_map_free(map);
3163 return NULL;
3166 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3167 enum isl_dim_type type, unsigned first, unsigned n)
3169 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3170 type, first, n));
3173 /* Project out n inputs starting at first using Fourier-Motzkin */
3174 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
3175 unsigned first, unsigned n)
3177 return isl_map_remove_dims(map, isl_dim_in, first, n);
3180 void isl_basic_set_print_internal(struct isl_basic_set *bset,
3181 FILE *out, int indent)
3183 isl_printer *p;
3185 if (!bset) {
3186 fprintf(out, "null basic set\n");
3187 return;
3190 fprintf(out, "%*s", indent, "");
3191 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3192 bset->ref, bset->dim->nparam, bset->dim->n_out,
3193 bset->extra, bset->flags);
3195 p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
3196 p = isl_printer_set_dump(p, 1);
3197 p = isl_printer_set_indent(p, indent);
3198 p = isl_printer_start_line(p);
3199 p = isl_printer_print_basic_set(p, bset);
3200 p = isl_printer_end_line(p);
3201 isl_printer_free(p);
3204 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
3205 FILE *out, int indent)
3207 isl_printer *p;
3209 if (!bmap) {
3210 fprintf(out, "null basic map\n");
3211 return;
3214 fprintf(out, "%*s", indent, "");
3215 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3216 "flags: %x, n_name: %d\n",
3217 bmap->ref,
3218 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3219 bmap->extra, bmap->flags, bmap->dim->n_id);
3221 p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
3222 p = isl_printer_set_dump(p, 1);
3223 p = isl_printer_set_indent(p, indent);
3224 p = isl_printer_start_line(p);
3225 p = isl_printer_print_basic_map(p, bmap);
3226 p = isl_printer_end_line(p);
3227 isl_printer_free(p);
3230 __isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3231 unsigned pos)
3233 unsigned total;
3235 if (!bmap)
3236 return NULL;
3237 total = isl_basic_map_total_dim(bmap);
3238 if (pos >= bmap->n_ineq)
3239 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3240 "invalid position", return isl_basic_map_free(bmap));
3241 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3242 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3243 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3244 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3245 return bmap;
3248 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3249 unsigned flags)
3251 if (isl_space_check_is_set(space) < 0)
3252 goto error;
3253 return isl_map_alloc_space(space, n, flags);
3254 error:
3255 isl_space_free(space);
3256 return NULL;
3259 /* Make sure "map" has room for at least "n" more basic maps.
3261 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3263 int i;
3264 struct isl_map *grown = NULL;
3266 if (!map)
3267 return NULL;
3268 isl_assert(map->ctx, n >= 0, goto error);
3269 if (map->n + n <= map->size)
3270 return map;
3271 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3272 if (!grown)
3273 goto error;
3274 for (i = 0; i < map->n; ++i) {
3275 grown->p[i] = isl_basic_map_copy(map->p[i]);
3276 if (!grown->p[i])
3277 goto error;
3278 grown->n++;
3280 isl_map_free(map);
3281 return grown;
3282 error:
3283 isl_map_free(grown);
3284 isl_map_free(map);
3285 return NULL;
3288 /* Make sure "set" has room for at least "n" more basic sets.
3290 struct isl_set *isl_set_grow(struct isl_set *set, int n)
3292 return set_from_map(isl_map_grow(set_to_map(set), n));
3295 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3297 return isl_map_from_basic_map(bset);
3300 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3302 struct isl_map *map;
3304 if (!bmap)
3305 return NULL;
3307 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3308 return isl_map_add_basic_map(map, bmap);
3311 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3312 __isl_take isl_basic_set *bset)
3314 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3315 bset_to_bmap(bset)));
3318 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3320 return isl_map_free(set);
3323 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3325 int i;
3327 if (!set) {
3328 fprintf(out, "null set\n");
3329 return;
3332 fprintf(out, "%*s", indent, "");
3333 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3334 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3335 set->flags);
3336 for (i = 0; i < set->n; ++i) {
3337 fprintf(out, "%*s", indent, "");
3338 fprintf(out, "basic set %d:\n", i);
3339 isl_basic_set_print_internal(set->p[i], out, indent+4);
3343 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3345 int i;
3347 if (!map) {
3348 fprintf(out, "null map\n");
3349 return;
3352 fprintf(out, "%*s", indent, "");
3353 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3354 "flags: %x, n_name: %d\n",
3355 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3356 map->dim->n_out, map->flags, map->dim->n_id);
3357 for (i = 0; i < map->n; ++i) {
3358 fprintf(out, "%*s", indent, "");
3359 fprintf(out, "basic map %d:\n", i);
3360 isl_basic_map_print_internal(map->p[i], out, indent+4);
3364 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3365 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3367 struct isl_basic_map *bmap_domain;
3369 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3370 goto error;
3372 if (isl_basic_set_dim(bset, isl_dim_set) != 0)
3373 isl_assert(bset->ctx,
3374 isl_basic_map_compatible_domain(bmap, bset), goto error);
3376 bmap = isl_basic_map_cow(bmap);
3377 if (!bmap)
3378 goto error;
3379 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3380 bset->n_div, bset->n_eq, bset->n_ineq);
3381 bmap_domain = isl_basic_map_from_domain(bset);
3382 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3384 bmap = isl_basic_map_simplify(bmap);
3385 return isl_basic_map_finalize(bmap);
3386 error:
3387 isl_basic_map_free(bmap);
3388 isl_basic_set_free(bset);
3389 return NULL;
3392 /* Check that the space of "bset" is the same as that of the range of "bmap".
3394 static isl_stat isl_basic_map_check_compatible_range(
3395 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3397 isl_bool ok;
3399 ok = isl_basic_map_compatible_range(bmap, bset);
3400 if (ok < 0)
3401 return isl_stat_error;
3402 if (!ok)
3403 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3404 "incompatible spaces", return isl_stat_error);
3406 return isl_stat_ok;
3409 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3410 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3412 struct isl_basic_map *bmap_range;
3414 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3415 goto error;
3417 if (isl_basic_set_dim(bset, isl_dim_set) != 0 &&
3418 isl_basic_map_check_compatible_range(bmap, bset) < 0)
3419 goto error;
3421 if (isl_basic_set_plain_is_universe(bset)) {
3422 isl_basic_set_free(bset);
3423 return bmap;
3426 bmap = isl_basic_map_cow(bmap);
3427 if (!bmap)
3428 goto error;
3429 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3430 bset->n_div, bset->n_eq, bset->n_ineq);
3431 bmap_range = bset_to_bmap(bset);
3432 bmap = add_constraints(bmap, bmap_range, 0, 0);
3434 bmap = isl_basic_map_simplify(bmap);
3435 return isl_basic_map_finalize(bmap);
3436 error:
3437 isl_basic_map_free(bmap);
3438 isl_basic_set_free(bset);
3439 return NULL;
3442 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3443 __isl_keep isl_vec *vec)
3445 int i;
3446 unsigned total;
3447 isl_int s;
3449 if (!bmap || !vec)
3450 return isl_bool_error;
3452 total = 1 + isl_basic_map_total_dim(bmap);
3453 if (total != vec->size)
3454 return isl_bool_false;
3456 isl_int_init(s);
3458 for (i = 0; i < bmap->n_eq; ++i) {
3459 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3460 if (!isl_int_is_zero(s)) {
3461 isl_int_clear(s);
3462 return isl_bool_false;
3466 for (i = 0; i < bmap->n_ineq; ++i) {
3467 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3468 if (isl_int_is_neg(s)) {
3469 isl_int_clear(s);
3470 return isl_bool_false;
3474 isl_int_clear(s);
3476 return isl_bool_true;
3479 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3480 __isl_keep isl_vec *vec)
3482 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3485 __isl_give isl_basic_map *isl_basic_map_intersect(
3486 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3488 struct isl_vec *sample = NULL;
3489 isl_space *space1, *space2;
3491 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3492 goto error;
3493 space1 = isl_basic_map_peek_space(bmap1);
3494 space2 = isl_basic_map_peek_space(bmap2);
3495 if (isl_space_dim(space1, isl_dim_all) ==
3496 isl_space_dim(space1, isl_dim_param) &&
3497 isl_space_dim(space2, isl_dim_all) !=
3498 isl_space_dim(space2, isl_dim_param))
3499 return isl_basic_map_intersect(bmap2, bmap1);
3501 if (isl_space_dim(space2, isl_dim_all) !=
3502 isl_space_dim(space2, isl_dim_param))
3503 isl_assert(bmap1->ctx,
3504 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3506 if (isl_basic_map_plain_is_empty(bmap1)) {
3507 isl_basic_map_free(bmap2);
3508 return bmap1;
3510 if (isl_basic_map_plain_is_empty(bmap2)) {
3511 isl_basic_map_free(bmap1);
3512 return bmap2;
3515 if (bmap1->sample &&
3516 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3517 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3518 sample = isl_vec_copy(bmap1->sample);
3519 else if (bmap2->sample &&
3520 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3521 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3522 sample = isl_vec_copy(bmap2->sample);
3524 bmap1 = isl_basic_map_cow(bmap1);
3525 if (!bmap1)
3526 goto error;
3527 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3528 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3529 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3531 if (!bmap1)
3532 isl_vec_free(sample);
3533 else if (sample) {
3534 isl_vec_free(bmap1->sample);
3535 bmap1->sample = sample;
3538 bmap1 = isl_basic_map_simplify(bmap1);
3539 return isl_basic_map_finalize(bmap1);
3540 error:
3541 if (sample)
3542 isl_vec_free(sample);
3543 isl_basic_map_free(bmap1);
3544 isl_basic_map_free(bmap2);
3545 return NULL;
3548 struct isl_basic_set *isl_basic_set_intersect(
3549 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3551 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3552 bset_to_bmap(bset2)));
3555 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3556 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3558 return isl_basic_set_intersect(bset1, bset2);
3561 /* Special case of isl_map_intersect, where both map1 and map2
3562 * are convex, without any divs and such that either map1 or map2
3563 * contains a single constraint. This constraint is then simply
3564 * added to the other map.
3566 static __isl_give isl_map *map_intersect_add_constraint(
3567 __isl_take isl_map *map1, __isl_take isl_map *map2)
3569 isl_assert(map1->ctx, map1->n == 1, goto error);
3570 isl_assert(map2->ctx, map1->n == 1, goto error);
3571 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3572 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3574 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3575 return isl_map_intersect(map2, map1);
3577 map1 = isl_map_cow(map1);
3578 if (!map1)
3579 goto error;
3580 if (isl_map_plain_is_empty(map1)) {
3581 isl_map_free(map2);
3582 return map1;
3584 if (map2->p[0]->n_eq == 1)
3585 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3586 else
3587 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3588 map2->p[0]->ineq[0]);
3590 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3591 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3592 if (!map1->p[0])
3593 goto error;
3595 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3596 isl_basic_map_free(map1->p[0]);
3597 map1->n = 0;
3600 isl_map_free(map2);
3602 map1 = isl_map_unmark_normalized(map1);
3603 return map1;
3604 error:
3605 isl_map_free(map1);
3606 isl_map_free(map2);
3607 return NULL;
3610 /* map2 may be either a parameter domain or a map living in the same
3611 * space as map1.
3613 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3614 __isl_take isl_map *map2)
3616 unsigned flags = 0;
3617 isl_bool equal;
3618 isl_map *result;
3619 int i, j;
3621 if (!map1 || !map2)
3622 goto error;
3624 if ((isl_map_plain_is_empty(map1) ||
3625 isl_map_plain_is_universe(map2)) &&
3626 isl_space_is_equal(map1->dim, map2->dim)) {
3627 isl_map_free(map2);
3628 return map1;
3630 if ((isl_map_plain_is_empty(map2) ||
3631 isl_map_plain_is_universe(map1)) &&
3632 isl_space_is_equal(map1->dim, map2->dim)) {
3633 isl_map_free(map1);
3634 return map2;
3637 if (map1->n == 1 && map2->n == 1 &&
3638 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3639 isl_space_is_equal(map1->dim, map2->dim) &&
3640 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3641 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3642 return map_intersect_add_constraint(map1, map2);
3644 equal = isl_map_plain_is_equal(map1, map2);
3645 if (equal < 0)
3646 goto error;
3647 if (equal) {
3648 isl_map_free(map2);
3649 return map1;
3652 if (isl_map_dim(map2, isl_dim_all) != isl_map_dim(map2, isl_dim_param))
3653 isl_assert(map1->ctx,
3654 isl_space_is_equal(map1->dim, map2->dim), goto error);
3656 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3657 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3658 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3660 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3661 map1->n * map2->n, flags);
3662 if (!result)
3663 goto error;
3664 for (i = 0; i < map1->n; ++i)
3665 for (j = 0; j < map2->n; ++j) {
3666 struct isl_basic_map *part;
3667 part = isl_basic_map_intersect(
3668 isl_basic_map_copy(map1->p[i]),
3669 isl_basic_map_copy(map2->p[j]));
3670 if (isl_basic_map_is_empty(part) < 0)
3671 part = isl_basic_map_free(part);
3672 result = isl_map_add_basic_map(result, part);
3673 if (!result)
3674 goto error;
3676 isl_map_free(map1);
3677 isl_map_free(map2);
3678 return result;
3679 error:
3680 isl_map_free(map1);
3681 isl_map_free(map2);
3682 return NULL;
3685 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3686 __isl_take isl_map *map2)
3688 if (!map1 || !map2)
3689 goto error;
3690 if (!isl_space_is_equal(map1->dim, map2->dim))
3691 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3692 "spaces don't match", goto error);
3693 return map_intersect_internal(map1, map2);
3694 error:
3695 isl_map_free(map1);
3696 isl_map_free(map2);
3697 return NULL;
3700 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3701 __isl_take isl_map *map2)
3703 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3706 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3708 return set_from_map(isl_map_intersect(set_to_map(set1),
3709 set_to_map(set2)));
3712 /* map_intersect_internal accepts intersections
3713 * with parameter domains, so we can just call that function.
3715 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3716 __isl_take isl_set *params)
3718 return map_intersect_internal(map, params);
3721 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3722 __isl_take isl_map *map2)
3724 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3727 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3728 __isl_take isl_set *params)
3730 return isl_map_intersect_params(set, params);
3733 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3735 isl_space *space;
3736 unsigned pos, n1, n2;
3738 if (!bmap)
3739 return NULL;
3740 bmap = isl_basic_map_cow(bmap);
3741 if (!bmap)
3742 return NULL;
3743 space = isl_space_reverse(isl_space_copy(bmap->dim));
3744 pos = isl_basic_map_offset(bmap, isl_dim_in);
3745 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3746 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3747 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3748 return isl_basic_map_reset_space(bmap, space);
3751 static __isl_give isl_basic_map *basic_map_space_reset(
3752 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3754 isl_space *space;
3756 if (!bmap)
3757 return NULL;
3758 if (!isl_space_is_named_or_nested(bmap->dim, type))
3759 return bmap;
3761 space = isl_basic_map_get_space(bmap);
3762 space = isl_space_reset(space, type);
3763 bmap = isl_basic_map_reset_space(bmap, space);
3764 return bmap;
3767 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3768 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3769 unsigned pos, unsigned n)
3771 isl_bool rational, is_empty;
3772 isl_space *res_space;
3773 struct isl_basic_map *res;
3774 struct isl_dim_map *dim_map;
3775 unsigned total, off;
3776 enum isl_dim_type t;
3778 if (n == 0)
3779 return basic_map_space_reset(bmap, type);
3781 is_empty = isl_basic_map_plain_is_empty(bmap);
3782 if (is_empty < 0)
3783 return isl_basic_map_free(bmap);
3784 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3785 type, pos, n);
3786 if (!res_space)
3787 return isl_basic_map_free(bmap);
3788 if (is_empty) {
3789 isl_basic_map_free(bmap);
3790 return isl_basic_map_empty(res_space);
3793 total = isl_basic_map_total_dim(bmap) + n;
3794 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3795 off = 0;
3796 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3797 if (t != type) {
3798 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3799 } else {
3800 unsigned size = isl_basic_map_dim(bmap, t);
3801 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3802 0, pos, off);
3803 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3804 pos, size - pos, off + pos + n);
3806 off += isl_space_dim(res_space, t);
3808 isl_dim_map_div(dim_map, bmap, off);
3810 res = isl_basic_map_alloc_space(res_space,
3811 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3812 rational = isl_basic_map_is_rational(bmap);
3813 if (rational < 0)
3814 res = isl_basic_map_free(res);
3815 if (rational)
3816 res = isl_basic_map_set_rational(res);
3817 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3818 return isl_basic_map_finalize(res);
3821 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3822 __isl_take isl_basic_set *bset,
3823 enum isl_dim_type type, unsigned pos, unsigned n)
3825 return isl_basic_map_insert_dims(bset, type, pos, n);
3828 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3829 enum isl_dim_type type, unsigned n)
3831 if (!bmap)
3832 return NULL;
3833 return isl_basic_map_insert_dims(bmap, type,
3834 isl_basic_map_dim(bmap, type), n);
3837 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3838 enum isl_dim_type type, unsigned n)
3840 if (!bset)
3841 return NULL;
3842 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3843 return isl_basic_map_add_dims(bset, type, n);
3844 error:
3845 isl_basic_set_free(bset);
3846 return NULL;
3849 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3850 enum isl_dim_type type)
3852 isl_space *space;
3854 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3855 return map;
3857 space = isl_map_get_space(map);
3858 space = isl_space_reset(space, type);
3859 map = isl_map_reset_space(map, space);
3860 return map;
3863 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3864 enum isl_dim_type type, unsigned pos, unsigned n)
3866 int i;
3868 if (n == 0)
3869 return map_space_reset(map, type);
3871 map = isl_map_cow(map);
3872 if (!map)
3873 return NULL;
3875 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3876 if (!map->dim)
3877 goto error;
3879 for (i = 0; i < map->n; ++i) {
3880 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3881 if (!map->p[i])
3882 goto error;
3885 return map;
3886 error:
3887 isl_map_free(map);
3888 return NULL;
3891 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3892 enum isl_dim_type type, unsigned pos, unsigned n)
3894 return isl_map_insert_dims(set, type, pos, n);
3897 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3898 enum isl_dim_type type, unsigned n)
3900 if (!map)
3901 return NULL;
3902 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3905 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3906 enum isl_dim_type type, unsigned n)
3908 if (!set)
3909 return NULL;
3910 isl_assert(set->ctx, type != isl_dim_in, goto error);
3911 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
3912 error:
3913 isl_set_free(set);
3914 return NULL;
3917 __isl_give isl_basic_map *isl_basic_map_move_dims(
3918 __isl_take isl_basic_map *bmap,
3919 enum isl_dim_type dst_type, unsigned dst_pos,
3920 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3922 isl_space *space;
3923 struct isl_dim_map *dim_map;
3924 struct isl_basic_map *res;
3925 enum isl_dim_type t;
3926 unsigned total, off;
3928 if (!bmap)
3929 return NULL;
3930 if (n == 0) {
3931 bmap = isl_basic_map_reset(bmap, src_type);
3932 bmap = isl_basic_map_reset(bmap, dst_type);
3933 return bmap;
3936 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
3937 return isl_basic_map_free(bmap);
3939 if (dst_type == src_type && dst_pos == src_pos)
3940 return bmap;
3942 isl_assert(bmap->ctx, dst_type != src_type, goto error);
3944 if (pos(bmap->dim, dst_type) + dst_pos ==
3945 pos(bmap->dim, src_type) + src_pos +
3946 ((src_type < dst_type) ? n : 0)) {
3947 bmap = isl_basic_map_cow(bmap);
3948 if (!bmap)
3949 return NULL;
3951 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3952 src_type, src_pos, n);
3953 if (!bmap->dim)
3954 goto error;
3956 bmap = isl_basic_map_finalize(bmap);
3958 return bmap;
3961 total = isl_basic_map_total_dim(bmap);
3962 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3964 off = 0;
3965 space = isl_basic_map_peek_space(bmap);
3966 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3967 unsigned size = isl_space_dim(space, t);
3968 if (t == dst_type) {
3969 isl_dim_map_dim_range(dim_map, space, t,
3970 0, dst_pos, off);
3971 off += dst_pos;
3972 isl_dim_map_dim_range(dim_map, space, src_type,
3973 src_pos, n, off);
3974 off += n;
3975 isl_dim_map_dim_range(dim_map, space, t,
3976 dst_pos, size - dst_pos, off);
3977 off += size - dst_pos;
3978 } else if (t == src_type) {
3979 isl_dim_map_dim_range(dim_map, space, t,
3980 0, src_pos, off);
3981 off += src_pos;
3982 isl_dim_map_dim_range(dim_map, space, t,
3983 src_pos + n, size - src_pos - n, off);
3984 off += size - src_pos - n;
3985 } else {
3986 isl_dim_map_dim(dim_map, space, t, off);
3987 off += size;
3990 isl_dim_map_div(dim_map, bmap, off);
3992 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3993 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3994 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3995 if (!bmap)
3996 goto error;
3998 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3999 src_type, src_pos, n);
4000 if (!bmap->dim)
4001 goto error;
4003 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4004 bmap = isl_basic_map_gauss(bmap, NULL);
4005 bmap = isl_basic_map_finalize(bmap);
4007 return bmap;
4008 error:
4009 isl_basic_map_free(bmap);
4010 return NULL;
4013 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4014 enum isl_dim_type dst_type, unsigned dst_pos,
4015 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4017 isl_basic_map *bmap = bset_to_bmap(bset);
4018 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4019 src_type, src_pos, n);
4020 return bset_from_bmap(bmap);
4023 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4024 enum isl_dim_type dst_type, unsigned dst_pos,
4025 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4027 if (!set)
4028 return NULL;
4029 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4030 return set_from_map(isl_map_move_dims(set_to_map(set),
4031 dst_type, dst_pos, src_type, src_pos, n));
4032 error:
4033 isl_set_free(set);
4034 return NULL;
4037 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4038 enum isl_dim_type dst_type, unsigned dst_pos,
4039 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4041 int i;
4043 if (n == 0) {
4044 map = isl_map_reset(map, src_type);
4045 map = isl_map_reset(map, dst_type);
4046 return map;
4049 if (isl_map_check_range(map, src_type, src_pos, n))
4050 return isl_map_free(map);
4052 if (dst_type == src_type && dst_pos == src_pos)
4053 return map;
4055 isl_assert(map->ctx, dst_type != src_type, goto error);
4057 map = isl_map_cow(map);
4058 if (!map)
4059 return NULL;
4061 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
4062 if (!map->dim)
4063 goto error;
4065 for (i = 0; i < map->n; ++i) {
4066 map->p[i] = isl_basic_map_move_dims(map->p[i],
4067 dst_type, dst_pos,
4068 src_type, src_pos, n);
4069 if (!map->p[i])
4070 goto error;
4073 return map;
4074 error:
4075 isl_map_free(map);
4076 return NULL;
4079 /* Move the specified dimensions to the last columns right before
4080 * the divs. Don't change the dimension specification of bmap.
4081 * That's the responsibility of the caller.
4083 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4084 enum isl_dim_type type, unsigned first, unsigned n)
4086 isl_space *space;
4087 struct isl_dim_map *dim_map;
4088 struct isl_basic_map *res;
4089 enum isl_dim_type t;
4090 unsigned total, off;
4092 if (!bmap)
4093 return NULL;
4094 if (isl_basic_map_offset(bmap, type) + first + n ==
4095 isl_basic_map_offset(bmap, isl_dim_div))
4096 return bmap;
4098 total = isl_basic_map_total_dim(bmap);
4099 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4101 off = 0;
4102 space = isl_basic_map_peek_space(bmap);
4103 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4104 unsigned size = isl_space_dim(space, t);
4105 if (t == type) {
4106 isl_dim_map_dim_range(dim_map, space, t,
4107 0, first, off);
4108 off += first;
4109 isl_dim_map_dim_range(dim_map, space, t,
4110 first, n, total - bmap->n_div - n);
4111 isl_dim_map_dim_range(dim_map, space, t,
4112 first + n, size - (first + n), off);
4113 off += size - (first + n);
4114 } else {
4115 isl_dim_map_dim(dim_map, space, t, off);
4116 off += size;
4119 isl_dim_map_div(dim_map, bmap, off + n);
4121 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4122 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4123 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4124 return res;
4127 /* Insert "n" rows in the divs of "bmap".
4129 * The number of columns is not changed, which means that the last
4130 * dimensions of "bmap" are being reintepreted as the new divs.
4131 * The space of "bmap" is not adjusted, however, which means
4132 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4133 * from the space of "bmap" is the responsibility of the caller.
4135 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4136 int n)
4138 int i;
4139 size_t row_size;
4140 isl_int **new_div;
4141 isl_int *old;
4143 bmap = isl_basic_map_cow(bmap);
4144 if (!bmap)
4145 return NULL;
4147 row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;
4148 old = bmap->block2.data;
4149 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4150 (bmap->extra + n) * (1 + row_size));
4151 if (!bmap->block2.data)
4152 return isl_basic_map_free(bmap);
4153 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4154 if (!new_div)
4155 return isl_basic_map_free(bmap);
4156 for (i = 0; i < n; ++i) {
4157 new_div[i] = bmap->block2.data +
4158 (bmap->extra + i) * (1 + row_size);
4159 isl_seq_clr(new_div[i], 1 + row_size);
4161 for (i = 0; i < bmap->extra; ++i)
4162 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4163 free(bmap->div);
4164 bmap->div = new_div;
4165 bmap->n_div += n;
4166 bmap->extra += n;
4168 return bmap;
4171 /* Drop constraints from "bmap" that only involve the variables
4172 * of "type" in the range [first, first + n] that are not related
4173 * to any of the variables outside that interval.
4174 * These constraints cannot influence the values for the variables
4175 * outside the interval, except in case they cause "bmap" to be empty.
4176 * Only drop the constraints if "bmap" is known to be non-empty.
4178 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4179 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4180 unsigned first, unsigned n)
4182 int i;
4183 int *groups;
4184 unsigned dim, n_div;
4185 isl_bool non_empty;
4187 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4188 if (non_empty < 0)
4189 return isl_basic_map_free(bmap);
4190 if (!non_empty)
4191 return bmap;
4193 dim = isl_basic_map_dim(bmap, isl_dim_all);
4194 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4195 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4196 if (!groups)
4197 return isl_basic_map_free(bmap);
4198 first += isl_basic_map_offset(bmap, type) - 1;
4199 for (i = 0; i < first; ++i)
4200 groups[i] = -1;
4201 for (i = first + n; i < dim - n_div; ++i)
4202 groups[i] = -1;
4204 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4206 return bmap;
4209 /* Turn the n dimensions of type type, starting at first
4210 * into existentially quantified variables.
4212 * If a subset of the projected out variables are unrelated
4213 * to any of the variables that remain, then the constraints
4214 * involving this subset are simply dropped first.
4216 __isl_give isl_basic_map *isl_basic_map_project_out(
4217 __isl_take isl_basic_map *bmap,
4218 enum isl_dim_type type, unsigned first, unsigned n)
4220 isl_bool empty;
4222 if (n == 0)
4223 return basic_map_space_reset(bmap, type);
4224 if (type == isl_dim_div)
4225 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4226 "cannot project out existentially quantified variables",
4227 return isl_basic_map_free(bmap));
4229 empty = isl_basic_map_plain_is_empty(bmap);
4230 if (empty < 0)
4231 return isl_basic_map_free(bmap);
4232 if (empty)
4233 bmap = isl_basic_map_set_to_empty(bmap);
4235 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4236 if (!bmap)
4237 return NULL;
4239 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4240 return isl_basic_map_remove_dims(bmap, type, first, n);
4242 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4243 return isl_basic_map_free(bmap);
4245 bmap = move_last(bmap, type, first, n);
4246 bmap = isl_basic_map_cow(bmap);
4247 bmap = insert_div_rows(bmap, n);
4248 if (!bmap)
4249 return NULL;
4251 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
4252 if (!bmap->dim)
4253 goto error;
4254 bmap = isl_basic_map_simplify(bmap);
4255 bmap = isl_basic_map_drop_redundant_divs(bmap);
4256 return isl_basic_map_finalize(bmap);
4257 error:
4258 isl_basic_map_free(bmap);
4259 return NULL;
4262 /* Turn the n dimensions of type type, starting at first
4263 * into existentially quantified variables.
4265 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
4266 enum isl_dim_type type, unsigned first, unsigned n)
4268 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4269 type, first, n));
4272 /* Turn the n dimensions of type type, starting at first
4273 * into existentially quantified variables.
4275 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4276 enum isl_dim_type type, unsigned first, unsigned n)
4278 int i;
4280 if (n == 0)
4281 return map_space_reset(map, type);
4283 if (isl_map_check_range(map, type, first, n) < 0)
4284 return isl_map_free(map);
4286 map = isl_map_cow(map);
4287 if (!map)
4288 return NULL;
4290 map->dim = isl_space_drop_dims(map->dim, type, first, n);
4291 if (!map->dim)
4292 goto error;
4294 for (i = 0; i < map->n; ++i) {
4295 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4296 if (!map->p[i])
4297 goto error;
4300 return map;
4301 error:
4302 isl_map_free(map);
4303 return NULL;
4306 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4307 * into existentially quantified variables.
4309 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4310 enum isl_dim_type type, unsigned first, unsigned n)
4312 unsigned dim;
4314 if (isl_map_check_range(map, type, first, n) < 0)
4315 return isl_map_free(map);
4316 dim = isl_map_dim(map, type);
4317 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4318 map = isl_map_project_out(map, type, 0, first);
4319 return map;
4322 /* Turn the n dimensions of type type, starting at first
4323 * into existentially quantified variables.
4325 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4326 enum isl_dim_type type, unsigned first, unsigned n)
4328 return set_from_map(isl_map_project_out(set_to_map(set),
4329 type, first, n));
4332 /* Return a map that projects the elements in "set" onto their
4333 * "n" set dimensions starting at "first".
4334 * "type" should be equal to isl_dim_set.
4336 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4337 enum isl_dim_type type, unsigned first, unsigned n)
4339 int i;
4340 isl_map *map;
4342 if (type != isl_dim_set)
4343 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4344 "only set dimensions can be projected out", goto error);
4345 if (isl_set_check_range(set, type, first, n) < 0)
4346 return isl_set_free(set);
4348 map = isl_map_from_domain(set);
4349 map = isl_map_add_dims(map, isl_dim_out, n);
4350 for (i = 0; i < n; ++i)
4351 map = isl_map_equate(map, isl_dim_in, first + i,
4352 isl_dim_out, i);
4353 return map;
4354 error:
4355 isl_set_free(set);
4356 return NULL;
4359 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4360 unsigned n)
4362 int i, j;
4364 for (i = 0; i < n; ++i) {
4365 j = isl_basic_map_alloc_div(bmap);
4366 if (j < 0)
4367 goto error;
4368 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4370 return bmap;
4371 error:
4372 isl_basic_map_free(bmap);
4373 return NULL;
4376 struct isl_basic_map *isl_basic_map_apply_range(
4377 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4379 isl_space *space_result = NULL;
4380 struct isl_basic_map *bmap;
4381 unsigned n_in, n_out, n, nparam, total, pos;
4382 struct isl_dim_map *dim_map1, *dim_map2;
4384 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4385 goto error;
4386 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4387 bmap2->dim, isl_dim_in))
4388 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4389 "spaces don't match", goto error);
4391 space_result = isl_space_join(isl_basic_map_get_space(bmap1),
4392 isl_basic_map_get_space(bmap2));
4394 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4395 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4396 n = isl_basic_map_dim(bmap1, isl_dim_out);
4397 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4399 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4400 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4401 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4402 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4403 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4404 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4405 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4406 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4407 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4408 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4409 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4411 bmap = isl_basic_map_alloc_space(space_result,
4412 bmap1->n_div + bmap2->n_div + n,
4413 bmap1->n_eq + bmap2->n_eq,
4414 bmap1->n_ineq + bmap2->n_ineq);
4415 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4416 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4417 bmap = add_divs(bmap, n);
4418 bmap = isl_basic_map_simplify(bmap);
4419 bmap = isl_basic_map_drop_redundant_divs(bmap);
4420 return isl_basic_map_finalize(bmap);
4421 error:
4422 isl_basic_map_free(bmap1);
4423 isl_basic_map_free(bmap2);
4424 return NULL;
4427 struct isl_basic_set *isl_basic_set_apply(
4428 struct isl_basic_set *bset, struct isl_basic_map *bmap)
4430 if (!bset || !bmap)
4431 goto error;
4433 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4434 goto error);
4436 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4437 bmap));
4438 error:
4439 isl_basic_set_free(bset);
4440 isl_basic_map_free(bmap);
4441 return NULL;
4444 struct isl_basic_map *isl_basic_map_apply_domain(
4445 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4447 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4448 goto error;
4449 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4450 bmap2->dim, isl_dim_in))
4451 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4452 "spaces don't match", goto error);
4454 bmap1 = isl_basic_map_reverse(bmap1);
4455 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4456 return isl_basic_map_reverse(bmap1);
4457 error:
4458 isl_basic_map_free(bmap1);
4459 isl_basic_map_free(bmap2);
4460 return NULL;
4463 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4464 * A \cap B -> f(A) + f(B)
4466 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4467 __isl_take isl_basic_map *bmap2)
4469 unsigned n_in, n_out, nparam, total, pos;
4470 struct isl_basic_map *bmap = NULL;
4471 struct isl_dim_map *dim_map1, *dim_map2;
4472 int i;
4474 if (!bmap1 || !bmap2)
4475 goto error;
4477 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4478 goto error);
4480 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4481 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4482 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4484 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4485 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4486 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4487 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4488 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4489 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4490 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4491 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4492 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4493 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4494 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4496 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4497 bmap1->n_div + bmap2->n_div + 2 * n_out,
4498 bmap1->n_eq + bmap2->n_eq + n_out,
4499 bmap1->n_ineq + bmap2->n_ineq);
4500 for (i = 0; i < n_out; ++i) {
4501 int j = isl_basic_map_alloc_equality(bmap);
4502 if (j < 0)
4503 goto error;
4504 isl_seq_clr(bmap->eq[j], 1+total);
4505 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4506 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4507 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4509 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4510 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4511 bmap = add_divs(bmap, 2 * n_out);
4513 bmap = isl_basic_map_simplify(bmap);
4514 return isl_basic_map_finalize(bmap);
4515 error:
4516 isl_basic_map_free(bmap);
4517 isl_basic_map_free(bmap1);
4518 isl_basic_map_free(bmap2);
4519 return NULL;
4522 /* Given two maps A -> f(A) and B -> g(B), construct a map
4523 * A \cap B -> f(A) + f(B)
4525 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4526 __isl_take isl_map *map2)
4528 struct isl_map *result;
4529 int i, j;
4531 if (!map1 || !map2)
4532 goto error;
4534 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4536 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4537 map1->n * map2->n, 0);
4538 if (!result)
4539 goto error;
4540 for (i = 0; i < map1->n; ++i)
4541 for (j = 0; j < map2->n; ++j) {
4542 struct isl_basic_map *part;
4543 part = isl_basic_map_sum(
4544 isl_basic_map_copy(map1->p[i]),
4545 isl_basic_map_copy(map2->p[j]));
4546 if (isl_basic_map_is_empty(part))
4547 isl_basic_map_free(part);
4548 else
4549 result = isl_map_add_basic_map(result, part);
4550 if (!result)
4551 goto error;
4553 isl_map_free(map1);
4554 isl_map_free(map2);
4555 return result;
4556 error:
4557 isl_map_free(map1);
4558 isl_map_free(map2);
4559 return NULL;
4562 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4563 __isl_take isl_set *set2)
4565 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4568 /* Given a basic map A -> f(A), construct A -> -f(A).
4570 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4572 int i, j;
4573 unsigned off, n;
4575 bmap = isl_basic_map_cow(bmap);
4576 if (!bmap)
4577 return NULL;
4579 n = isl_basic_map_dim(bmap, isl_dim_out);
4580 off = isl_basic_map_offset(bmap, isl_dim_out);
4581 for (i = 0; i < bmap->n_eq; ++i)
4582 for (j = 0; j < n; ++j)
4583 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4584 for (i = 0; i < bmap->n_ineq; ++i)
4585 for (j = 0; j < n; ++j)
4586 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4587 for (i = 0; i < bmap->n_div; ++i)
4588 for (j = 0; j < n; ++j)
4589 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4590 bmap = isl_basic_map_gauss(bmap, NULL);
4591 return isl_basic_map_finalize(bmap);
4594 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4596 return isl_basic_map_neg(bset);
4599 /* Given a map A -> f(A), construct A -> -f(A).
4601 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4603 int i;
4605 map = isl_map_cow(map);
4606 if (!map)
4607 return NULL;
4609 for (i = 0; i < map->n; ++i) {
4610 map->p[i] = isl_basic_map_neg(map->p[i]);
4611 if (!map->p[i])
4612 goto error;
4615 return map;
4616 error:
4617 isl_map_free(map);
4618 return NULL;
4621 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4623 return set_from_map(isl_map_neg(set_to_map(set)));
4626 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4627 * A -> floor(f(A)/d).
4629 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4630 isl_int d)
4632 unsigned n_in, n_out, nparam, total, pos;
4633 struct isl_basic_map *result = NULL;
4634 struct isl_dim_map *dim_map;
4635 int i;
4637 if (!bmap)
4638 return NULL;
4640 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4641 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4642 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4644 total = nparam + n_in + n_out + bmap->n_div + n_out;
4645 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4646 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4647 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4648 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4649 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4651 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4652 bmap->n_div + n_out,
4653 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4654 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4655 result = add_divs(result, n_out);
4656 for (i = 0; i < n_out; ++i) {
4657 int j;
4658 j = isl_basic_map_alloc_inequality(result);
4659 if (j < 0)
4660 goto error;
4661 isl_seq_clr(result->ineq[j], 1+total);
4662 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4663 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4664 j = isl_basic_map_alloc_inequality(result);
4665 if (j < 0)
4666 goto error;
4667 isl_seq_clr(result->ineq[j], 1+total);
4668 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4669 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4670 isl_int_sub_ui(result->ineq[j][0], d, 1);
4673 result = isl_basic_map_simplify(result);
4674 return isl_basic_map_finalize(result);
4675 error:
4676 isl_basic_map_free(result);
4677 return NULL;
4680 /* Given a map A -> f(A) and an integer d, construct a map
4681 * A -> floor(f(A)/d).
4683 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4685 int i;
4687 map = isl_map_cow(map);
4688 if (!map)
4689 return NULL;
4691 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4692 for (i = 0; i < map->n; ++i) {
4693 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4694 if (!map->p[i])
4695 goto error;
4697 map = isl_map_unmark_normalized(map);
4699 return map;
4700 error:
4701 isl_map_free(map);
4702 return NULL;
4705 /* Given a map A -> f(A) and an integer d, construct a map
4706 * A -> floor(f(A)/d).
4708 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4709 __isl_take isl_val *d)
4711 if (!map || !d)
4712 goto error;
4713 if (!isl_val_is_int(d))
4714 isl_die(isl_val_get_ctx(d), isl_error_invalid,
4715 "expecting integer denominator", goto error);
4716 map = isl_map_floordiv(map, d->n);
4717 isl_val_free(d);
4718 return map;
4719 error:
4720 isl_map_free(map);
4721 isl_val_free(d);
4722 return NULL;
4725 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
4726 unsigned pos)
4728 int i;
4729 unsigned nparam;
4730 unsigned n_in;
4732 i = isl_basic_map_alloc_equality(bmap);
4733 if (i < 0)
4734 goto error;
4735 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4736 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4737 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4738 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4739 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4740 return isl_basic_map_finalize(bmap);
4741 error:
4742 isl_basic_map_free(bmap);
4743 return NULL;
4746 /* Add a constraint to "bmap" expressing i_pos < o_pos
4748 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
4749 unsigned pos)
4751 int i;
4752 unsigned nparam;
4753 unsigned n_in;
4755 i = isl_basic_map_alloc_inequality(bmap);
4756 if (i < 0)
4757 goto error;
4758 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4759 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4760 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4761 isl_int_set_si(bmap->ineq[i][0], -1);
4762 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4763 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4764 return isl_basic_map_finalize(bmap);
4765 error:
4766 isl_basic_map_free(bmap);
4767 return NULL;
4770 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4772 static __isl_give isl_basic_map *var_less_or_equal(
4773 __isl_take isl_basic_map *bmap, unsigned pos)
4775 int i;
4776 unsigned nparam;
4777 unsigned n_in;
4779 i = isl_basic_map_alloc_inequality(bmap);
4780 if (i < 0)
4781 goto error;
4782 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4783 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4784 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4785 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4786 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4787 return isl_basic_map_finalize(bmap);
4788 error:
4789 isl_basic_map_free(bmap);
4790 return NULL;
4793 /* Add a constraint to "bmap" expressing i_pos > o_pos
4795 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
4796 unsigned pos)
4798 int i;
4799 unsigned nparam;
4800 unsigned n_in;
4802 i = isl_basic_map_alloc_inequality(bmap);
4803 if (i < 0)
4804 goto error;
4805 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4806 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4807 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4808 isl_int_set_si(bmap->ineq[i][0], -1);
4809 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4810 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4811 return isl_basic_map_finalize(bmap);
4812 error:
4813 isl_basic_map_free(bmap);
4814 return NULL;
4817 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4819 static __isl_give isl_basic_map *var_more_or_equal(
4820 __isl_take isl_basic_map *bmap, unsigned pos)
4822 int i;
4823 unsigned nparam;
4824 unsigned n_in;
4826 i = isl_basic_map_alloc_inequality(bmap);
4827 if (i < 0)
4828 goto error;
4829 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4830 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4831 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4832 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4833 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4834 return isl_basic_map_finalize(bmap);
4835 error:
4836 isl_basic_map_free(bmap);
4837 return NULL;
4840 __isl_give isl_basic_map *isl_basic_map_equal(
4841 __isl_take isl_space *space, unsigned n_equal)
4843 int i;
4844 struct isl_basic_map *bmap;
4845 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
4846 if (!bmap)
4847 return NULL;
4848 for (i = 0; i < n_equal && bmap; ++i)
4849 bmap = var_equal(bmap, i);
4850 return isl_basic_map_finalize(bmap);
4853 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
4855 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
4856 unsigned pos)
4858 int i;
4859 struct isl_basic_map *bmap;
4860 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4861 if (!bmap)
4862 return NULL;
4863 for (i = 0; i < pos && bmap; ++i)
4864 bmap = var_equal(bmap, i);
4865 if (bmap)
4866 bmap = var_less(bmap, pos);
4867 return isl_basic_map_finalize(bmap);
4870 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
4872 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4873 __isl_take isl_space *space, unsigned pos)
4875 int i;
4876 isl_basic_map *bmap;
4878 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4879 for (i = 0; i < pos; ++i)
4880 bmap = var_equal(bmap, i);
4881 bmap = var_less_or_equal(bmap, pos);
4882 return isl_basic_map_finalize(bmap);
4885 /* Return a relation on "space" expressing i_pos > o_pos
4887 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
4888 unsigned pos)
4890 int i;
4891 struct isl_basic_map *bmap;
4892 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4893 if (!bmap)
4894 return NULL;
4895 for (i = 0; i < pos && bmap; ++i)
4896 bmap = var_equal(bmap, i);
4897 if (bmap)
4898 bmap = var_more(bmap, pos);
4899 return isl_basic_map_finalize(bmap);
4902 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
4904 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4905 __isl_take isl_space *space, unsigned pos)
4907 int i;
4908 isl_basic_map *bmap;
4910 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4911 for (i = 0; i < pos; ++i)
4912 bmap = var_equal(bmap, i);
4913 bmap = var_more_or_equal(bmap, pos);
4914 return isl_basic_map_finalize(bmap);
4917 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
4918 unsigned n, int equal)
4920 struct isl_map *map;
4921 int i;
4923 if (n == 0 && equal)
4924 return isl_map_universe(space);
4926 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
4928 for (i = 0; i + 1 < n; ++i)
4929 map = isl_map_add_basic_map(map,
4930 isl_basic_map_less_at(isl_space_copy(space), i));
4931 if (n > 0) {
4932 if (equal)
4933 map = isl_map_add_basic_map(map,
4934 isl_basic_map_less_or_equal_at(space, n - 1));
4935 else
4936 map = isl_map_add_basic_map(map,
4937 isl_basic_map_less_at(space, n - 1));
4938 } else
4939 isl_space_free(space);
4941 return map;
4944 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
4946 if (!space)
4947 return NULL;
4948 return map_lex_lte_first(space, space->n_out, equal);
4951 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
4953 return map_lex_lte_first(dim, n, 0);
4956 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
4958 return map_lex_lte_first(dim, n, 1);
4961 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
4963 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
4966 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
4968 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
4971 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
4972 unsigned n, int equal)
4974 struct isl_map *map;
4975 int i;
4977 if (n == 0 && equal)
4978 return isl_map_universe(space);
4980 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
4982 for (i = 0; i + 1 < n; ++i)
4983 map = isl_map_add_basic_map(map,
4984 isl_basic_map_more_at(isl_space_copy(space), i));
4985 if (n > 0) {
4986 if (equal)
4987 map = isl_map_add_basic_map(map,
4988 isl_basic_map_more_or_equal_at(space, n - 1));
4989 else
4990 map = isl_map_add_basic_map(map,
4991 isl_basic_map_more_at(space, n - 1));
4992 } else
4993 isl_space_free(space);
4995 return map;
4998 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5000 if (!space)
5001 return NULL;
5002 return map_lex_gte_first(space, space->n_out, equal);
5005 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
5007 return map_lex_gte_first(dim, n, 0);
5010 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
5012 return map_lex_gte_first(dim, n, 1);
5015 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
5017 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
5020 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
5022 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
5025 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5026 __isl_take isl_set *set2)
5028 isl_map *map;
5029 map = isl_map_lex_le(isl_set_get_space(set1));
5030 map = isl_map_intersect_domain(map, set1);
5031 map = isl_map_intersect_range(map, set2);
5032 return map;
5035 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5036 __isl_take isl_set *set2)
5038 isl_map *map;
5039 map = isl_map_lex_lt(isl_set_get_space(set1));
5040 map = isl_map_intersect_domain(map, set1);
5041 map = isl_map_intersect_range(map, set2);
5042 return map;
5045 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5046 __isl_take isl_set *set2)
5048 isl_map *map;
5049 map = isl_map_lex_ge(isl_set_get_space(set1));
5050 map = isl_map_intersect_domain(map, set1);
5051 map = isl_map_intersect_range(map, set2);
5052 return map;
5055 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5056 __isl_take isl_set *set2)
5058 isl_map *map;
5059 map = isl_map_lex_gt(isl_set_get_space(set1));
5060 map = isl_map_intersect_domain(map, set1);
5061 map = isl_map_intersect_range(map, set2);
5062 return map;
5065 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5066 __isl_take isl_map *map2)
5068 isl_map *map;
5069 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5070 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5071 map = isl_map_apply_range(map, isl_map_reverse(map2));
5072 return map;
5075 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5076 __isl_take isl_map *map2)
5078 isl_map *map;
5079 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5080 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5081 map = isl_map_apply_range(map, isl_map_reverse(map2));
5082 return map;
5085 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5086 __isl_take isl_map *map2)
5088 isl_map *map;
5089 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5090 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5091 map = isl_map_apply_range(map, isl_map_reverse(map2));
5092 return map;
5095 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5096 __isl_take isl_map *map2)
5098 isl_map *map;
5099 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5100 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5101 map = isl_map_apply_range(map, isl_map_reverse(map2));
5102 return map;
5105 /* For the div d = floor(f/m) at position "div", add the constraint
5107 * f - m d >= 0
5109 static __isl_give isl_basic_map *add_upper_div_constraint(
5110 __isl_take isl_basic_map *bmap, unsigned div)
5112 int i;
5113 int v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5114 unsigned n_div, pos;
5116 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5117 if (v_div < 0)
5118 return isl_basic_map_free(bmap);
5119 pos = v_div + div;
5120 i = isl_basic_map_alloc_inequality(bmap);
5121 if (i < 0)
5122 return isl_basic_map_free(bmap);
5123 isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5124 isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5126 return bmap;
5129 /* For the div d = floor(f/m) at position "div", add the constraint
5131 * -(f-(m-1)) + m d >= 0
5133 static __isl_give isl_basic_map *add_lower_div_constraint(
5134 __isl_take isl_basic_map *bmap, unsigned div)
5136 int i;
5137 int v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5138 unsigned n_div, pos;
5140 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5141 if (v_div < 0)
5142 return isl_basic_map_free(bmap);
5143 pos = v_div + div;
5144 i = isl_basic_map_alloc_inequality(bmap);
5145 if (i < 0)
5146 return isl_basic_map_free(bmap);
5147 isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5148 isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5149 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5150 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5152 return bmap;
5155 /* For the div d = floor(f/m) at position "pos", add the constraints
5157 * f - m d >= 0
5158 * -(f-(m-1)) + m d >= 0
5160 * Note that the second constraint is the negation of
5162 * f - m d >= m
5164 __isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5165 __isl_take isl_basic_map *bmap, unsigned pos)
5167 bmap = add_upper_div_constraint(bmap, pos);
5168 bmap = add_lower_div_constraint(bmap, pos);
5169 return bmap;
5172 /* For each known div d = floor(f/m), add the constraints
5174 * f - m d >= 0
5175 * -(f-(m-1)) + m d >= 0
5177 * Remove duplicate constraints in case of some these div constraints
5178 * already appear in "bmap".
5180 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5181 __isl_take isl_basic_map *bmap)
5183 unsigned n_div;
5185 if (!bmap)
5186 return NULL;
5187 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5188 if (n_div == 0)
5189 return bmap;
5191 bmap = add_known_div_constraints(bmap);
5192 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5193 bmap = isl_basic_map_finalize(bmap);
5194 return bmap;
5197 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5199 * In particular, if this div is of the form d = floor(f/m),
5200 * then add the constraint
5202 * f - m d >= 0
5204 * if sign < 0 or the constraint
5206 * -(f-(m-1)) + m d >= 0
5208 * if sign > 0.
5210 __isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5211 __isl_take isl_basic_map *bmap, unsigned div, int sign)
5213 if (sign < 0)
5214 return add_upper_div_constraint(bmap, div);
5215 else
5216 return add_lower_div_constraint(bmap, div);
5219 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5220 __isl_take isl_basic_map *bmap)
5222 if (!bmap)
5223 goto error;
5224 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5225 bmap->n_div == 0 &&
5226 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5227 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5228 return bset_from_bmap(bmap);
5229 bmap = isl_basic_map_cow(bmap);
5230 if (!bmap)
5231 goto error;
5232 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
5233 if (!bmap->dim)
5234 goto error;
5235 bmap->extra -= bmap->n_div;
5236 bmap->n_div = 0;
5237 bmap = isl_basic_map_finalize(bmap);
5238 return bset_from_bmap(bmap);
5239 error:
5240 isl_basic_map_free(bmap);
5241 return NULL;
5244 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5245 __isl_take isl_basic_set *bset)
5247 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5250 /* Replace each element in "list" by the result of applying
5251 * isl_basic_map_underlying_set to the element.
5253 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5254 __isl_take isl_basic_map_list *list)
5256 int i, n;
5258 if (!list)
5259 return NULL;
5261 n = isl_basic_map_list_n_basic_map(list);
5262 for (i = 0; i < n; ++i) {
5263 isl_basic_map *bmap;
5264 isl_basic_set *bset;
5266 bmap = isl_basic_map_list_get_basic_map(list, i);
5267 bset = isl_basic_set_underlying_set(bmap);
5268 list = isl_basic_set_list_set_basic_set(list, i, bset);
5271 return list;
5274 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5275 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5277 struct isl_basic_map *bmap;
5278 struct isl_ctx *ctx;
5279 unsigned dim, total;
5280 int i;
5282 if (!bset || !like)
5283 goto error;
5284 ctx = bset->ctx;
5285 if (isl_basic_set_check_no_params(bset) < 0 ||
5286 isl_basic_set_check_no_locals(bset) < 0)
5287 goto error;
5288 dim = isl_basic_set_dim(bset, isl_dim_set);
5289 isl_assert(ctx, dim == isl_basic_map_total_dim(like), goto error);
5290 if (like->n_div == 0) {
5291 isl_space *space = isl_basic_map_get_space(like);
5292 isl_basic_map_free(like);
5293 return isl_basic_map_reset_space(bset, space);
5295 bset = isl_basic_set_cow(bset);
5296 if (!bset)
5297 goto error;
5298 total = dim + bset->extra;
5299 bmap = bset_to_bmap(bset);
5300 isl_space_free(bmap->dim);
5301 bmap->dim = isl_space_copy(like->dim);
5302 if (!bmap->dim)
5303 goto error;
5304 bmap->n_div = like->n_div;
5305 bmap->extra += like->n_div;
5306 if (bmap->extra) {
5307 unsigned ltotal;
5308 isl_int **div;
5309 ltotal = total - bmap->extra + like->extra;
5310 if (ltotal > total)
5311 ltotal = total;
5312 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5313 bmap->extra * (1 + 1 + total));
5314 if (isl_blk_is_error(bmap->block2))
5315 goto error;
5316 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5317 if (!div)
5318 goto error;
5319 bmap->div = div;
5320 for (i = 0; i < bmap->extra; ++i)
5321 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5322 for (i = 0; i < like->n_div; ++i) {
5323 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5324 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5326 bmap = isl_basic_map_add_known_div_constraints(bmap);
5328 isl_basic_map_free(like);
5329 bmap = isl_basic_map_simplify(bmap);
5330 bmap = isl_basic_map_finalize(bmap);
5331 return bmap;
5332 error:
5333 isl_basic_map_free(like);
5334 isl_basic_set_free(bset);
5335 return NULL;
5338 struct isl_basic_set *isl_basic_set_from_underlying_set(
5339 struct isl_basic_set *bset, struct isl_basic_set *like)
5341 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5342 bset_to_bmap(like)));
5345 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5347 int i;
5349 map = isl_map_cow(map);
5350 if (!map)
5351 return NULL;
5352 map->dim = isl_space_cow(map->dim);
5353 if (!map->dim)
5354 goto error;
5356 for (i = 1; i < map->n; ++i)
5357 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5358 goto error);
5359 for (i = 0; i < map->n; ++i) {
5360 map->p[i] = bset_to_bmap(
5361 isl_basic_map_underlying_set(map->p[i]));
5362 if (!map->p[i])
5363 goto error;
5365 if (map->n == 0)
5366 map->dim = isl_space_underlying(map->dim, 0);
5367 else {
5368 isl_space_free(map->dim);
5369 map->dim = isl_space_copy(map->p[0]->dim);
5371 if (!map->dim)
5372 goto error;
5373 return set_from_map(map);
5374 error:
5375 isl_map_free(map);
5376 return NULL;
5379 /* Replace the space of "bmap" by "space".
5381 * If the space of "bmap" is identical to "space" (including the identifiers
5382 * of the input and output dimensions), then simply return the original input.
5384 __isl_give isl_basic_map *isl_basic_map_reset_space(
5385 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5387 isl_bool equal;
5388 isl_space *bmap_space;
5390 bmap_space = isl_basic_map_peek_space(bmap);
5391 equal = isl_space_is_equal(bmap_space, space);
5392 if (equal >= 0 && equal)
5393 equal = isl_space_has_equal_ids(bmap_space, space);
5394 if (equal < 0)
5395 goto error;
5396 if (equal) {
5397 isl_space_free(space);
5398 return bmap;
5400 bmap = isl_basic_map_cow(bmap);
5401 if (!bmap || !space)
5402 goto error;
5404 isl_space_free(bmap->dim);
5405 bmap->dim = space;
5407 bmap = isl_basic_map_finalize(bmap);
5409 return bmap;
5410 error:
5411 isl_basic_map_free(bmap);
5412 isl_space_free(space);
5413 return NULL;
5416 __isl_give isl_basic_set *isl_basic_set_reset_space(
5417 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5419 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5420 dim));
5423 /* Check that the total dimensions of "map" and "space" are the same.
5425 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5426 __isl_keep isl_space *space)
5428 unsigned dim1, dim2;
5430 if (!map || !space)
5431 return isl_stat_error;
5432 dim1 = isl_map_dim(map, isl_dim_all);
5433 dim2 = isl_space_dim(space, isl_dim_all);
5434 if (dim1 == dim2)
5435 return isl_stat_ok;
5436 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5437 "total dimensions do not match", return isl_stat_error);
5440 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5441 __isl_take isl_space *space)
5443 int i;
5445 map = isl_map_cow(map);
5446 if (!map || !space)
5447 goto error;
5449 for (i = 0; i < map->n; ++i) {
5450 map->p[i] = isl_basic_map_reset_space(map->p[i],
5451 isl_space_copy(space));
5452 if (!map->p[i])
5453 goto error;
5455 isl_space_free(map->dim);
5456 map->dim = space;
5458 return map;
5459 error:
5460 isl_map_free(map);
5461 isl_space_free(space);
5462 return NULL;
5465 /* Replace the space of "map" by "space", without modifying
5466 * the dimension of "map".
5468 * If the space of "map" is identical to "space" (including the identifiers
5469 * of the input and output dimensions), then simply return the original input.
5471 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5472 __isl_take isl_space *space)
5474 isl_bool equal;
5475 isl_space *map_space;
5477 map_space = isl_map_peek_space(map);
5478 equal = isl_space_is_equal(map_space, space);
5479 if (equal >= 0 && equal)
5480 equal = isl_space_has_equal_ids(map_space, space);
5481 if (equal < 0)
5482 goto error;
5483 if (equal) {
5484 isl_space_free(space);
5485 return map;
5487 if (check_map_space_equal_total_dim(map, space) < 0)
5488 goto error;
5489 return isl_map_reset_space(map, space);
5490 error:
5491 isl_map_free(map);
5492 isl_space_free(space);
5493 return NULL;
5496 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5497 __isl_take isl_space *dim)
5499 return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5502 /* Compute the parameter domain of the given basic set.
5504 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5506 isl_bool is_params;
5507 isl_space *space;
5508 unsigned n;
5510 is_params = isl_basic_set_is_params(bset);
5511 if (is_params < 0)
5512 return isl_basic_set_free(bset);
5513 if (is_params)
5514 return bset;
5516 n = isl_basic_set_dim(bset, isl_dim_set);
5517 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5518 space = isl_basic_set_get_space(bset);
5519 space = isl_space_params(space);
5520 bset = isl_basic_set_reset_space(bset, space);
5521 return bset;
5524 /* Construct a zero-dimensional basic set with the given parameter domain.
5526 __isl_give isl_basic_set *isl_basic_set_from_params(
5527 __isl_take isl_basic_set *bset)
5529 isl_space *space;
5530 space = isl_basic_set_get_space(bset);
5531 space = isl_space_set_from_params(space);
5532 bset = isl_basic_set_reset_space(bset, space);
5533 return bset;
5536 /* Compute the parameter domain of the given set.
5538 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5540 return isl_map_params(set_to_map(set));
5543 /* Construct a zero-dimensional set with the given parameter domain.
5545 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5547 isl_space *space;
5548 space = isl_set_get_space(set);
5549 space = isl_space_set_from_params(space);
5550 set = isl_set_reset_space(set, space);
5551 return set;
5554 /* Compute the parameter domain of the given map.
5556 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5558 isl_space *space;
5559 unsigned n;
5561 n = isl_map_dim(map, isl_dim_in);
5562 map = isl_map_project_out(map, isl_dim_in, 0, n);
5563 n = isl_map_dim(map, isl_dim_out);
5564 map = isl_map_project_out(map, isl_dim_out, 0, n);
5565 space = isl_map_get_space(map);
5566 space = isl_space_params(space);
5567 map = isl_map_reset_space(map, space);
5568 return map;
5571 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5573 isl_space *space;
5574 unsigned n_out;
5576 if (!bmap)
5577 return NULL;
5578 space = isl_space_domain(isl_basic_map_get_space(bmap));
5580 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5581 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5583 return isl_basic_map_reset_space(bmap, space);
5586 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5588 if (!bmap)
5589 return isl_bool_error;
5590 return isl_space_may_be_set(bmap->dim);
5593 /* Is this basic map actually a set?
5594 * Users should never call this function. Outside of isl,
5595 * the type should indicate whether something is a set or a map.
5597 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5599 if (!bmap)
5600 return isl_bool_error;
5601 return isl_space_is_set(bmap->dim);
5604 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5606 isl_bool is_set;
5608 is_set = isl_basic_map_is_set(bmap);
5609 if (is_set < 0)
5610 goto error;
5611 if (is_set)
5612 return bmap;
5613 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5614 error:
5615 isl_basic_map_free(bmap);
5616 return NULL;
5619 __isl_give isl_basic_map *isl_basic_map_domain_map(
5620 __isl_take isl_basic_map *bmap)
5622 int i;
5623 isl_space *space;
5624 isl_basic_map *domain;
5625 int nparam, n_in, n_out;
5627 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5628 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5629 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5631 space = isl_basic_map_get_space(bmap);
5632 space = isl_space_from_range(isl_space_domain(space));
5633 domain = isl_basic_map_universe(space);
5635 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5636 bmap = isl_basic_map_apply_range(bmap, domain);
5637 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5639 for (i = 0; i < n_in; ++i)
5640 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5641 isl_dim_out, i);
5643 bmap = isl_basic_map_gauss(bmap, NULL);
5644 return isl_basic_map_finalize(bmap);
5647 __isl_give isl_basic_map *isl_basic_map_range_map(
5648 __isl_take isl_basic_map *bmap)
5650 int i;
5651 isl_space *space;
5652 isl_basic_map *range;
5653 int nparam, n_in, n_out;
5655 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5656 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5657 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5659 space = isl_basic_map_get_space(bmap);
5660 space = isl_space_from_range(isl_space_range(space));
5661 range = isl_basic_map_universe(space);
5663 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5664 bmap = isl_basic_map_apply_range(bmap, range);
5665 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5667 for (i = 0; i < n_out; ++i)
5668 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5669 isl_dim_out, i);
5671 bmap = isl_basic_map_gauss(bmap, NULL);
5672 return isl_basic_map_finalize(bmap);
5675 int isl_map_may_be_set(__isl_keep isl_map *map)
5677 if (!map)
5678 return -1;
5679 return isl_space_may_be_set(map->dim);
5682 /* Is this map actually a set?
5683 * Users should never call this function. Outside of isl,
5684 * the type should indicate whether something is a set or a map.
5686 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5688 if (!map)
5689 return isl_bool_error;
5690 return isl_space_is_set(map->dim);
5693 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
5695 int i;
5696 isl_bool is_set;
5697 struct isl_set *set;
5699 is_set = isl_map_is_set(map);
5700 if (is_set < 0)
5701 goto error;
5702 if (is_set)
5703 return set_from_map(map);
5705 map = isl_map_cow(map);
5706 if (!map)
5707 goto error;
5709 set = set_from_map(map);
5710 set->dim = isl_space_range(set->dim);
5711 if (!set->dim)
5712 goto error;
5713 for (i = 0; i < map->n; ++i) {
5714 set->p[i] = isl_basic_map_range(map->p[i]);
5715 if (!set->p[i])
5716 goto error;
5718 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5719 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5720 return set;
5721 error:
5722 isl_map_free(map);
5723 return NULL;
5726 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5728 int i;
5730 map = isl_map_cow(map);
5731 if (!map)
5732 return NULL;
5734 map->dim = isl_space_domain_map(map->dim);
5735 if (!map->dim)
5736 goto error;
5737 for (i = 0; i < map->n; ++i) {
5738 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5739 if (!map->p[i])
5740 goto error;
5742 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5743 map = isl_map_unmark_normalized(map);
5744 return map;
5745 error:
5746 isl_map_free(map);
5747 return NULL;
5750 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5752 int i;
5753 isl_space *range_dim;
5755 map = isl_map_cow(map);
5756 if (!map)
5757 return NULL;
5759 range_dim = isl_space_range(isl_map_get_space(map));
5760 range_dim = isl_space_from_range(range_dim);
5761 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5762 map->dim = isl_space_join(map->dim, range_dim);
5763 if (!map->dim)
5764 goto error;
5765 for (i = 0; i < map->n; ++i) {
5766 map->p[i] = isl_basic_map_range_map(map->p[i]);
5767 if (!map->p[i])
5768 goto error;
5770 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5771 map = isl_map_unmark_normalized(map);
5772 return map;
5773 error:
5774 isl_map_free(map);
5775 return NULL;
5778 /* Given a wrapped map of the form A[B -> C],
5779 * return the map A[B -> C] -> B.
5781 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5783 isl_id *id;
5784 isl_map *map;
5786 if (!set)
5787 return NULL;
5788 if (!isl_set_has_tuple_id(set))
5789 return isl_map_domain_map(isl_set_unwrap(set));
5791 id = isl_set_get_tuple_id(set);
5792 map = isl_map_domain_map(isl_set_unwrap(set));
5793 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5795 return map;
5798 __isl_give isl_basic_map *isl_basic_map_from_domain(
5799 __isl_take isl_basic_set *bset)
5801 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5804 __isl_give isl_basic_map *isl_basic_map_from_range(
5805 __isl_take isl_basic_set *bset)
5807 isl_space *space;
5808 space = isl_basic_set_get_space(bset);
5809 space = isl_space_from_range(space);
5810 bset = isl_basic_set_reset_space(bset, space);
5811 return bset_to_bmap(bset);
5814 /* Create a relation with the given set as range.
5815 * The domain of the created relation is a zero-dimensional
5816 * flat anonymous space.
5818 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5820 isl_space *space;
5821 space = isl_set_get_space(set);
5822 space = isl_space_from_range(space);
5823 set = isl_set_reset_space(set, space);
5824 return set_to_map(set);
5827 /* Create a relation with the given set as domain.
5828 * The range of the created relation is a zero-dimensional
5829 * flat anonymous space.
5831 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5833 return isl_map_reverse(isl_map_from_range(set));
5836 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5837 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5839 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5842 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5843 __isl_take isl_set *range)
5845 return isl_map_apply_range(isl_map_reverse(domain), range);
5848 /* Return a newly allocated isl_map with given space and flags and
5849 * room for "n" basic maps.
5850 * Make sure that all cached information is cleared.
5852 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5853 unsigned flags)
5855 struct isl_map *map;
5857 if (!space)
5858 return NULL;
5859 if (n < 0)
5860 isl_die(space->ctx, isl_error_internal,
5861 "negative number of basic maps", goto error);
5862 map = isl_calloc(space->ctx, struct isl_map,
5863 sizeof(struct isl_map) +
5864 (n - 1) * sizeof(struct isl_basic_map *));
5865 if (!map)
5866 goto error;
5868 map->ctx = space->ctx;
5869 isl_ctx_ref(map->ctx);
5870 map->ref = 1;
5871 map->size = n;
5872 map->n = 0;
5873 map->dim = space;
5874 map->flags = flags;
5875 return map;
5876 error:
5877 isl_space_free(space);
5878 return NULL;
5881 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
5883 struct isl_basic_map *bmap;
5884 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
5885 bmap = isl_basic_map_set_to_empty(bmap);
5886 return bmap;
5889 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
5891 struct isl_basic_set *bset;
5892 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
5893 bset = isl_basic_set_set_to_empty(bset);
5894 return bset;
5897 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
5899 struct isl_basic_map *bmap;
5900 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
5901 bmap = isl_basic_map_finalize(bmap);
5902 return bmap;
5905 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
5907 struct isl_basic_set *bset;
5908 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
5909 bset = isl_basic_set_finalize(bset);
5910 return bset;
5913 __isl_give isl_basic_map *isl_basic_map_nat_universe(
5914 __isl_take isl_space *space)
5916 int i;
5917 unsigned total = isl_space_dim(space, isl_dim_all);
5918 isl_basic_map *bmap;
5920 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
5921 for (i = 0; i < total; ++i) {
5922 int k = isl_basic_map_alloc_inequality(bmap);
5923 if (k < 0)
5924 goto error;
5925 isl_seq_clr(bmap->ineq[k], 1 + total);
5926 isl_int_set_si(bmap->ineq[k][1 + i], 1);
5928 return bmap;
5929 error:
5930 isl_basic_map_free(bmap);
5931 return NULL;
5934 __isl_give isl_basic_set *isl_basic_set_nat_universe(
5935 __isl_take isl_space *space)
5937 return isl_basic_map_nat_universe(space);
5940 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
5942 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
5945 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
5947 return isl_map_nat_universe(dim);
5950 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
5952 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
5955 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
5957 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
5960 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
5962 struct isl_map *map;
5963 if (!space)
5964 return NULL;
5965 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
5966 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
5967 return map;
5970 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
5972 struct isl_set *set;
5973 if (!space)
5974 return NULL;
5975 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
5976 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
5977 return set;
5980 struct isl_map *isl_map_dup(struct isl_map *map)
5982 int i;
5983 struct isl_map *dup;
5985 if (!map)
5986 return NULL;
5987 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
5988 for (i = 0; i < map->n; ++i)
5989 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
5990 return dup;
5993 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
5994 __isl_take isl_basic_map *bmap)
5996 if (!bmap || !map)
5997 goto error;
5998 if (isl_basic_map_plain_is_empty(bmap)) {
5999 isl_basic_map_free(bmap);
6000 return map;
6002 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
6003 isl_assert(map->ctx, map->n < map->size, goto error);
6004 map->p[map->n] = bmap;
6005 map->n++;
6006 map = isl_map_unmark_normalized(map);
6007 return map;
6008 error:
6009 if (map)
6010 isl_map_free(map);
6011 if (bmap)
6012 isl_basic_map_free(bmap);
6013 return NULL;
6016 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6018 int i;
6020 if (!map)
6021 return NULL;
6023 if (--map->ref > 0)
6024 return NULL;
6026 clear_caches(map);
6027 isl_ctx_deref(map->ctx);
6028 for (i = 0; i < map->n; ++i)
6029 isl_basic_map_free(map->p[i]);
6030 isl_space_free(map->dim);
6031 free(map);
6033 return NULL;
6036 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6037 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6039 int j;
6041 bmap = isl_basic_map_cow(bmap);
6042 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6043 j = isl_basic_map_alloc_equality(bmap);
6044 if (j < 0)
6045 goto error;
6046 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6047 isl_int_set_si(bmap->eq[j][pos], -1);
6048 isl_int_set_si(bmap->eq[j][0], value);
6049 bmap = isl_basic_map_simplify(bmap);
6050 return isl_basic_map_finalize(bmap);
6051 error:
6052 isl_basic_map_free(bmap);
6053 return NULL;
6056 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6057 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6059 int j;
6061 bmap = isl_basic_map_cow(bmap);
6062 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6063 j = isl_basic_map_alloc_equality(bmap);
6064 if (j < 0)
6065 goto error;
6066 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6067 isl_int_set_si(bmap->eq[j][pos], -1);
6068 isl_int_set(bmap->eq[j][0], value);
6069 bmap = isl_basic_map_simplify(bmap);
6070 return isl_basic_map_finalize(bmap);
6071 error:
6072 isl_basic_map_free(bmap);
6073 return NULL;
6076 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6077 enum isl_dim_type type, unsigned pos, int value)
6079 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6080 return isl_basic_map_free(bmap);
6081 return isl_basic_map_fix_pos_si(bmap,
6082 isl_basic_map_offset(bmap, type) + pos, value);
6085 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6086 enum isl_dim_type type, unsigned pos, isl_int value)
6088 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6089 return isl_basic_map_free(bmap);
6090 return isl_basic_map_fix_pos(bmap,
6091 isl_basic_map_offset(bmap, type) + pos, value);
6094 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6095 * to be equal to "v".
6097 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6098 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6100 if (!bmap || !v)
6101 goto error;
6102 if (!isl_val_is_int(v))
6103 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6104 "expecting integer value", goto error);
6105 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6106 goto error;
6107 pos += isl_basic_map_offset(bmap, type);
6108 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6109 isl_val_free(v);
6110 return bmap;
6111 error:
6112 isl_basic_map_free(bmap);
6113 isl_val_free(v);
6114 return NULL;
6117 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6118 * to be equal to "v".
6120 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6121 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6123 return isl_basic_map_fix_val(bset, type, pos, v);
6126 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
6127 enum isl_dim_type type, unsigned pos, int value)
6129 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6130 type, pos, value));
6133 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6134 enum isl_dim_type type, unsigned pos, isl_int value)
6136 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6137 type, pos, value));
6140 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
6141 unsigned input, int value)
6143 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
6146 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
6147 unsigned dim, int value)
6149 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6150 isl_dim_set, dim, value));
6153 /* Remove the basic map at position "i" from "map" if this basic map
6154 * is (obviously) empty.
6156 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6158 isl_bool empty;
6160 if (!map)
6161 return NULL;
6163 empty = isl_basic_map_plain_is_empty(map->p[i]);
6164 if (empty < 0)
6165 return isl_map_free(map);
6166 if (!empty)
6167 return map;
6169 isl_basic_map_free(map->p[i]);
6170 map->n--;
6171 if (i != map->n) {
6172 map->p[i] = map->p[map->n];
6173 map = isl_map_unmark_normalized(map);
6177 return map;
6180 /* Perform "fn" on each basic map of "map", where we may not be holding
6181 * the only reference to "map".
6182 * In particular, "fn" should be a semantics preserving operation
6183 * that we want to apply to all copies of "map". We therefore need
6184 * to be careful not to modify "map" in a way that breaks "map"
6185 * in case anything goes wrong.
6187 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6188 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6190 struct isl_basic_map *bmap;
6191 int i;
6193 if (!map)
6194 return NULL;
6196 for (i = map->n - 1; i >= 0; --i) {
6197 bmap = isl_basic_map_copy(map->p[i]);
6198 bmap = fn(bmap);
6199 if (!bmap)
6200 goto error;
6201 isl_basic_map_free(map->p[i]);
6202 map->p[i] = bmap;
6203 map = remove_if_empty(map, i);
6204 if (!map)
6205 return NULL;
6208 return map;
6209 error:
6210 isl_map_free(map);
6211 return NULL;
6214 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6215 enum isl_dim_type type, unsigned pos, int value)
6217 int i;
6219 map = isl_map_cow(map);
6220 if (isl_map_check_range(map, type, pos, 1) < 0)
6221 return isl_map_free(map);
6222 for (i = map->n - 1; i >= 0; --i) {
6223 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6224 map = remove_if_empty(map, i);
6225 if (!map)
6226 return NULL;
6228 map = isl_map_unmark_normalized(map);
6229 return map;
6232 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6233 enum isl_dim_type type, unsigned pos, int value)
6235 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6238 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6239 enum isl_dim_type type, unsigned pos, isl_int value)
6241 int i;
6243 map = isl_map_cow(map);
6244 if (isl_map_check_range(map, type, pos, 1) < 0)
6245 return isl_map_free(map);
6246 for (i = 0; i < map->n; ++i) {
6247 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6248 if (!map->p[i])
6249 goto error;
6251 map = isl_map_unmark_normalized(map);
6252 return map;
6253 error:
6254 isl_map_free(map);
6255 return NULL;
6258 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6259 enum isl_dim_type type, unsigned pos, isl_int value)
6261 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6264 /* Fix the value of the variable at position "pos" of type "type" of "map"
6265 * to be equal to "v".
6267 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6268 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6270 int i;
6272 map = isl_map_cow(map);
6273 if (!map || !v)
6274 goto error;
6276 if (!isl_val_is_int(v))
6277 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6278 "expecting integer value", goto error);
6279 if (isl_map_check_range(map, type, pos, 1) < 0)
6280 goto error;
6281 for (i = map->n - 1; i >= 0; --i) {
6282 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6283 isl_val_copy(v));
6284 map = remove_if_empty(map, i);
6285 if (!map)
6286 goto error;
6288 map = isl_map_unmark_normalized(map);
6289 isl_val_free(v);
6290 return map;
6291 error:
6292 isl_map_free(map);
6293 isl_val_free(v);
6294 return NULL;
6297 /* Fix the value of the variable at position "pos" of type "type" of "set"
6298 * to be equal to "v".
6300 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6301 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6303 return isl_map_fix_val(set, type, pos, v);
6306 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
6307 unsigned input, int value)
6309 return isl_map_fix_si(map, isl_dim_in, input, value);
6312 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
6314 return set_from_map(isl_map_fix_si(set_to_map(set),
6315 isl_dim_set, dim, value));
6318 static __isl_give isl_basic_map *basic_map_bound_si(
6319 __isl_take isl_basic_map *bmap,
6320 enum isl_dim_type type, unsigned pos, int value, int upper)
6322 int j;
6324 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6325 return isl_basic_map_free(bmap);
6326 pos += isl_basic_map_offset(bmap, type);
6327 bmap = isl_basic_map_cow(bmap);
6328 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6329 j = isl_basic_map_alloc_inequality(bmap);
6330 if (j < 0)
6331 goto error;
6332 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6333 if (upper) {
6334 isl_int_set_si(bmap->ineq[j][pos], -1);
6335 isl_int_set_si(bmap->ineq[j][0], value);
6336 } else {
6337 isl_int_set_si(bmap->ineq[j][pos], 1);
6338 isl_int_set_si(bmap->ineq[j][0], -value);
6340 bmap = isl_basic_map_simplify(bmap);
6341 return isl_basic_map_finalize(bmap);
6342 error:
6343 isl_basic_map_free(bmap);
6344 return NULL;
6347 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6348 __isl_take isl_basic_map *bmap,
6349 enum isl_dim_type type, unsigned pos, int value)
6351 return basic_map_bound_si(bmap, type, pos, value, 0);
6354 /* Constrain the values of the given dimension to be no greater than "value".
6356 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6357 __isl_take isl_basic_map *bmap,
6358 enum isl_dim_type type, unsigned pos, int value)
6360 return basic_map_bound_si(bmap, type, pos, value, 1);
6363 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6364 enum isl_dim_type type, unsigned pos, int value, int upper)
6366 int i;
6368 map = isl_map_cow(map);
6369 if (isl_map_check_range(map, type, pos, 1) < 0)
6370 return isl_map_free(map);
6371 for (i = 0; i < map->n; ++i) {
6372 map->p[i] = basic_map_bound_si(map->p[i],
6373 type, pos, value, upper);
6374 if (!map->p[i])
6375 goto error;
6377 map = isl_map_unmark_normalized(map);
6378 return map;
6379 error:
6380 isl_map_free(map);
6381 return NULL;
6384 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6385 enum isl_dim_type type, unsigned pos, int value)
6387 return map_bound_si(map, type, pos, value, 0);
6390 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6391 enum isl_dim_type type, unsigned pos, int value)
6393 return map_bound_si(map, type, pos, value, 1);
6396 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6397 enum isl_dim_type type, unsigned pos, int value)
6399 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6400 type, pos, value));
6403 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6404 enum isl_dim_type type, unsigned pos, int value)
6406 return isl_map_upper_bound_si(set, type, pos, value);
6409 /* Bound the given variable of "bmap" from below (or above is "upper"
6410 * is set) to "value".
6412 static __isl_give isl_basic_map *basic_map_bound(
6413 __isl_take isl_basic_map *bmap,
6414 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6416 int j;
6418 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6419 return isl_basic_map_free(bmap);
6420 pos += isl_basic_map_offset(bmap, type);
6421 bmap = isl_basic_map_cow(bmap);
6422 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6423 j = isl_basic_map_alloc_inequality(bmap);
6424 if (j < 0)
6425 goto error;
6426 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6427 if (upper) {
6428 isl_int_set_si(bmap->ineq[j][pos], -1);
6429 isl_int_set(bmap->ineq[j][0], value);
6430 } else {
6431 isl_int_set_si(bmap->ineq[j][pos], 1);
6432 isl_int_neg(bmap->ineq[j][0], value);
6434 bmap = isl_basic_map_simplify(bmap);
6435 return isl_basic_map_finalize(bmap);
6436 error:
6437 isl_basic_map_free(bmap);
6438 return NULL;
6441 /* Bound the given variable of "map" from below (or above is "upper"
6442 * is set) to "value".
6444 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6445 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6447 int i;
6449 map = isl_map_cow(map);
6450 if (isl_map_check_range(map, type, pos, 1) < 0)
6451 return isl_map_free(map);
6452 for (i = map->n - 1; i >= 0; --i) {
6453 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6454 map = remove_if_empty(map, i);
6455 if (!map)
6456 return NULL;
6458 map = isl_map_unmark_normalized(map);
6459 return map;
6462 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6463 enum isl_dim_type type, unsigned pos, isl_int value)
6465 return map_bound(map, type, pos, value, 0);
6468 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6469 enum isl_dim_type type, unsigned pos, isl_int value)
6471 return map_bound(map, type, pos, value, 1);
6474 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6475 enum isl_dim_type type, unsigned pos, isl_int value)
6477 return isl_map_lower_bound(set, type, pos, value);
6480 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6481 enum isl_dim_type type, unsigned pos, isl_int value)
6483 return isl_map_upper_bound(set, type, pos, value);
6486 /* Force the values of the variable at position "pos" of type "type" of "set"
6487 * to be no smaller than "value".
6489 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6490 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6492 if (!value)
6493 goto error;
6494 if (!isl_val_is_int(value))
6495 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6496 "expecting integer value", goto error);
6497 set = isl_set_lower_bound(set, type, pos, value->n);
6498 isl_val_free(value);
6499 return set;
6500 error:
6501 isl_val_free(value);
6502 isl_set_free(set);
6503 return NULL;
6506 /* Force the values of the variable at position "pos" of type "type" of "set"
6507 * to be no greater than "value".
6509 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6510 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6512 if (!value)
6513 goto error;
6514 if (!isl_val_is_int(value))
6515 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6516 "expecting integer value", goto error);
6517 set = isl_set_upper_bound(set, type, pos, value->n);
6518 isl_val_free(value);
6519 return set;
6520 error:
6521 isl_val_free(value);
6522 isl_set_free(set);
6523 return NULL;
6526 /* Bound the given variable of "bset" from below (or above is "upper"
6527 * is set) to "value".
6529 static __isl_give isl_basic_set *isl_basic_set_bound(
6530 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6531 isl_int value, int upper)
6533 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
6534 type, pos, value, upper));
6537 /* Bound the given variable of "bset" from below (or above is "upper"
6538 * is set) to "value".
6540 static __isl_give isl_basic_set *isl_basic_set_bound_val(
6541 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6542 __isl_take isl_val *value, int upper)
6544 if (!value)
6545 goto error;
6546 if (!isl_val_is_int(value))
6547 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
6548 "expecting integer value", goto error);
6549 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
6550 isl_val_free(value);
6551 return bset;
6552 error:
6553 isl_val_free(value);
6554 isl_basic_set_free(bset);
6555 return NULL;
6558 /* Bound the given variable of "bset" from below to "value".
6560 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
6561 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6562 __isl_take isl_val *value)
6564 return isl_basic_set_bound_val(bset, type, pos, value, 0);
6567 /* Bound the given variable of "bset" from above to "value".
6569 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
6570 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6571 __isl_take isl_val *value)
6573 return isl_basic_set_bound_val(bset, type, pos, value, 1);
6576 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
6578 int i;
6580 map = isl_map_cow(map);
6581 if (!map)
6582 return NULL;
6584 map->dim = isl_space_reverse(map->dim);
6585 if (!map->dim)
6586 goto error;
6587 for (i = 0; i < map->n; ++i) {
6588 map->p[i] = isl_basic_map_reverse(map->p[i]);
6589 if (!map->p[i])
6590 goto error;
6592 map = isl_map_unmark_normalized(map);
6593 return map;
6594 error:
6595 isl_map_free(map);
6596 return NULL;
6599 #undef TYPE
6600 #define TYPE isl_pw_multi_aff
6601 #undef SUFFIX
6602 #define SUFFIX _pw_multi_aff
6603 #undef EMPTY
6604 #define EMPTY isl_pw_multi_aff_empty
6605 #undef ADD
6606 #define ADD isl_pw_multi_aff_union_add
6607 #include "isl_map_lexopt_templ.c"
6609 /* Given a map "map", compute the lexicographically minimal
6610 * (or maximal) image element for each domain element in dom,
6611 * in the form of an isl_pw_multi_aff.
6612 * If "empty" is not NULL, then set *empty to those elements in dom that
6613 * do not have an image element.
6614 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6615 * should be computed over the domain of "map". "empty" is also NULL
6616 * in this case.
6618 * We first compute the lexicographically minimal or maximal element
6619 * in the first basic map. This results in a partial solution "res"
6620 * and a subset "todo" of dom that still need to be handled.
6621 * We then consider each of the remaining maps in "map" and successively
6622 * update both "res" and "todo".
6623 * If "empty" is NULL, then the todo sets are not needed and therefore
6624 * also not computed.
6626 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6627 __isl_take isl_map *map, __isl_take isl_set *dom,
6628 __isl_give isl_set **empty, unsigned flags)
6630 int i;
6631 int full;
6632 isl_pw_multi_aff *res;
6633 isl_set *todo;
6635 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6636 if (!map || (!full && !dom))
6637 goto error;
6639 if (isl_map_plain_is_empty(map)) {
6640 if (empty)
6641 *empty = dom;
6642 else
6643 isl_set_free(dom);
6644 return isl_pw_multi_aff_from_map(map);
6647 res = basic_map_partial_lexopt_pw_multi_aff(
6648 isl_basic_map_copy(map->p[0]),
6649 isl_set_copy(dom), empty, flags);
6651 if (empty)
6652 todo = *empty;
6653 for (i = 1; i < map->n; ++i) {
6654 isl_pw_multi_aff *res_i;
6656 res_i = basic_map_partial_lexopt_pw_multi_aff(
6657 isl_basic_map_copy(map->p[i]),
6658 isl_set_copy(dom), empty, flags);
6660 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6661 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6662 else
6663 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6665 if (empty)
6666 todo = isl_set_intersect(todo, *empty);
6669 isl_set_free(dom);
6670 isl_map_free(map);
6672 if (empty)
6673 *empty = todo;
6675 return res;
6676 error:
6677 if (empty)
6678 *empty = NULL;
6679 isl_set_free(dom);
6680 isl_map_free(map);
6681 return NULL;
6684 #undef TYPE
6685 #define TYPE isl_map
6686 #undef SUFFIX
6687 #define SUFFIX
6688 #undef EMPTY
6689 #define EMPTY isl_map_empty
6690 #undef ADD
6691 #define ADD isl_map_union_disjoint
6692 #include "isl_map_lexopt_templ.c"
6694 /* Given a map "map", compute the lexicographically minimal
6695 * (or maximal) image element for each domain element in "dom",
6696 * in the form of an isl_map.
6697 * If "empty" is not NULL, then set *empty to those elements in "dom" that
6698 * do not have an image element.
6699 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6700 * should be computed over the domain of "map". "empty" is also NULL
6701 * in this case.
6703 * If the input consists of more than one disjunct, then first
6704 * compute the desired result in the form of an isl_pw_multi_aff and
6705 * then convert that into an isl_map.
6707 * This function used to have an explicit implementation in terms
6708 * of isl_maps, but it would continually intersect the domains of
6709 * partial results with the complement of the domain of the next
6710 * partial solution, potentially leading to an explosion in the number
6711 * of disjuncts if there are several disjuncts in the input.
6712 * An even earlier implementation of this function would look for
6713 * better results in the domain of the partial result and for extra
6714 * results in the complement of this domain, which would lead to
6715 * even more splintering.
6717 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6718 __isl_take isl_map *map, __isl_take isl_set *dom,
6719 __isl_give isl_set **empty, unsigned flags)
6721 int full;
6722 struct isl_map *res;
6723 isl_pw_multi_aff *pma;
6725 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6726 if (!map || (!full && !dom))
6727 goto error;
6729 if (isl_map_plain_is_empty(map)) {
6730 if (empty)
6731 *empty = dom;
6732 else
6733 isl_set_free(dom);
6734 return map;
6737 if (map->n == 1) {
6738 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6739 dom, empty, flags);
6740 isl_map_free(map);
6741 return res;
6744 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6745 flags);
6746 return isl_map_from_pw_multi_aff(pma);
6747 error:
6748 if (empty)
6749 *empty = NULL;
6750 isl_set_free(dom);
6751 isl_map_free(map);
6752 return NULL;
6755 __isl_give isl_map *isl_map_partial_lexmax(
6756 __isl_take isl_map *map, __isl_take isl_set *dom,
6757 __isl_give isl_set **empty)
6759 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6762 __isl_give isl_map *isl_map_partial_lexmin(
6763 __isl_take isl_map *map, __isl_take isl_set *dom,
6764 __isl_give isl_set **empty)
6766 return isl_map_partial_lexopt(map, dom, empty, 0);
6769 __isl_give isl_set *isl_set_partial_lexmin(
6770 __isl_take isl_set *set, __isl_take isl_set *dom,
6771 __isl_give isl_set **empty)
6773 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6774 dom, empty));
6777 __isl_give isl_set *isl_set_partial_lexmax(
6778 __isl_take isl_set *set, __isl_take isl_set *dom,
6779 __isl_give isl_set **empty)
6781 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6782 dom, empty));
6785 /* Compute the lexicographic minimum (or maximum if "flags" includes
6786 * ISL_OPT_MAX) of "bset" over its parametric domain.
6788 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6789 unsigned flags)
6791 return isl_basic_map_lexopt(bset, flags);
6794 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6796 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6799 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6801 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6804 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6806 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6809 /* Compute the lexicographic minimum of "bset" over its parametric domain
6810 * for the purpose of quantifier elimination.
6811 * That is, find an explicit representation for all the existentially
6812 * quantified variables in "bset" by computing their lexicographic
6813 * minimum.
6815 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6816 __isl_take isl_basic_set *bset)
6818 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6821 /* Given a basic map with one output dimension, compute the minimum or
6822 * maximum of that dimension as an isl_pw_aff.
6824 * Compute the optimum as a lexicographic optimum over the single
6825 * output dimension and extract the single isl_pw_aff from the result.
6827 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6828 int max)
6830 isl_pw_multi_aff *pma;
6831 isl_pw_aff *pwaff;
6833 bmap = isl_basic_map_copy(bmap);
6834 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
6835 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
6836 isl_pw_multi_aff_free(pma);
6838 return pwaff;
6841 /* Compute the minimum or maximum of the given output dimension
6842 * as a function of the parameters and the input dimensions,
6843 * but independently of the other output dimensions.
6845 * We first project out the other output dimension and then compute
6846 * the "lexicographic" maximum in each basic map, combining the results
6847 * using isl_pw_aff_union_max.
6849 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6850 int max)
6852 int i;
6853 isl_pw_aff *pwaff;
6854 unsigned n_out;
6856 n_out = isl_map_dim(map, isl_dim_out);
6857 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6858 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6859 if (!map)
6860 return NULL;
6862 if (map->n == 0) {
6863 isl_space *space = isl_map_get_space(map);
6864 isl_map_free(map);
6865 return isl_pw_aff_empty(space);
6868 pwaff = basic_map_dim_opt(map->p[0], max);
6869 for (i = 1; i < map->n; ++i) {
6870 isl_pw_aff *pwaff_i;
6872 pwaff_i = basic_map_dim_opt(map->p[i], max);
6873 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6876 isl_map_free(map);
6878 return pwaff;
6881 /* Compute the minimum of the given output dimension as a function of the
6882 * parameters and input dimensions, but independently of
6883 * the other output dimensions.
6885 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
6887 return map_dim_opt(map, pos, 0);
6890 /* Compute the maximum of the given output dimension as a function of the
6891 * parameters and input dimensions, but independently of
6892 * the other output dimensions.
6894 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6896 return map_dim_opt(map, pos, 1);
6899 /* Compute the minimum or maximum of the given set dimension
6900 * as a function of the parameters,
6901 * but independently of the other set dimensions.
6903 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
6904 int max)
6906 return map_dim_opt(set, pos, max);
6909 /* Compute the maximum of the given set dimension as a function of the
6910 * parameters, but independently of the other set dimensions.
6912 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
6914 return set_dim_opt(set, pos, 1);
6917 /* Compute the minimum of the given set dimension as a function of the
6918 * parameters, but independently of the other set dimensions.
6920 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
6922 return set_dim_opt(set, pos, 0);
6925 /* Apply a preimage specified by "mat" on the parameters of "bset".
6926 * bset is assumed to have only parameters and divs.
6928 static __isl_give isl_basic_set *basic_set_parameter_preimage(
6929 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
6931 unsigned nparam;
6933 if (!bset || !mat)
6934 goto error;
6936 bset->dim = isl_space_cow(bset->dim);
6937 if (!bset->dim)
6938 goto error;
6940 nparam = isl_basic_set_dim(bset, isl_dim_param);
6942 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
6944 bset->dim->nparam = 0;
6945 bset->dim->n_out = nparam;
6946 bset = isl_basic_set_preimage(bset, mat);
6947 if (bset) {
6948 bset->dim->nparam = bset->dim->n_out;
6949 bset->dim->n_out = 0;
6951 return bset;
6952 error:
6953 isl_mat_free(mat);
6954 isl_basic_set_free(bset);
6955 return NULL;
6958 /* Apply a preimage specified by "mat" on the parameters of "set".
6959 * set is assumed to have only parameters and divs.
6961 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
6962 __isl_take isl_mat *mat)
6964 isl_space *space;
6965 unsigned nparam;
6967 if (!set || !mat)
6968 goto error;
6970 nparam = isl_set_dim(set, isl_dim_param);
6972 if (mat->n_row != 1 + nparam)
6973 isl_die(isl_set_get_ctx(set), isl_error_internal,
6974 "unexpected number of rows", goto error);
6976 space = isl_set_get_space(set);
6977 space = isl_space_move_dims(space, isl_dim_set, 0,
6978 isl_dim_param, 0, nparam);
6979 set = isl_set_reset_space(set, space);
6980 set = isl_set_preimage(set, mat);
6981 nparam = isl_set_dim(set, isl_dim_out);
6982 space = isl_set_get_space(set);
6983 space = isl_space_move_dims(space, isl_dim_param, 0,
6984 isl_dim_out, 0, nparam);
6985 set = isl_set_reset_space(set, space);
6986 return set;
6987 error:
6988 isl_mat_free(mat);
6989 isl_set_free(set);
6990 return NULL;
6993 /* Intersect the basic set "bset" with the affine space specified by the
6994 * equalities in "eq".
6996 static __isl_give isl_basic_set *basic_set_append_equalities(
6997 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
6999 int i, k;
7000 unsigned len;
7002 if (!bset || !eq)
7003 goto error;
7005 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
7006 eq->n_row, 0);
7007 if (!bset)
7008 goto error;
7010 len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7011 for (i = 0; i < eq->n_row; ++i) {
7012 k = isl_basic_set_alloc_equality(bset);
7013 if (k < 0)
7014 goto error;
7015 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7016 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7018 isl_mat_free(eq);
7020 bset = isl_basic_set_gauss(bset, NULL);
7021 bset = isl_basic_set_finalize(bset);
7023 return bset;
7024 error:
7025 isl_mat_free(eq);
7026 isl_basic_set_free(bset);
7027 return NULL;
7030 /* Intersect the set "set" with the affine space specified by the
7031 * equalities in "eq".
7033 static struct isl_set *set_append_equalities(struct isl_set *set,
7034 struct isl_mat *eq)
7036 int i;
7038 if (!set || !eq)
7039 goto error;
7041 for (i = 0; i < set->n; ++i) {
7042 set->p[i] = basic_set_append_equalities(set->p[i],
7043 isl_mat_copy(eq));
7044 if (!set->p[i])
7045 goto error;
7047 isl_mat_free(eq);
7048 return set;
7049 error:
7050 isl_mat_free(eq);
7051 isl_set_free(set);
7052 return NULL;
7055 /* Given a basic set "bset" that only involves parameters and existentially
7056 * quantified variables, return the index of the first equality
7057 * that only involves parameters. If there is no such equality then
7058 * return bset->n_eq.
7060 * This function assumes that isl_basic_set_gauss has been called on "bset".
7062 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7064 int i, j;
7065 unsigned nparam, n_div;
7067 if (!bset)
7068 return -1;
7070 nparam = isl_basic_set_dim(bset, isl_dim_param);
7071 n_div = isl_basic_set_dim(bset, isl_dim_div);
7073 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7074 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7075 ++i;
7078 return i;
7081 /* Compute an explicit representation for the existentially quantified
7082 * variables in "bset" by computing the "minimal value" of the set
7083 * variables. Since there are no set variables, the computation of
7084 * the minimal value essentially computes an explicit representation
7085 * of the non-empty part(s) of "bset".
7087 * The input only involves parameters and existentially quantified variables.
7088 * All equalities among parameters have been removed.
7090 * Since the existentially quantified variables in the result are in general
7091 * going to be different from those in the input, we first replace
7092 * them by the minimal number of variables based on their equalities.
7093 * This should simplify the parametric integer programming.
7095 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7097 isl_morph *morph1, *morph2;
7098 isl_set *set;
7099 unsigned n;
7101 if (!bset)
7102 return NULL;
7103 if (bset->n_eq == 0)
7104 return isl_basic_set_lexmin_compute_divs(bset);
7106 morph1 = isl_basic_set_parameter_compression(bset);
7107 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7108 bset = isl_basic_set_lift(bset);
7109 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7110 bset = isl_morph_basic_set(morph2, bset);
7111 n = isl_basic_set_dim(bset, isl_dim_set);
7112 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7114 set = isl_basic_set_lexmin_compute_divs(bset);
7116 set = isl_morph_set(isl_morph_inverse(morph1), set);
7118 return set;
7121 /* Project the given basic set onto its parameter domain, possibly introducing
7122 * new, explicit, existential variables in the constraints.
7123 * The input has parameters and (possibly implicit) existential variables.
7124 * The output has the same parameters, but only
7125 * explicit existentially quantified variables.
7127 * The actual projection is performed by pip, but pip doesn't seem
7128 * to like equalities very much, so we first remove the equalities
7129 * among the parameters by performing a variable compression on
7130 * the parameters. Afterward, an inverse transformation is performed
7131 * and the equalities among the parameters are inserted back in.
7133 * The variable compression on the parameters may uncover additional
7134 * equalities that were only implicit before. We therefore check
7135 * if there are any new parameter equalities in the result and
7136 * if so recurse. The removal of parameter equalities is required
7137 * for the parameter compression performed by base_compute_divs.
7139 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
7141 int i;
7142 struct isl_mat *eq;
7143 struct isl_mat *T, *T2;
7144 struct isl_set *set;
7145 unsigned nparam;
7147 bset = isl_basic_set_cow(bset);
7148 if (!bset)
7149 return NULL;
7151 if (bset->n_eq == 0)
7152 return base_compute_divs(bset);
7154 bset = isl_basic_set_gauss(bset, NULL);
7155 if (!bset)
7156 return NULL;
7157 if (isl_basic_set_plain_is_empty(bset))
7158 return isl_set_from_basic_set(bset);
7160 i = first_parameter_equality(bset);
7161 if (i == bset->n_eq)
7162 return base_compute_divs(bset);
7164 nparam = isl_basic_set_dim(bset, isl_dim_param);
7165 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7166 0, 1 + nparam);
7167 eq = isl_mat_cow(eq);
7168 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7169 if (T && T->n_col == 0) {
7170 isl_mat_free(T);
7171 isl_mat_free(T2);
7172 isl_mat_free(eq);
7173 bset = isl_basic_set_set_to_empty(bset);
7174 return isl_set_from_basic_set(bset);
7176 bset = basic_set_parameter_preimage(bset, T);
7178 i = first_parameter_equality(bset);
7179 if (!bset)
7180 set = NULL;
7181 else if (i == bset->n_eq)
7182 set = base_compute_divs(bset);
7183 else
7184 set = parameter_compute_divs(bset);
7185 set = set_parameter_preimage(set, T2);
7186 set = set_append_equalities(set, eq);
7187 return set;
7190 /* Insert the divs from "ls" before those of "bmap".
7192 * The number of columns is not changed, which means that the last
7193 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7194 * The caller is responsible for removing the same number of dimensions
7195 * from the space of "bmap".
7197 static __isl_give isl_basic_map *insert_divs_from_local_space(
7198 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7200 int i;
7201 int n_div;
7202 int old_n_div;
7204 n_div = isl_local_space_dim(ls, isl_dim_div);
7205 if (n_div == 0)
7206 return bmap;
7208 old_n_div = bmap->n_div;
7209 bmap = insert_div_rows(bmap, n_div);
7210 if (!bmap)
7211 return NULL;
7213 for (i = 0; i < n_div; ++i) {
7214 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7215 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7218 return bmap;
7221 /* Replace the space of "bmap" by the space and divs of "ls".
7223 * If "ls" has any divs, then we simplify the result since we may
7224 * have discovered some additional equalities that could simplify
7225 * the div expressions.
7227 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7228 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7230 int n_div;
7232 bmap = isl_basic_map_cow(bmap);
7233 if (!bmap || !ls)
7234 goto error;
7236 n_div = isl_local_space_dim(ls, isl_dim_div);
7237 bmap = insert_divs_from_local_space(bmap, ls);
7238 if (!bmap)
7239 goto error;
7241 isl_space_free(bmap->dim);
7242 bmap->dim = isl_local_space_get_space(ls);
7243 if (!bmap->dim)
7244 goto error;
7246 isl_local_space_free(ls);
7247 if (n_div > 0)
7248 bmap = isl_basic_map_simplify(bmap);
7249 bmap = isl_basic_map_finalize(bmap);
7250 return bmap;
7251 error:
7252 isl_basic_map_free(bmap);
7253 isl_local_space_free(ls);
7254 return NULL;
7257 /* Replace the space of "map" by the space and divs of "ls".
7259 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7260 __isl_take isl_local_space *ls)
7262 int i;
7264 map = isl_map_cow(map);
7265 if (!map || !ls)
7266 goto error;
7268 for (i = 0; i < map->n; ++i) {
7269 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7270 isl_local_space_copy(ls));
7271 if (!map->p[i])
7272 goto error;
7274 isl_space_free(map->dim);
7275 map->dim = isl_local_space_get_space(ls);
7276 if (!map->dim)
7277 goto error;
7279 isl_local_space_free(ls);
7280 return map;
7281 error:
7282 isl_local_space_free(ls);
7283 isl_map_free(map);
7284 return NULL;
7287 /* Compute an explicit representation for the existentially
7288 * quantified variables for which do not know any explicit representation yet.
7290 * We first sort the existentially quantified variables so that the
7291 * existentially quantified variables for which we already have an explicit
7292 * representation are placed before those for which we do not.
7293 * The input dimensions, the output dimensions and the existentially
7294 * quantified variables for which we already have an explicit
7295 * representation are then turned into parameters.
7296 * compute_divs returns a map with the same parameters and
7297 * no input or output dimensions and the dimension specification
7298 * is reset to that of the input, including the existentially quantified
7299 * variables for which we already had an explicit representation.
7301 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7303 struct isl_basic_set *bset;
7304 struct isl_set *set;
7305 struct isl_map *map;
7306 isl_space *space;
7307 isl_local_space *ls;
7308 unsigned nparam;
7309 unsigned n_in;
7310 unsigned n_out;
7311 int n_known;
7312 int i;
7314 bmap = isl_basic_map_sort_divs(bmap);
7315 bmap = isl_basic_map_cow(bmap);
7316 if (!bmap)
7317 return NULL;
7319 n_known = isl_basic_map_first_unknown_div(bmap);
7320 if (n_known < 0)
7321 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7323 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7324 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7325 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7326 space = isl_space_set_alloc(bmap->ctx,
7327 nparam + n_in + n_out + n_known, 0);
7328 if (!space)
7329 goto error;
7331 ls = isl_basic_map_get_local_space(bmap);
7332 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7333 n_known, bmap->n_div - n_known);
7334 if (n_known > 0) {
7335 for (i = n_known; i < bmap->n_div; ++i)
7336 swap_div(bmap, i - n_known, i);
7337 bmap->n_div -= n_known;
7338 bmap->extra -= n_known;
7340 bmap = isl_basic_map_reset_space(bmap, space);
7341 bset = bset_from_bmap(bmap);
7343 set = parameter_compute_divs(bset);
7344 map = set_to_map(set);
7345 map = replace_space_by_local_space(map, ls);
7347 return map;
7348 error:
7349 isl_basic_map_free(bmap);
7350 return NULL;
7353 /* Remove the explicit representation of local variable "div",
7354 * if there is any.
7356 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7357 __isl_take isl_basic_map *bmap, int div)
7359 isl_bool unknown;
7361 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7362 if (unknown < 0)
7363 return isl_basic_map_free(bmap);
7364 if (unknown)
7365 return bmap;
7367 bmap = isl_basic_map_cow(bmap);
7368 if (!bmap)
7369 return NULL;
7370 isl_int_set_si(bmap->div[div][0], 0);
7371 return bmap;
7374 /* Is local variable "div" of "bmap" marked as not having an explicit
7375 * representation?
7376 * Note that even if "div" is not marked in this way and therefore
7377 * has an explicit representation, this representation may still
7378 * depend (indirectly) on other local variables that do not
7379 * have an explicit representation.
7381 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7382 int div)
7384 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7385 return isl_bool_error;
7386 return isl_int_is_zero(bmap->div[div][0]);
7389 /* Return the position of the first local variable that does not
7390 * have an explicit representation.
7391 * Return the total number of local variables if they all have
7392 * an explicit representation.
7393 * Return -1 on error.
7395 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7397 int i;
7399 if (!bmap)
7400 return -1;
7402 for (i = 0; i < bmap->n_div; ++i) {
7403 if (!isl_basic_map_div_is_known(bmap, i))
7404 return i;
7406 return bmap->n_div;
7409 /* Return the position of the first local variable that does not
7410 * have an explicit representation.
7411 * Return the total number of local variables if they all have
7412 * an explicit representation.
7413 * Return -1 on error.
7415 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7417 return isl_basic_map_first_unknown_div(bset);
7420 /* Does "bmap" have an explicit representation for all local variables?
7422 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7424 int first, n;
7426 n = isl_basic_map_dim(bmap, isl_dim_div);
7427 first = isl_basic_map_first_unknown_div(bmap);
7428 if (first < 0)
7429 return isl_bool_error;
7430 return first == n;
7433 /* Do all basic maps in "map" have an explicit representation
7434 * for all local variables?
7436 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7438 int i;
7440 if (!map)
7441 return isl_bool_error;
7443 for (i = 0; i < map->n; ++i) {
7444 int known = isl_basic_map_divs_known(map->p[i]);
7445 if (known <= 0)
7446 return known;
7449 return isl_bool_true;
7452 /* If bmap contains any unknown divs, then compute explicit
7453 * expressions for them. However, this computation may be
7454 * quite expensive, so first try to remove divs that aren't
7455 * strictly needed.
7457 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7459 int known;
7460 struct isl_map *map;
7462 known = isl_basic_map_divs_known(bmap);
7463 if (known < 0)
7464 goto error;
7465 if (known)
7466 return isl_map_from_basic_map(bmap);
7468 bmap = isl_basic_map_drop_redundant_divs(bmap);
7470 known = isl_basic_map_divs_known(bmap);
7471 if (known < 0)
7472 goto error;
7473 if (known)
7474 return isl_map_from_basic_map(bmap);
7476 map = compute_divs(bmap);
7477 return map;
7478 error:
7479 isl_basic_map_free(bmap);
7480 return NULL;
7483 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7485 int i;
7486 int known;
7487 struct isl_map *res;
7489 if (!map)
7490 return NULL;
7491 if (map->n == 0)
7492 return map;
7494 known = isl_map_divs_known(map);
7495 if (known < 0) {
7496 isl_map_free(map);
7497 return NULL;
7499 if (known)
7500 return map;
7502 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7503 for (i = 1 ; i < map->n; ++i) {
7504 struct isl_map *r2;
7505 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7506 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7507 res = isl_map_union_disjoint(res, r2);
7508 else
7509 res = isl_map_union(res, r2);
7511 isl_map_free(map);
7513 return res;
7516 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
7518 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7521 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7523 return set_from_map(isl_map_compute_divs(set_to_map(set)));
7526 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
7528 int i;
7529 struct isl_set *set;
7531 if (!map)
7532 goto error;
7534 map = isl_map_cow(map);
7535 if (!map)
7536 return NULL;
7538 set = set_from_map(map);
7539 set->dim = isl_space_domain(set->dim);
7540 if (!set->dim)
7541 goto error;
7542 for (i = 0; i < map->n; ++i) {
7543 set->p[i] = isl_basic_map_domain(map->p[i]);
7544 if (!set->p[i])
7545 goto error;
7547 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7548 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7549 return set;
7550 error:
7551 isl_map_free(map);
7552 return NULL;
7555 /* Return the union of "map1" and "map2", where we assume for now that
7556 * "map1" and "map2" are disjoint. Note that the basic maps inside
7557 * "map1" or "map2" may not be disjoint from each other.
7558 * Also note that this function is also called from isl_map_union,
7559 * which takes care of handling the situation where "map1" and "map2"
7560 * may not be disjoint.
7562 * If one of the inputs is empty, we can simply return the other input.
7563 * Similarly, if one of the inputs is universal, then it is equal to the union.
7565 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7566 __isl_take isl_map *map2)
7568 int i;
7569 unsigned flags = 0;
7570 struct isl_map *map = NULL;
7571 int is_universe;
7573 if (!map1 || !map2)
7574 goto error;
7576 if (!isl_space_is_equal(map1->dim, map2->dim))
7577 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7578 "spaces don't match", goto error);
7580 if (map1->n == 0) {
7581 isl_map_free(map1);
7582 return map2;
7584 if (map2->n == 0) {
7585 isl_map_free(map2);
7586 return map1;
7589 is_universe = isl_map_plain_is_universe(map1);
7590 if (is_universe < 0)
7591 goto error;
7592 if (is_universe) {
7593 isl_map_free(map2);
7594 return map1;
7597 is_universe = isl_map_plain_is_universe(map2);
7598 if (is_universe < 0)
7599 goto error;
7600 if (is_universe) {
7601 isl_map_free(map1);
7602 return map2;
7605 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7606 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7607 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7609 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7610 map1->n + map2->n, flags);
7611 if (!map)
7612 goto error;
7613 for (i = 0; i < map1->n; ++i) {
7614 map = isl_map_add_basic_map(map,
7615 isl_basic_map_copy(map1->p[i]));
7616 if (!map)
7617 goto error;
7619 for (i = 0; i < map2->n; ++i) {
7620 map = isl_map_add_basic_map(map,
7621 isl_basic_map_copy(map2->p[i]));
7622 if (!map)
7623 goto error;
7625 isl_map_free(map1);
7626 isl_map_free(map2);
7627 return map;
7628 error:
7629 isl_map_free(map);
7630 isl_map_free(map1);
7631 isl_map_free(map2);
7632 return NULL;
7635 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7636 * guaranteed to be disjoint by the caller.
7638 * Note that this functions is called from within isl_map_make_disjoint,
7639 * so we have to be careful not to touch the constraints of the inputs
7640 * in any way.
7642 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7643 __isl_take isl_map *map2)
7645 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7648 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7649 * not be disjoint. The parameters are assumed to have been aligned.
7651 * We currently simply call map_union_disjoint, the internal operation
7652 * of which does not really depend on the inputs being disjoint.
7653 * If the result contains more than one basic map, then we clear
7654 * the disjoint flag since the result may contain basic maps from
7655 * both inputs and these are not guaranteed to be disjoint.
7657 * As a special case, if "map1" and "map2" are obviously equal,
7658 * then we simply return "map1".
7660 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7661 __isl_take isl_map *map2)
7663 int equal;
7665 if (!map1 || !map2)
7666 goto error;
7668 equal = isl_map_plain_is_equal(map1, map2);
7669 if (equal < 0)
7670 goto error;
7671 if (equal) {
7672 isl_map_free(map2);
7673 return map1;
7676 map1 = map_union_disjoint(map1, map2);
7677 if (!map1)
7678 return NULL;
7679 if (map1->n > 1)
7680 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7681 return map1;
7682 error:
7683 isl_map_free(map1);
7684 isl_map_free(map2);
7685 return NULL;
7688 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7689 * not be disjoint.
7691 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7692 __isl_take isl_map *map2)
7694 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7697 __isl_give isl_set *isl_set_union_disjoint(
7698 __isl_take isl_set *set1, __isl_take isl_set *set2)
7700 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7701 set_to_map(set2)));
7704 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7706 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7709 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7710 * the results.
7712 * "map" and "set" are assumed to be compatible and non-NULL.
7714 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7715 __isl_take isl_set *set,
7716 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7717 __isl_take isl_basic_set *bset))
7719 unsigned flags = 0;
7720 struct isl_map *result;
7721 int i, j;
7723 if (isl_set_plain_is_universe(set)) {
7724 isl_set_free(set);
7725 return map;
7728 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7729 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7730 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7732 result = isl_map_alloc_space(isl_space_copy(map->dim),
7733 map->n * set->n, flags);
7734 for (i = 0; result && i < map->n; ++i)
7735 for (j = 0; j < set->n; ++j) {
7736 result = isl_map_add_basic_map(result,
7737 fn(isl_basic_map_copy(map->p[i]),
7738 isl_basic_set_copy(set->p[j])));
7739 if (!result)
7740 break;
7743 isl_map_free(map);
7744 isl_set_free(set);
7745 return result;
7748 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7749 __isl_take isl_set *set)
7751 isl_bool ok;
7753 ok = isl_map_compatible_range(map, set);
7754 if (ok < 0)
7755 goto error;
7756 if (!ok)
7757 isl_die(set->ctx, isl_error_invalid,
7758 "incompatible spaces", goto error);
7760 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7761 error:
7762 isl_map_free(map);
7763 isl_set_free(set);
7764 return NULL;
7767 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7768 __isl_take isl_set *set)
7770 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7773 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7774 __isl_take isl_set *set)
7776 isl_bool ok;
7778 ok = isl_map_compatible_domain(map, set);
7779 if (ok < 0)
7780 goto error;
7781 if (!ok)
7782 isl_die(set->ctx, isl_error_invalid,
7783 "incompatible spaces", goto error);
7785 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7786 error:
7787 isl_map_free(map);
7788 isl_set_free(set);
7789 return NULL;
7792 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7793 __isl_take isl_set *set)
7795 return isl_map_align_params_map_map_and(map, set,
7796 &map_intersect_domain);
7799 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7800 * in the space B -> C, return the intersection.
7801 * The parameters are assumed to have been aligned.
7803 * The map "factor" is first extended to a map living in the space
7804 * [A -> B] -> C and then a regular intersection is computed.
7806 static __isl_give isl_map *map_intersect_domain_factor_range(
7807 __isl_take isl_map *map, __isl_take isl_map *factor)
7809 isl_space *space;
7810 isl_map *ext_factor;
7812 space = isl_space_domain_factor_domain(isl_map_get_space(map));
7813 ext_factor = isl_map_universe(space);
7814 ext_factor = isl_map_domain_product(ext_factor, factor);
7815 return map_intersect(map, ext_factor);
7818 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7819 * in the space B -> C, return the intersection.
7821 __isl_give isl_map *isl_map_intersect_domain_factor_range(
7822 __isl_take isl_map *map, __isl_take isl_map *factor)
7824 return isl_map_align_params_map_map_and(map, factor,
7825 &map_intersect_domain_factor_range);
7828 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7829 * in the space A -> C, return the intersection.
7831 * The map "factor" is first extended to a map living in the space
7832 * A -> [B -> C] and then a regular intersection is computed.
7834 static __isl_give isl_map *map_intersect_range_factor_range(
7835 __isl_take isl_map *map, __isl_take isl_map *factor)
7837 isl_space *space;
7838 isl_map *ext_factor;
7840 space = isl_space_range_factor_domain(isl_map_get_space(map));
7841 ext_factor = isl_map_universe(space);
7842 ext_factor = isl_map_range_product(ext_factor, factor);
7843 return isl_map_intersect(map, ext_factor);
7846 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7847 * in the space A -> C, return the intersection.
7849 __isl_give isl_map *isl_map_intersect_range_factor_range(
7850 __isl_take isl_map *map, __isl_take isl_map *factor)
7852 return isl_map_align_params_map_map_and(map, factor,
7853 &map_intersect_range_factor_range);
7856 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7857 __isl_take isl_map *map2)
7859 if (!map1 || !map2)
7860 goto error;
7861 map1 = isl_map_reverse(map1);
7862 map1 = isl_map_apply_range(map1, map2);
7863 return isl_map_reverse(map1);
7864 error:
7865 isl_map_free(map1);
7866 isl_map_free(map2);
7867 return NULL;
7870 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7871 __isl_take isl_map *map2)
7873 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7876 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7877 __isl_take isl_map *map2)
7879 isl_space *space;
7880 struct isl_map *result;
7881 int i, j;
7883 if (!map1 || !map2)
7884 goto error;
7886 space = isl_space_join(isl_space_copy(map1->dim),
7887 isl_space_copy(map2->dim));
7889 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
7890 if (!result)
7891 goto error;
7892 for (i = 0; i < map1->n; ++i)
7893 for (j = 0; j < map2->n; ++j) {
7894 result = isl_map_add_basic_map(result,
7895 isl_basic_map_apply_range(
7896 isl_basic_map_copy(map1->p[i]),
7897 isl_basic_map_copy(map2->p[j])));
7898 if (!result)
7899 goto error;
7901 isl_map_free(map1);
7902 isl_map_free(map2);
7903 if (result && result->n <= 1)
7904 ISL_F_SET(result, ISL_MAP_DISJOINT);
7905 return result;
7906 error:
7907 isl_map_free(map1);
7908 isl_map_free(map2);
7909 return NULL;
7912 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
7913 __isl_take isl_map *map2)
7915 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
7919 * returns range - domain
7921 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
7923 isl_space *target_space;
7924 struct isl_basic_set *bset;
7925 unsigned dim;
7926 unsigned nparam;
7927 int i;
7929 if (!bmap)
7930 goto error;
7931 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7932 bmap->dim, isl_dim_out),
7933 goto error);
7934 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
7935 dim = isl_basic_map_dim(bmap, isl_dim_in);
7936 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7937 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
7938 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
7939 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
7940 for (i = 0; i < dim; ++i) {
7941 int j = isl_basic_map_alloc_equality(bmap);
7942 if (j < 0) {
7943 bmap = isl_basic_map_free(bmap);
7944 break;
7946 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7947 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7948 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
7949 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
7951 bset = isl_basic_map_domain(bmap);
7952 bset = isl_basic_set_reset_space(bset, target_space);
7953 return bset;
7954 error:
7955 isl_basic_map_free(bmap);
7956 return NULL;
7959 /* Check that domain and range of "map" are the same.
7961 isl_stat isl_map_check_equal_tuples(__isl_keep isl_map *map)
7963 isl_space *space;
7964 isl_bool equal;
7966 space = isl_map_peek_space(map);
7967 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
7968 if (equal < 0)
7969 return isl_stat_error;
7970 if (!equal)
7971 isl_die(isl_map_get_ctx(map), isl_error_invalid,
7972 "domain and range don't match", return isl_stat_error);
7973 return isl_stat_ok;
7977 * returns range - domain
7979 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
7981 int i;
7982 isl_space *dim;
7983 struct isl_set *result;
7985 if (!map)
7986 return NULL;
7988 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
7989 map->dim, isl_dim_out),
7990 goto error);
7991 dim = isl_map_get_space(map);
7992 dim = isl_space_domain(dim);
7993 result = isl_set_alloc_space(dim, map->n, 0);
7994 if (!result)
7995 goto error;
7996 for (i = 0; i < map->n; ++i)
7997 result = isl_set_add_basic_set(result,
7998 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
7999 isl_map_free(map);
8000 return result;
8001 error:
8002 isl_map_free(map);
8003 return NULL;
8007 * returns [domain -> range] -> range - domain
8009 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8010 __isl_take isl_basic_map *bmap)
8012 int i, k;
8013 isl_space *space;
8014 isl_basic_map *domain;
8015 int nparam, n;
8016 unsigned total;
8018 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8019 bmap->dim, isl_dim_out))
8020 isl_die(bmap->ctx, isl_error_invalid,
8021 "domain and range don't match", goto error);
8023 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8024 n = isl_basic_map_dim(bmap, isl_dim_in);
8026 space = isl_basic_map_get_space(bmap);
8027 space = isl_space_from_range(isl_space_domain(space));
8028 domain = isl_basic_map_universe(space);
8030 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8031 bmap = isl_basic_map_apply_range(bmap, domain);
8032 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8034 total = isl_basic_map_total_dim(bmap);
8036 for (i = 0; i < n; ++i) {
8037 k = isl_basic_map_alloc_equality(bmap);
8038 if (k < 0)
8039 goto error;
8040 isl_seq_clr(bmap->eq[k], 1 + total);
8041 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8042 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8043 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8046 bmap = isl_basic_map_gauss(bmap, NULL);
8047 return isl_basic_map_finalize(bmap);
8048 error:
8049 isl_basic_map_free(bmap);
8050 return NULL;
8054 * returns [domain -> range] -> range - domain
8056 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8058 int i;
8059 isl_space *domain_space;
8061 if (isl_map_check_equal_tuples(map) < 0)
8062 return isl_map_free(map);
8064 map = isl_map_cow(map);
8065 if (!map)
8066 return NULL;
8068 domain_space = isl_space_domain(isl_map_get_space(map));
8069 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
8070 map->dim = isl_space_join(map->dim, isl_space_from_range(domain_space));
8071 if (!map->dim)
8072 goto error;
8073 for (i = 0; i < map->n; ++i) {
8074 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
8075 if (!map->p[i])
8076 goto error;
8078 map = isl_map_unmark_normalized(map);
8079 return map;
8080 error:
8081 isl_map_free(map);
8082 return NULL;
8085 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8087 unsigned n_in, n_out;
8089 if (!space)
8090 return NULL;
8091 n_in = isl_space_dim(space, isl_dim_in);
8092 n_out = isl_space_dim(space, isl_dim_out);
8093 if (n_in != n_out)
8094 isl_die(space->ctx, isl_error_invalid,
8095 "number of input and output dimensions needs to be "
8096 "the same", goto error);
8097 return isl_basic_map_equal(space, n_in);
8098 error:
8099 isl_space_free(space);
8100 return NULL;
8103 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
8105 return isl_map_from_basic_map(isl_basic_map_identity(dim));
8108 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8110 isl_space *dim = isl_set_get_space(set);
8111 isl_map *id;
8112 id = isl_map_identity(isl_space_map_from_set(dim));
8113 return isl_map_intersect_range(id, set);
8116 /* Construct a basic set with all set dimensions having only non-negative
8117 * values.
8119 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8120 __isl_take isl_space *space)
8122 int i;
8123 unsigned nparam;
8124 unsigned dim;
8125 struct isl_basic_set *bset;
8127 if (!space)
8128 return NULL;
8129 nparam = isl_space_dim(space, isl_dim_param);
8130 dim = isl_space_dim(space, isl_dim_set);
8131 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8132 if (!bset)
8133 return NULL;
8134 for (i = 0; i < dim; ++i) {
8135 int k = isl_basic_set_alloc_inequality(bset);
8136 if (k < 0)
8137 goto error;
8138 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
8139 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8141 return bset;
8142 error:
8143 isl_basic_set_free(bset);
8144 return NULL;
8147 /* Construct the half-space x_pos >= 0.
8149 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8150 int pos)
8152 int k;
8153 isl_basic_set *nonneg;
8155 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8156 k = isl_basic_set_alloc_inequality(nonneg);
8157 if (k < 0)
8158 goto error;
8159 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
8160 isl_int_set_si(nonneg->ineq[k][pos], 1);
8162 return isl_basic_set_finalize(nonneg);
8163 error:
8164 isl_basic_set_free(nonneg);
8165 return NULL;
8168 /* Construct the half-space x_pos <= -1.
8170 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8171 int pos)
8173 int k;
8174 isl_basic_set *neg;
8176 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8177 k = isl_basic_set_alloc_inequality(neg);
8178 if (k < 0)
8179 goto error;
8180 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
8181 isl_int_set_si(neg->ineq[k][0], -1);
8182 isl_int_set_si(neg->ineq[k][pos], -1);
8184 return isl_basic_set_finalize(neg);
8185 error:
8186 isl_basic_set_free(neg);
8187 return NULL;
8190 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8191 enum isl_dim_type type, unsigned first, unsigned n)
8193 int i;
8194 unsigned offset;
8195 isl_basic_set *nonneg;
8196 isl_basic_set *neg;
8198 if (n == 0)
8199 return set;
8201 if (isl_set_check_range(set, type, first, n) < 0)
8202 return isl_set_free(set);
8204 offset = pos(set->dim, type);
8205 for (i = 0; i < n; ++i) {
8206 nonneg = nonneg_halfspace(isl_set_get_space(set),
8207 offset + first + i);
8208 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8210 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8213 return set;
8216 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8217 int len,
8218 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8219 void *user)
8221 isl_set *half;
8223 if (!set)
8224 return isl_stat_error;
8225 if (isl_set_plain_is_empty(set)) {
8226 isl_set_free(set);
8227 return isl_stat_ok;
8229 if (first == len)
8230 return fn(set, signs, user);
8232 signs[first] = 1;
8233 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8234 1 + first));
8235 half = isl_set_intersect(half, isl_set_copy(set));
8236 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8237 goto error;
8239 signs[first] = -1;
8240 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8241 1 + first));
8242 half = isl_set_intersect(half, set);
8243 return foreach_orthant(half, signs, first + 1, len, fn, user);
8244 error:
8245 isl_set_free(set);
8246 return isl_stat_error;
8249 /* Call "fn" on the intersections of "set" with each of the orthants
8250 * (except for obviously empty intersections). The orthant is identified
8251 * by the signs array, with each entry having value 1 or -1 according
8252 * to the sign of the corresponding variable.
8254 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8255 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8256 void *user)
8258 unsigned nparam;
8259 unsigned nvar;
8260 int *signs;
8261 isl_stat r;
8263 if (!set)
8264 return isl_stat_error;
8265 if (isl_set_plain_is_empty(set))
8266 return isl_stat_ok;
8268 nparam = isl_set_dim(set, isl_dim_param);
8269 nvar = isl_set_dim(set, isl_dim_set);
8271 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8273 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8274 fn, user);
8276 free(signs);
8278 return r;
8281 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8283 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8286 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8287 __isl_keep isl_basic_map *bmap2)
8289 isl_bool is_subset;
8290 struct isl_map *map1;
8291 struct isl_map *map2;
8293 if (!bmap1 || !bmap2)
8294 return isl_bool_error;
8296 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8297 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8299 is_subset = isl_map_is_subset(map1, map2);
8301 isl_map_free(map1);
8302 isl_map_free(map2);
8304 return is_subset;
8307 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8308 __isl_keep isl_basic_set *bset2)
8310 return isl_basic_map_is_subset(bset1, bset2);
8313 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8314 __isl_keep isl_basic_map *bmap2)
8316 isl_bool is_subset;
8318 if (!bmap1 || !bmap2)
8319 return isl_bool_error;
8320 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8321 if (is_subset != isl_bool_true)
8322 return is_subset;
8323 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8324 return is_subset;
8327 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8328 __isl_keep isl_basic_set *bset2)
8330 return isl_basic_map_is_equal(
8331 bset_to_bmap(bset1), bset_to_bmap(bset2));
8334 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8336 int i;
8337 int is_empty;
8339 if (!map)
8340 return isl_bool_error;
8341 for (i = 0; i < map->n; ++i) {
8342 is_empty = isl_basic_map_is_empty(map->p[i]);
8343 if (is_empty < 0)
8344 return isl_bool_error;
8345 if (!is_empty)
8346 return isl_bool_false;
8348 return isl_bool_true;
8351 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8353 return map ? map->n == 0 : isl_bool_error;
8356 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8358 return set ? set->n == 0 : isl_bool_error;
8361 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8363 return isl_map_is_empty(set_to_map(set));
8366 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
8367 __isl_keep isl_map *map2)
8369 if (!map1 || !map2)
8370 return isl_bool_error;
8372 return isl_space_is_equal(map1->dim, map2->dim);
8375 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
8376 __isl_keep isl_set *set2)
8378 if (!set1 || !set2)
8379 return isl_bool_error;
8381 return isl_space_is_equal(set1->dim, set2->dim);
8384 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8386 isl_bool is_subset;
8388 if (!map1 || !map2)
8389 return isl_bool_error;
8390 is_subset = isl_map_is_subset(map1, map2);
8391 if (is_subset != isl_bool_true)
8392 return is_subset;
8393 is_subset = isl_map_is_subset(map2, map1);
8394 return is_subset;
8397 /* Is "map1" equal to "map2"?
8399 * First check if they are obviously equal.
8400 * If not, then perform a more detailed analysis.
8402 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8404 isl_bool equal;
8406 equal = isl_map_plain_is_equal(map1, map2);
8407 if (equal < 0 || equal)
8408 return equal;
8409 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8412 isl_bool isl_basic_map_is_strict_subset(
8413 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8415 isl_bool is_subset;
8417 if (!bmap1 || !bmap2)
8418 return isl_bool_error;
8419 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8420 if (is_subset != isl_bool_true)
8421 return is_subset;
8422 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8423 return isl_bool_not(is_subset);
8426 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8427 __isl_keep isl_map *map2)
8429 isl_bool is_subset;
8431 if (!map1 || !map2)
8432 return isl_bool_error;
8433 is_subset = isl_map_is_subset(map1, map2);
8434 if (is_subset != isl_bool_true)
8435 return is_subset;
8436 is_subset = isl_map_is_subset(map2, map1);
8437 return isl_bool_not(is_subset);
8440 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8441 __isl_keep isl_set *set2)
8443 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8446 /* Is "bmap" obviously equal to the universe with the same space?
8448 * That is, does it not have any constraints?
8450 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8452 if (!bmap)
8453 return isl_bool_error;
8454 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8457 /* Is "bset" obviously equal to the universe with the same space?
8459 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8461 return isl_basic_map_plain_is_universe(bset);
8464 /* If "c" does not involve any existentially quantified variables,
8465 * then set *univ to false and abort
8467 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8469 isl_bool *univ = user;
8470 unsigned n;
8472 n = isl_constraint_dim(c, isl_dim_div);
8473 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8474 isl_constraint_free(c);
8475 if (*univ < 0 || !*univ)
8476 return isl_stat_error;
8477 return isl_stat_ok;
8480 /* Is "bmap" equal to the universe with the same space?
8482 * First check if it is obviously equal to the universe.
8483 * If not and if there are any constraints not involving
8484 * existentially quantified variables, then it is certainly
8485 * not equal to the universe.
8486 * Otherwise, check if the universe is a subset of "bmap".
8488 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8490 isl_bool univ;
8491 isl_basic_map *test;
8493 univ = isl_basic_map_plain_is_universe(bmap);
8494 if (univ < 0 || univ)
8495 return univ;
8496 if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8497 return isl_bool_false;
8498 univ = isl_bool_true;
8499 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8500 univ)
8501 return isl_bool_error;
8502 if (univ < 0 || !univ)
8503 return univ;
8504 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8505 univ = isl_basic_map_is_subset(test, bmap);
8506 isl_basic_map_free(test);
8507 return univ;
8510 /* Is "bset" equal to the universe with the same space?
8512 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8514 return isl_basic_map_is_universe(bset);
8517 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8519 int i;
8521 if (!map)
8522 return isl_bool_error;
8524 for (i = 0; i < map->n; ++i) {
8525 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8526 if (r < 0 || r)
8527 return r;
8530 return isl_bool_false;
8533 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8535 return isl_map_plain_is_universe(set_to_map(set));
8538 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8540 struct isl_basic_set *bset = NULL;
8541 struct isl_vec *sample = NULL;
8542 isl_bool empty, non_empty;
8544 if (!bmap)
8545 return isl_bool_error;
8547 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8548 return isl_bool_true;
8550 if (isl_basic_map_plain_is_universe(bmap))
8551 return isl_bool_false;
8553 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8554 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8555 copy = isl_basic_map_remove_redundancies(copy);
8556 empty = isl_basic_map_plain_is_empty(copy);
8557 isl_basic_map_free(copy);
8558 return empty;
8561 non_empty = isl_basic_map_plain_is_non_empty(bmap);
8562 if (non_empty < 0)
8563 return isl_bool_error;
8564 if (non_empty)
8565 return isl_bool_false;
8566 isl_vec_free(bmap->sample);
8567 bmap->sample = NULL;
8568 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8569 if (!bset)
8570 return isl_bool_error;
8571 sample = isl_basic_set_sample_vec(bset);
8572 if (!sample)
8573 return isl_bool_error;
8574 empty = sample->size == 0;
8575 isl_vec_free(bmap->sample);
8576 bmap->sample = sample;
8577 if (empty)
8578 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8580 return empty;
8583 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8585 if (!bmap)
8586 return isl_bool_error;
8587 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8590 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8592 if (!bset)
8593 return isl_bool_error;
8594 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8597 /* Is "bmap" known to be non-empty?
8599 * That is, is the cached sample still valid?
8601 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8603 unsigned total;
8605 if (!bmap)
8606 return isl_bool_error;
8607 if (!bmap->sample)
8608 return isl_bool_false;
8609 total = 1 + isl_basic_map_total_dim(bmap);
8610 if (bmap->sample->size != total)
8611 return isl_bool_false;
8612 return isl_basic_map_contains(bmap, bmap->sample);
8615 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8617 return isl_basic_map_is_empty(bset_to_bmap(bset));
8620 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
8621 __isl_take isl_basic_map *bmap2)
8623 struct isl_map *map;
8624 if (!bmap1 || !bmap2)
8625 goto error;
8627 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8629 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8630 if (!map)
8631 goto error;
8632 map = isl_map_add_basic_map(map, bmap1);
8633 map = isl_map_add_basic_map(map, bmap2);
8634 return map;
8635 error:
8636 isl_basic_map_free(bmap1);
8637 isl_basic_map_free(bmap2);
8638 return NULL;
8641 struct isl_set *isl_basic_set_union(
8642 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8644 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8645 bset_to_bmap(bset2)));
8648 /* Order divs such that any div only depends on previous divs */
8649 __isl_give isl_basic_map *isl_basic_map_order_divs(
8650 __isl_take isl_basic_map *bmap)
8652 int i;
8653 int off;
8655 off = isl_basic_map_var_offset(bmap, isl_dim_div);
8656 if (off < 0)
8657 return isl_basic_map_free(bmap);
8659 for (i = 0; i < bmap->n_div; ++i) {
8660 int pos;
8661 if (isl_int_is_zero(bmap->div[i][0]))
8662 continue;
8663 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8664 bmap->n_div-i);
8665 if (pos == -1)
8666 continue;
8667 if (pos == 0)
8668 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8669 "integer division depends on itself",
8670 return isl_basic_map_free(bmap));
8671 bmap = isl_basic_map_swap_div(bmap, i, i + pos);
8672 if (!bmap)
8673 return NULL;
8674 --i;
8676 return bmap;
8679 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8681 return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8684 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8686 int i;
8688 if (!map)
8689 return 0;
8691 for (i = 0; i < map->n; ++i) {
8692 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8693 if (!map->p[i])
8694 goto error;
8697 return map;
8698 error:
8699 isl_map_free(map);
8700 return NULL;
8703 /* Sort the local variables of "bset".
8705 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8706 __isl_take isl_basic_set *bset)
8708 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8711 /* Apply the expansion computed by isl_merge_divs.
8712 * The expansion itself is given by "exp" while the resulting
8713 * list of divs is given by "div".
8715 * Move the integer divisions of "bmap" into the right position
8716 * according to "exp" and then introduce the additional integer
8717 * divisions, adding div constraints.
8718 * The moving should be done first to avoid moving coefficients
8719 * in the definitions of the extra integer divisions.
8721 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8722 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8724 int i, j;
8725 int n_div;
8727 bmap = isl_basic_map_cow(bmap);
8728 if (!bmap || !div)
8729 goto error;
8731 if (div->n_row < bmap->n_div)
8732 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8733 "not an expansion", goto error);
8735 n_div = bmap->n_div;
8736 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8737 div->n_row - n_div, 0,
8738 2 * (div->n_row - n_div));
8740 for (i = n_div; i < div->n_row; ++i)
8741 if (isl_basic_map_alloc_div(bmap) < 0)
8742 goto error;
8744 for (j = n_div - 1; j >= 0; --j) {
8745 if (exp[j] == j)
8746 break;
8747 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
8748 if (!bmap)
8749 goto error;
8751 j = 0;
8752 for (i = 0; i < div->n_row; ++i) {
8753 if (j < n_div && exp[j] == i) {
8754 j++;
8755 } else {
8756 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8757 if (isl_basic_map_div_is_marked_unknown(bmap, i))
8758 continue;
8759 bmap = isl_basic_map_add_div_constraints(bmap, i);
8760 if (!bmap)
8761 goto error;
8765 isl_mat_free(div);
8766 return bmap;
8767 error:
8768 isl_basic_map_free(bmap);
8769 isl_mat_free(div);
8770 return NULL;
8773 /* Apply the expansion computed by isl_merge_divs.
8774 * The expansion itself is given by "exp" while the resulting
8775 * list of divs is given by "div".
8777 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8778 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8780 return isl_basic_map_expand_divs(bset, div, exp);
8783 /* Look for a div in dst that corresponds to the div "div" in src.
8784 * The divs before "div" in src and dst are assumed to be the same.
8786 * Return the position of the corresponding div in dst
8787 * if there is one. Otherwise, return a position beyond the integer divisions.
8788 * Return -1 on error.
8790 static int find_div(__isl_keep isl_basic_map *dst,
8791 __isl_keep isl_basic_map *src, unsigned div)
8793 int i;
8794 unsigned n_div;
8795 int v_div;
8797 v_div = isl_basic_map_var_offset(src, isl_dim_div);
8798 if (!dst || v_div < 0)
8799 return -1;
8801 n_div = isl_basic_map_dim(dst, isl_dim_div);
8802 isl_assert(dst->ctx, div <= n_div, return -1);
8803 for (i = div; i < n_div; ++i)
8804 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
8805 isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
8806 n_div - div) == -1)
8807 return i;
8808 return n_div;
8811 /* Align the divs of "dst" to those of "src", adding divs from "src"
8812 * if needed. That is, make sure that the first src->n_div divs
8813 * of the result are equal to those of src.
8815 * The result is not finalized as by design it will have redundant
8816 * divs if any divs from "src" were copied.
8818 __isl_give isl_basic_map *isl_basic_map_align_divs(
8819 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8821 int i;
8822 isl_bool known;
8823 int extended;
8824 int v_div;
8825 unsigned dst_n_div;
8827 if (!dst || !src)
8828 return isl_basic_map_free(dst);
8830 if (src->n_div == 0)
8831 return dst;
8833 known = isl_basic_map_divs_known(src);
8834 if (known < 0)
8835 return isl_basic_map_free(dst);
8836 if (!known)
8837 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8838 "some src divs are unknown",
8839 return isl_basic_map_free(dst));
8841 v_div = isl_basic_map_var_offset(src, isl_dim_div);
8842 if (v_div < 0)
8843 return isl_basic_map_free(dst);
8845 src = isl_basic_map_order_divs(isl_basic_map_copy(src));
8846 if (!src)
8847 return isl_basic_map_free(dst);
8849 extended = 0;
8850 dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
8851 for (i = 0; i < src->n_div; ++i) {
8852 int j = find_div(dst, src, i);
8853 if (j < 0)
8854 dst = isl_basic_map_free(dst);
8855 if (j == dst_n_div) {
8856 if (!extended) {
8857 int extra = src->n_div - i;
8858 dst = isl_basic_map_cow(dst);
8859 if (!dst)
8860 goto error;
8861 dst = isl_basic_map_extend_space(dst,
8862 isl_space_copy(dst->dim),
8863 extra, 0, 2 * extra);
8864 extended = 1;
8866 j = isl_basic_map_alloc_div(dst);
8867 if (j < 0)
8868 goto error;
8869 isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
8870 isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
8871 dst_n_div++;
8872 dst = isl_basic_map_add_div_constraints(dst, j);
8873 if (!dst)
8874 goto error;
8876 if (j != i)
8877 dst = isl_basic_map_swap_div(dst, i, j);
8878 if (!dst)
8879 goto error;
8881 isl_basic_map_free(src);
8882 return dst;
8883 error:
8884 isl_basic_map_free(src);
8885 isl_basic_map_free(dst);
8886 return NULL;
8889 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
8891 int i;
8893 if (!map)
8894 return NULL;
8895 if (map->n == 0)
8896 return map;
8897 map = isl_map_compute_divs(map);
8898 map = isl_map_cow(map);
8899 if (!map)
8900 return NULL;
8902 for (i = 1; i < map->n; ++i)
8903 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8904 for (i = 1; i < map->n; ++i) {
8905 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8906 if (!map->p[i])
8907 return isl_map_free(map);
8910 map = isl_map_unmark_normalized(map);
8911 return map;
8914 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
8916 return isl_map_align_divs_internal(map);
8919 struct isl_set *isl_set_align_divs(struct isl_set *set)
8921 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
8924 /* Align the divs of the basic maps in "map" to those
8925 * of the basic maps in "list", as well as to the other basic maps in "map".
8926 * The elements in "list" are assumed to have known divs.
8928 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
8929 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
8931 int i, n;
8933 map = isl_map_compute_divs(map);
8934 map = isl_map_cow(map);
8935 if (!map || !list)
8936 return isl_map_free(map);
8937 if (map->n == 0)
8938 return map;
8940 n = isl_basic_map_list_n_basic_map(list);
8941 for (i = 0; i < n; ++i) {
8942 isl_basic_map *bmap;
8944 bmap = isl_basic_map_list_get_basic_map(list, i);
8945 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
8946 isl_basic_map_free(bmap);
8948 if (!map->p[0])
8949 return isl_map_free(map);
8951 return isl_map_align_divs_internal(map);
8954 /* Align the divs of each element of "list" to those of "bmap".
8955 * Both "bmap" and the elements of "list" are assumed to have known divs.
8957 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
8958 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
8960 int i, n;
8962 if (!list || !bmap)
8963 return isl_basic_map_list_free(list);
8965 n = isl_basic_map_list_n_basic_map(list);
8966 for (i = 0; i < n; ++i) {
8967 isl_basic_map *bmap_i;
8969 bmap_i = isl_basic_map_list_get_basic_map(list, i);
8970 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
8971 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
8974 return list;
8977 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
8978 __isl_take isl_map *map)
8980 isl_bool ok;
8982 ok = isl_map_compatible_domain(map, set);
8983 if (ok < 0)
8984 goto error;
8985 if (!ok)
8986 isl_die(isl_set_get_ctx(set), isl_error_invalid,
8987 "incompatible spaces", goto error);
8988 map = isl_map_intersect_domain(map, set);
8989 set = isl_map_range(map);
8990 return set;
8991 error:
8992 isl_set_free(set);
8993 isl_map_free(map);
8994 return NULL;
8997 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
8998 __isl_take isl_map *map)
9000 return isl_map_align_params_map_map_and(set, map, &set_apply);
9003 /* There is no need to cow as removing empty parts doesn't change
9004 * the meaning of the set.
9006 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9008 int i;
9010 if (!map)
9011 return NULL;
9013 for (i = map->n - 1; i >= 0; --i)
9014 map = remove_if_empty(map, i);
9016 return map;
9019 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
9021 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9024 /* Create a binary relation that maps the shared initial "pos" dimensions
9025 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9027 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9028 __isl_keep isl_basic_set *bset2, int pos)
9030 isl_basic_map *bmap1;
9031 isl_basic_map *bmap2;
9033 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9034 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9035 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9036 isl_dim_out, 0, pos);
9037 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9038 isl_dim_out, 0, pos);
9039 return isl_basic_map_range_product(bmap1, bmap2);
9042 /* Given two basic sets bset1 and bset2, compute the maximal difference
9043 * between the values of dimension pos in bset1 and those in bset2
9044 * for any common value of the parameters and dimensions preceding pos.
9046 static enum isl_lp_result basic_set_maximal_difference_at(
9047 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9048 int pos, isl_int *opt)
9050 isl_basic_map *bmap1;
9051 struct isl_ctx *ctx;
9052 struct isl_vec *obj;
9053 unsigned total;
9054 unsigned nparam;
9055 unsigned dim1;
9056 enum isl_lp_result res;
9058 if (!bset1 || !bset2)
9059 return isl_lp_error;
9061 nparam = isl_basic_set_n_param(bset1);
9062 dim1 = isl_basic_set_n_dim(bset1);
9064 bmap1 = join_initial(bset1, bset2, pos);
9065 if (!bmap1)
9066 return isl_lp_error;
9068 total = isl_basic_map_total_dim(bmap1);
9069 ctx = bmap1->ctx;
9070 obj = isl_vec_alloc(ctx, 1 + total);
9071 if (!obj)
9072 goto error;
9073 isl_seq_clr(obj->block.data, 1 + total);
9074 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9075 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9076 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9077 opt, NULL, NULL);
9078 isl_basic_map_free(bmap1);
9079 isl_vec_free(obj);
9080 return res;
9081 error:
9082 isl_basic_map_free(bmap1);
9083 return isl_lp_error;
9086 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9087 * for any common value of the parameters and dimensions preceding pos
9088 * in both basic sets, the values of dimension pos in bset1 are
9089 * smaller or larger than those in bset2.
9091 * Returns
9092 * 1 if bset1 follows bset2
9093 * -1 if bset1 precedes bset2
9094 * 0 if bset1 and bset2 are incomparable
9095 * -2 if some error occurred.
9097 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9098 __isl_keep isl_basic_set *bset2, int pos)
9100 isl_int opt;
9101 enum isl_lp_result res;
9102 int cmp;
9104 isl_int_init(opt);
9106 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9108 if (res == isl_lp_empty)
9109 cmp = 0;
9110 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9111 res == isl_lp_unbounded)
9112 cmp = 1;
9113 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9114 cmp = -1;
9115 else
9116 cmp = -2;
9118 isl_int_clear(opt);
9119 return cmp;
9122 /* Given two basic sets bset1 and bset2, check whether
9123 * for any common value of the parameters and dimensions preceding pos
9124 * there is a value of dimension pos in bset1 that is larger
9125 * than a value of the same dimension in bset2.
9127 * Return
9128 * 1 if there exists such a pair
9129 * 0 if there is no such pair, but there is a pair of equal values
9130 * -1 otherwise
9131 * -2 if some error occurred.
9133 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9134 __isl_keep isl_basic_set *bset2, int pos)
9136 isl_bool empty;
9137 isl_basic_map *bmap;
9138 unsigned dim1;
9140 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9141 bmap = join_initial(bset1, bset2, pos);
9142 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9143 isl_dim_out, dim1 - pos);
9144 empty = isl_basic_map_is_empty(bmap);
9145 if (empty < 0)
9146 goto error;
9147 if (empty) {
9148 isl_basic_map_free(bmap);
9149 return -1;
9151 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9152 isl_dim_out, dim1 - pos);
9153 empty = isl_basic_map_is_empty(bmap);
9154 if (empty < 0)
9155 goto error;
9156 isl_basic_map_free(bmap);
9157 if (empty)
9158 return 0;
9159 return 1;
9160 error:
9161 isl_basic_map_free(bmap);
9162 return -2;
9165 /* Given two sets set1 and set2, check whether
9166 * for any common value of the parameters and dimensions preceding pos
9167 * there is a value of dimension pos in set1 that is larger
9168 * than a value of the same dimension in set2.
9170 * Return
9171 * 1 if there exists such a pair
9172 * 0 if there is no such pair, but there is a pair of equal values
9173 * -1 otherwise
9174 * -2 if some error occurred.
9176 int isl_set_follows_at(__isl_keep isl_set *set1,
9177 __isl_keep isl_set *set2, int pos)
9179 int i, j;
9180 int follows = -1;
9182 if (!set1 || !set2)
9183 return -2;
9185 for (i = 0; i < set1->n; ++i)
9186 for (j = 0; j < set2->n; ++j) {
9187 int f;
9188 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9189 if (f == 1 || f == -2)
9190 return f;
9191 if (f > follows)
9192 follows = f;
9195 return follows;
9198 static isl_bool isl_basic_map_plain_has_fixed_var(
9199 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9201 int i;
9202 int d;
9203 unsigned total;
9205 if (!bmap)
9206 return isl_bool_error;
9207 total = isl_basic_map_total_dim(bmap);
9208 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9209 for (; d+1 > pos; --d)
9210 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9211 break;
9212 if (d != pos)
9213 continue;
9214 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9215 return isl_bool_false;
9216 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9217 return isl_bool_false;
9218 if (!isl_int_is_one(bmap->eq[i][1+d]))
9219 return isl_bool_false;
9220 if (val)
9221 isl_int_neg(*val, bmap->eq[i][0]);
9222 return isl_bool_true;
9224 return isl_bool_false;
9227 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9228 unsigned pos, isl_int *val)
9230 int i;
9231 isl_int v;
9232 isl_int tmp;
9233 isl_bool fixed;
9235 if (!map)
9236 return isl_bool_error;
9237 if (map->n == 0)
9238 return isl_bool_false;
9239 if (map->n == 1)
9240 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9241 isl_int_init(v);
9242 isl_int_init(tmp);
9243 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9244 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9245 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9246 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9247 fixed = isl_bool_false;
9249 if (val)
9250 isl_int_set(*val, v);
9251 isl_int_clear(tmp);
9252 isl_int_clear(v);
9253 return fixed;
9256 static isl_bool isl_basic_set_plain_has_fixed_var(
9257 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9259 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9260 pos, val);
9263 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9264 enum isl_dim_type type, unsigned pos, isl_int *val)
9266 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9267 return isl_bool_error;
9268 return isl_basic_map_plain_has_fixed_var(bmap,
9269 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9272 /* If "bmap" obviously lies on a hyperplane where the given dimension
9273 * has a fixed value, then return that value.
9274 * Otherwise return NaN.
9276 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9277 __isl_keep isl_basic_map *bmap,
9278 enum isl_dim_type type, unsigned pos)
9280 isl_ctx *ctx;
9281 isl_val *v;
9282 isl_bool fixed;
9284 if (!bmap)
9285 return NULL;
9286 ctx = isl_basic_map_get_ctx(bmap);
9287 v = isl_val_alloc(ctx);
9288 if (!v)
9289 return NULL;
9290 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9291 if (fixed < 0)
9292 return isl_val_free(v);
9293 if (fixed) {
9294 isl_int_set_si(v->d, 1);
9295 return v;
9297 isl_val_free(v);
9298 return isl_val_nan(ctx);
9301 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9302 enum isl_dim_type type, unsigned pos, isl_int *val)
9304 if (isl_map_check_range(map, type, pos, 1) < 0)
9305 return isl_bool_error;
9306 return isl_map_plain_has_fixed_var(map,
9307 map_offset(map, type) - 1 + pos, val);
9310 /* If "map" obviously lies on a hyperplane where the given dimension
9311 * has a fixed value, then return that value.
9312 * Otherwise return NaN.
9314 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9315 enum isl_dim_type type, unsigned pos)
9317 isl_ctx *ctx;
9318 isl_val *v;
9319 isl_bool fixed;
9321 if (!map)
9322 return NULL;
9323 ctx = isl_map_get_ctx(map);
9324 v = isl_val_alloc(ctx);
9325 if (!v)
9326 return NULL;
9327 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9328 if (fixed < 0)
9329 return isl_val_free(v);
9330 if (fixed) {
9331 isl_int_set_si(v->d, 1);
9332 return v;
9334 isl_val_free(v);
9335 return isl_val_nan(ctx);
9338 /* If "set" obviously lies on a hyperplane where the given dimension
9339 * has a fixed value, then return that value.
9340 * Otherwise return NaN.
9342 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
9343 enum isl_dim_type type, unsigned pos)
9345 return isl_map_plain_get_val_if_fixed(set, type, pos);
9348 /* Check if dimension dim has fixed value and if so and if val is not NULL,
9349 * then return this fixed value in *val.
9351 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
9352 unsigned dim, isl_int *val)
9354 return isl_basic_set_plain_has_fixed_var(bset,
9355 isl_basic_set_n_param(bset) + dim, val);
9358 /* Return -1 if the constraint "c1" should be sorted before "c2"
9359 * and 1 if it should be sorted after "c2".
9360 * Return 0 if the two constraints are the same (up to the constant term).
9362 * In particular, if a constraint involves later variables than another
9363 * then it is sorted after this other constraint.
9364 * uset_gist depends on constraints without existentially quantified
9365 * variables sorting first.
9367 * For constraints that have the same latest variable, those
9368 * with the same coefficient for this latest variable (first in absolute value
9369 * and then in actual value) are grouped together.
9370 * This is useful for detecting pairs of constraints that can
9371 * be chained in their printed representation.
9373 * Finally, within a group, constraints are sorted according to
9374 * their coefficients (excluding the constant term).
9376 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9378 isl_int **c1 = (isl_int **) p1;
9379 isl_int **c2 = (isl_int **) p2;
9380 int l1, l2;
9381 unsigned size = *(unsigned *) arg;
9382 int cmp;
9384 l1 = isl_seq_last_non_zero(*c1 + 1, size);
9385 l2 = isl_seq_last_non_zero(*c2 + 1, size);
9387 if (l1 != l2)
9388 return l1 - l2;
9390 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9391 if (cmp != 0)
9392 return cmp;
9393 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9394 if (cmp != 0)
9395 return -cmp;
9397 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9400 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
9401 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
9402 * and 0 if the two constraints are the same (up to the constant term).
9404 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
9405 isl_int *c1, isl_int *c2)
9407 unsigned total;
9409 if (!bmap)
9410 return -2;
9411 total = isl_basic_map_total_dim(bmap);
9412 return sort_constraint_cmp(&c1, &c2, &total);
9415 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9416 __isl_take isl_basic_map *bmap)
9418 unsigned total;
9420 if (!bmap)
9421 return NULL;
9422 if (bmap->n_ineq == 0)
9423 return bmap;
9424 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
9425 return bmap;
9426 total = isl_basic_map_total_dim(bmap);
9427 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9428 &sort_constraint_cmp, &total) < 0)
9429 return isl_basic_map_free(bmap);
9430 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
9431 return bmap;
9434 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9435 __isl_take isl_basic_set *bset)
9437 isl_basic_map *bmap = bset_to_bmap(bset);
9438 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9441 __isl_give isl_basic_map *isl_basic_map_normalize(
9442 __isl_take isl_basic_map *bmap)
9444 bmap = isl_basic_map_remove_redundancies(bmap);
9445 bmap = isl_basic_map_sort_constraints(bmap);
9446 return bmap;
9448 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9449 __isl_keep isl_basic_map *bmap2)
9451 int i, cmp;
9452 unsigned total;
9453 isl_space *space1, *space2;
9455 if (!bmap1 || !bmap2)
9456 return -1;
9458 if (bmap1 == bmap2)
9459 return 0;
9460 space1 = isl_basic_map_peek_space(bmap1);
9461 space2 = isl_basic_map_peek_space(bmap2);
9462 cmp = isl_space_cmp(space1, space2);
9463 if (cmp)
9464 return cmp;
9465 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9466 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9467 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9468 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9469 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9470 return 0;
9471 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9472 return 1;
9473 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9474 return -1;
9475 if (bmap1->n_eq != bmap2->n_eq)
9476 return bmap1->n_eq - bmap2->n_eq;
9477 if (bmap1->n_ineq != bmap2->n_ineq)
9478 return bmap1->n_ineq - bmap2->n_ineq;
9479 if (bmap1->n_div != bmap2->n_div)
9480 return bmap1->n_div - bmap2->n_div;
9481 total = isl_basic_map_total_dim(bmap1);
9482 for (i = 0; i < bmap1->n_eq; ++i) {
9483 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9484 if (cmp)
9485 return cmp;
9487 for (i = 0; i < bmap1->n_ineq; ++i) {
9488 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9489 if (cmp)
9490 return cmp;
9492 for (i = 0; i < bmap1->n_div; ++i) {
9493 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9494 if (cmp)
9495 return cmp;
9497 return 0;
9500 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9501 __isl_keep isl_basic_set *bset2)
9503 return isl_basic_map_plain_cmp(bset1, bset2);
9506 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9508 int i, cmp;
9510 if (set1 == set2)
9511 return 0;
9512 if (set1->n != set2->n)
9513 return set1->n - set2->n;
9515 for (i = 0; i < set1->n; ++i) {
9516 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9517 if (cmp)
9518 return cmp;
9521 return 0;
9524 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9525 __isl_keep isl_basic_map *bmap2)
9527 if (!bmap1 || !bmap2)
9528 return isl_bool_error;
9529 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9532 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9533 __isl_keep isl_basic_set *bset2)
9535 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9536 bset_to_bmap(bset2));
9539 static int qsort_bmap_cmp(const void *p1, const void *p2)
9541 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9542 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9544 return isl_basic_map_plain_cmp(bmap1, bmap2);
9547 /* Sort the basic maps of "map" and remove duplicate basic maps.
9549 * While removing basic maps, we make sure that the basic maps remain
9550 * sorted because isl_map_normalize expects the basic maps of the result
9551 * to be sorted.
9553 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9555 int i, j;
9557 map = isl_map_remove_empty_parts(map);
9558 if (!map)
9559 return NULL;
9560 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9561 for (i = map->n - 1; i >= 1; --i) {
9562 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9563 continue;
9564 isl_basic_map_free(map->p[i-1]);
9565 for (j = i; j < map->n; ++j)
9566 map->p[j - 1] = map->p[j];
9567 map->n--;
9570 return map;
9573 /* Remove obvious duplicates among the basic maps of "map".
9575 * Unlike isl_map_normalize, this function does not remove redundant
9576 * constraints and only removes duplicates that have exactly the same
9577 * constraints in the input. It does sort the constraints and
9578 * the basic maps to ease the detection of duplicates.
9580 * If "map" has already been normalized or if the basic maps are
9581 * disjoint, then there can be no duplicates.
9583 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9585 int i;
9586 isl_basic_map *bmap;
9588 if (!map)
9589 return NULL;
9590 if (map->n <= 1)
9591 return map;
9592 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9593 return map;
9594 for (i = 0; i < map->n; ++i) {
9595 bmap = isl_basic_map_copy(map->p[i]);
9596 bmap = isl_basic_map_sort_constraints(bmap);
9597 if (!bmap)
9598 return isl_map_free(map);
9599 isl_basic_map_free(map->p[i]);
9600 map->p[i] = bmap;
9603 map = sort_and_remove_duplicates(map);
9604 return map;
9607 /* We normalize in place, but if anything goes wrong we need
9608 * to return NULL, so we need to make sure we don't change the
9609 * meaning of any possible other copies of map.
9611 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9613 int i;
9614 struct isl_basic_map *bmap;
9616 if (!map)
9617 return NULL;
9618 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9619 return map;
9620 for (i = 0; i < map->n; ++i) {
9621 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9622 if (!bmap)
9623 goto error;
9624 isl_basic_map_free(map->p[i]);
9625 map->p[i] = bmap;
9628 map = sort_and_remove_duplicates(map);
9629 if (map)
9630 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9631 return map;
9632 error:
9633 isl_map_free(map);
9634 return NULL;
9637 struct isl_set *isl_set_normalize(struct isl_set *set)
9639 return set_from_map(isl_map_normalize(set_to_map(set)));
9642 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9643 __isl_keep isl_map *map2)
9645 int i;
9646 isl_bool equal;
9648 if (!map1 || !map2)
9649 return isl_bool_error;
9651 if (map1 == map2)
9652 return isl_bool_true;
9653 if (!isl_space_is_equal(map1->dim, map2->dim))
9654 return isl_bool_false;
9656 map1 = isl_map_copy(map1);
9657 map2 = isl_map_copy(map2);
9658 map1 = isl_map_normalize(map1);
9659 map2 = isl_map_normalize(map2);
9660 if (!map1 || !map2)
9661 goto error;
9662 equal = map1->n == map2->n;
9663 for (i = 0; equal && i < map1->n; ++i) {
9664 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9665 if (equal < 0)
9666 goto error;
9668 isl_map_free(map1);
9669 isl_map_free(map2);
9670 return equal;
9671 error:
9672 isl_map_free(map1);
9673 isl_map_free(map2);
9674 return isl_bool_error;
9677 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9678 __isl_keep isl_set *set2)
9680 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9683 /* Return the basic maps in "map" as a list.
9685 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9686 __isl_keep isl_map *map)
9688 int i;
9689 isl_ctx *ctx;
9690 isl_basic_map_list *list;
9692 if (!map)
9693 return NULL;
9694 ctx = isl_map_get_ctx(map);
9695 list = isl_basic_map_list_alloc(ctx, map->n);
9697 for (i = 0; i < map->n; ++i) {
9698 isl_basic_map *bmap;
9700 bmap = isl_basic_map_copy(map->p[i]);
9701 list = isl_basic_map_list_add(list, bmap);
9704 return list;
9707 /* Return the intersection of the elements in the non-empty list "list".
9708 * All elements are assumed to live in the same space.
9710 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9711 __isl_take isl_basic_map_list *list)
9713 int i, n;
9714 isl_basic_map *bmap;
9716 if (!list)
9717 return NULL;
9718 n = isl_basic_map_list_n_basic_map(list);
9719 if (n < 1)
9720 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9721 "expecting non-empty list", goto error);
9723 bmap = isl_basic_map_list_get_basic_map(list, 0);
9724 for (i = 1; i < n; ++i) {
9725 isl_basic_map *bmap_i;
9727 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9728 bmap = isl_basic_map_intersect(bmap, bmap_i);
9731 isl_basic_map_list_free(list);
9732 return bmap;
9733 error:
9734 isl_basic_map_list_free(list);
9735 return NULL;
9738 /* Return the intersection of the elements in the non-empty list "list".
9739 * All elements are assumed to live in the same space.
9741 __isl_give isl_basic_set *isl_basic_set_list_intersect(
9742 __isl_take isl_basic_set_list *list)
9744 return isl_basic_map_list_intersect(list);
9747 /* Return the union of the elements of "list".
9748 * The list is required to have at least one element.
9750 __isl_give isl_set *isl_basic_set_list_union(
9751 __isl_take isl_basic_set_list *list)
9753 int i, n;
9754 isl_space *space;
9755 isl_basic_set *bset;
9756 isl_set *set;
9758 if (!list)
9759 return NULL;
9760 n = isl_basic_set_list_n_basic_set(list);
9761 if (n < 1)
9762 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9763 "expecting non-empty list", goto error);
9765 bset = isl_basic_set_list_get_basic_set(list, 0);
9766 space = isl_basic_set_get_space(bset);
9767 isl_basic_set_free(bset);
9769 set = isl_set_alloc_space(space, n, 0);
9770 for (i = 0; i < n; ++i) {
9771 bset = isl_basic_set_list_get_basic_set(list, i);
9772 set = isl_set_add_basic_set(set, bset);
9775 isl_basic_set_list_free(list);
9776 return set;
9777 error:
9778 isl_basic_set_list_free(list);
9779 return NULL;
9782 /* Return the union of the elements in the non-empty list "list".
9783 * All elements are assumed to live in the same space.
9785 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9787 int i, n;
9788 isl_set *set;
9790 if (!list)
9791 return NULL;
9792 n = isl_set_list_n_set(list);
9793 if (n < 1)
9794 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9795 "expecting non-empty list", goto error);
9797 set = isl_set_list_get_set(list, 0);
9798 for (i = 1; i < n; ++i) {
9799 isl_set *set_i;
9801 set_i = isl_set_list_get_set(list, i);
9802 set = isl_set_union(set, set_i);
9805 isl_set_list_free(list);
9806 return set;
9807 error:
9808 isl_set_list_free(list);
9809 return NULL;
9812 __isl_give isl_basic_map *isl_basic_map_product(
9813 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9815 isl_space *space_result = NULL;
9816 struct isl_basic_map *bmap;
9817 unsigned in1, in2, out1, out2, nparam, total, pos;
9818 struct isl_dim_map *dim_map1, *dim_map2;
9820 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9821 goto error;
9822 space_result = isl_space_product(isl_space_copy(bmap1->dim),
9823 isl_space_copy(bmap2->dim));
9825 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9826 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9827 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9828 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9829 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9831 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9832 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9833 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9834 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9835 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9836 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9837 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9838 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9839 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9840 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9841 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9843 bmap = isl_basic_map_alloc_space(space_result,
9844 bmap1->n_div + bmap2->n_div,
9845 bmap1->n_eq + bmap2->n_eq,
9846 bmap1->n_ineq + bmap2->n_ineq);
9847 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9848 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9849 bmap = isl_basic_map_simplify(bmap);
9850 return isl_basic_map_finalize(bmap);
9851 error:
9852 isl_basic_map_free(bmap1);
9853 isl_basic_map_free(bmap2);
9854 return NULL;
9857 __isl_give isl_basic_map *isl_basic_map_flat_product(
9858 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9860 isl_basic_map *prod;
9862 prod = isl_basic_map_product(bmap1, bmap2);
9863 prod = isl_basic_map_flatten(prod);
9864 return prod;
9867 __isl_give isl_basic_set *isl_basic_set_flat_product(
9868 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9870 return isl_basic_map_flat_range_product(bset1, bset2);
9873 __isl_give isl_basic_map *isl_basic_map_domain_product(
9874 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9876 isl_space *space1, *space2;
9877 isl_space *space_result = NULL;
9878 isl_basic_map *bmap;
9879 unsigned in1, in2, out, nparam, total, pos;
9880 struct isl_dim_map *dim_map1, *dim_map2;
9882 if (!bmap1 || !bmap2)
9883 goto error;
9885 space1 = isl_basic_map_get_space(bmap1);
9886 space2 = isl_basic_map_get_space(bmap2);
9887 space_result = isl_space_domain_product(space1, space2);
9889 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9890 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9891 out = isl_basic_map_dim(bmap1, isl_dim_out);
9892 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9894 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9895 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9896 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9897 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9898 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9899 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9900 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9901 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9902 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9903 isl_dim_map_div(dim_map1, bmap1, pos += out);
9904 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9906 bmap = isl_basic_map_alloc_space(space_result,
9907 bmap1->n_div + bmap2->n_div,
9908 bmap1->n_eq + bmap2->n_eq,
9909 bmap1->n_ineq + bmap2->n_ineq);
9910 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9911 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9912 bmap = isl_basic_map_simplify(bmap);
9913 return isl_basic_map_finalize(bmap);
9914 error:
9915 isl_basic_map_free(bmap1);
9916 isl_basic_map_free(bmap2);
9917 return NULL;
9920 __isl_give isl_basic_map *isl_basic_map_range_product(
9921 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9923 isl_bool rational;
9924 isl_space *space_result = NULL;
9925 isl_basic_map *bmap;
9926 unsigned in, out1, out2, nparam, total, pos;
9927 struct isl_dim_map *dim_map1, *dim_map2;
9929 rational = isl_basic_map_is_rational(bmap1);
9930 if (rational >= 0 && rational)
9931 rational = isl_basic_map_is_rational(bmap2);
9932 if (!bmap1 || !bmap2 || rational < 0)
9933 goto error;
9935 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9936 goto error;
9938 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
9939 isl_space_copy(bmap2->dim));
9941 in = isl_basic_map_dim(bmap1, isl_dim_in);
9942 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9943 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9944 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9946 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
9947 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9948 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9949 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9950 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9951 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9952 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
9953 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
9954 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9955 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9956 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9958 bmap = isl_basic_map_alloc_space(space_result,
9959 bmap1->n_div + bmap2->n_div,
9960 bmap1->n_eq + bmap2->n_eq,
9961 bmap1->n_ineq + bmap2->n_ineq);
9962 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9963 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9964 if (rational)
9965 bmap = isl_basic_map_set_rational(bmap);
9966 bmap = isl_basic_map_simplify(bmap);
9967 return isl_basic_map_finalize(bmap);
9968 error:
9969 isl_basic_map_free(bmap1);
9970 isl_basic_map_free(bmap2);
9971 return NULL;
9974 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
9975 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9977 isl_basic_map *prod;
9979 prod = isl_basic_map_range_product(bmap1, bmap2);
9980 prod = isl_basic_map_flatten_range(prod);
9981 return prod;
9984 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
9985 * and collect the results.
9986 * The result live in the space obtained by calling "space_product"
9987 * on the spaces of "map1" and "map2".
9988 * If "remove_duplicates" is set then the result may contain duplicates
9989 * (even if the inputs do not) and so we try and remove the obvious
9990 * duplicates.
9992 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
9993 __isl_take isl_map *map2,
9994 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
9995 __isl_take isl_space *right),
9996 __isl_give isl_basic_map *(*basic_map_product)(
9997 __isl_take isl_basic_map *left,
9998 __isl_take isl_basic_map *right),
9999 int remove_duplicates)
10001 unsigned flags = 0;
10002 struct isl_map *result;
10003 int i, j;
10004 isl_bool m;
10006 m = isl_map_has_equal_params(map1, map2);
10007 if (m < 0)
10008 goto error;
10009 if (!m)
10010 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10011 "parameters don't match", goto error);
10013 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10014 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10015 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10017 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10018 isl_space_copy(map2->dim)),
10019 map1->n * map2->n, flags);
10020 if (!result)
10021 goto error;
10022 for (i = 0; i < map1->n; ++i)
10023 for (j = 0; j < map2->n; ++j) {
10024 struct isl_basic_map *part;
10025 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10026 isl_basic_map_copy(map2->p[j]));
10027 if (isl_basic_map_is_empty(part))
10028 isl_basic_map_free(part);
10029 else
10030 result = isl_map_add_basic_map(result, part);
10031 if (!result)
10032 goto error;
10034 if (remove_duplicates)
10035 result = isl_map_remove_obvious_duplicates(result);
10036 isl_map_free(map1);
10037 isl_map_free(map2);
10038 return result;
10039 error:
10040 isl_map_free(map1);
10041 isl_map_free(map2);
10042 return NULL;
10045 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10047 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
10048 __isl_take isl_map *map2)
10050 return map_product(map1, map2, &isl_space_product,
10051 &isl_basic_map_product, 0);
10054 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10055 __isl_take isl_map *map2)
10057 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
10060 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10062 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10063 __isl_take isl_map *map2)
10065 isl_map *prod;
10067 prod = isl_map_product(map1, map2);
10068 prod = isl_map_flatten(prod);
10069 return prod;
10072 /* Given two set A and B, construct its Cartesian product A x B.
10074 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
10076 return isl_map_range_product(set1, set2);
10079 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10080 __isl_take isl_set *set2)
10082 return isl_map_flat_range_product(set1, set2);
10085 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10087 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
10088 __isl_take isl_map *map2)
10090 return map_product(map1, map2, &isl_space_domain_product,
10091 &isl_basic_map_domain_product, 1);
10094 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10096 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
10097 __isl_take isl_map *map2)
10099 return map_product(map1, map2, &isl_space_range_product,
10100 &isl_basic_map_range_product, 1);
10103 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10104 __isl_take isl_map *map2)
10106 return isl_map_align_params_map_map_and(map1, map2,
10107 &map_domain_product_aligned);
10110 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10111 __isl_take isl_map *map2)
10113 return isl_map_align_params_map_map_and(map1, map2,
10114 &map_range_product_aligned);
10117 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10119 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10121 isl_space *space;
10122 int total1, keep1, total2, keep2;
10124 if (!map)
10125 return NULL;
10126 if (!isl_space_domain_is_wrapping(map->dim) ||
10127 !isl_space_range_is_wrapping(map->dim))
10128 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10129 "not a product", return isl_map_free(map));
10131 space = isl_map_get_space(map);
10132 total1 = isl_space_dim(space, isl_dim_in);
10133 total2 = isl_space_dim(space, isl_dim_out);
10134 space = isl_space_factor_domain(space);
10135 keep1 = isl_space_dim(space, isl_dim_in);
10136 keep2 = isl_space_dim(space, isl_dim_out);
10137 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10138 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10139 map = isl_map_reset_space(map, space);
10141 return map;
10144 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10146 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10148 isl_space *space;
10149 int total1, keep1, total2, keep2;
10151 if (!map)
10152 return NULL;
10153 if (!isl_space_domain_is_wrapping(map->dim) ||
10154 !isl_space_range_is_wrapping(map->dim))
10155 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10156 "not a product", return isl_map_free(map));
10158 space = isl_map_get_space(map);
10159 total1 = isl_space_dim(space, isl_dim_in);
10160 total2 = isl_space_dim(space, isl_dim_out);
10161 space = isl_space_factor_range(space);
10162 keep1 = isl_space_dim(space, isl_dim_in);
10163 keep2 = isl_space_dim(space, isl_dim_out);
10164 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10165 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10166 map = isl_map_reset_space(map, space);
10168 return map;
10171 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10173 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10175 isl_space *space;
10176 int total, keep;
10178 if (!map)
10179 return NULL;
10180 if (!isl_space_domain_is_wrapping(map->dim))
10181 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10182 "domain is not a product", return isl_map_free(map));
10184 space = isl_map_get_space(map);
10185 total = isl_space_dim(space, isl_dim_in);
10186 space = isl_space_domain_factor_domain(space);
10187 keep = isl_space_dim(space, isl_dim_in);
10188 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10189 map = isl_map_reset_space(map, space);
10191 return map;
10194 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10196 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10198 isl_space *space;
10199 int total, keep;
10201 if (!map)
10202 return NULL;
10203 if (!isl_space_domain_is_wrapping(map->dim))
10204 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10205 "domain is not a product", return isl_map_free(map));
10207 space = isl_map_get_space(map);
10208 total = isl_space_dim(space, isl_dim_in);
10209 space = isl_space_domain_factor_range(space);
10210 keep = isl_space_dim(space, isl_dim_in);
10211 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10212 map = isl_map_reset_space(map, space);
10214 return map;
10217 /* Given a map A -> [B -> C], extract the map A -> B.
10219 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10221 isl_space *space;
10222 int total, keep;
10224 if (!map)
10225 return NULL;
10226 if (!isl_space_range_is_wrapping(map->dim))
10227 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10228 "range is not a product", return isl_map_free(map));
10230 space = isl_map_get_space(map);
10231 total = isl_space_dim(space, isl_dim_out);
10232 space = isl_space_range_factor_domain(space);
10233 keep = isl_space_dim(space, isl_dim_out);
10234 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10235 map = isl_map_reset_space(map, space);
10237 return map;
10240 /* Given a map A -> [B -> C], extract the map A -> C.
10242 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10244 isl_space *space;
10245 int total, keep;
10247 if (!map)
10248 return NULL;
10249 if (!isl_space_range_is_wrapping(map->dim))
10250 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10251 "range is not a product", return isl_map_free(map));
10253 space = isl_map_get_space(map);
10254 total = isl_space_dim(space, isl_dim_out);
10255 space = isl_space_range_factor_range(space);
10256 keep = isl_space_dim(space, isl_dim_out);
10257 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10258 map = isl_map_reset_space(map, space);
10260 return map;
10263 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10265 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10266 __isl_take isl_map *map2)
10268 isl_map *prod;
10270 prod = isl_map_domain_product(map1, map2);
10271 prod = isl_map_flatten_domain(prod);
10272 return prod;
10275 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10277 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10278 __isl_take isl_map *map2)
10280 isl_map *prod;
10282 prod = isl_map_range_product(map1, map2);
10283 prod = isl_map_flatten_range(prod);
10284 return prod;
10287 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10289 int i;
10290 uint32_t hash = isl_hash_init();
10291 unsigned total;
10293 if (!bmap)
10294 return 0;
10295 bmap = isl_basic_map_copy(bmap);
10296 bmap = isl_basic_map_normalize(bmap);
10297 if (!bmap)
10298 return 0;
10299 total = isl_basic_map_total_dim(bmap);
10300 isl_hash_byte(hash, bmap->n_eq & 0xFF);
10301 for (i = 0; i < bmap->n_eq; ++i) {
10302 uint32_t c_hash;
10303 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
10304 isl_hash_hash(hash, c_hash);
10306 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
10307 for (i = 0; i < bmap->n_ineq; ++i) {
10308 uint32_t c_hash;
10309 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
10310 isl_hash_hash(hash, c_hash);
10312 isl_hash_byte(hash, bmap->n_div & 0xFF);
10313 for (i = 0; i < bmap->n_div; ++i) {
10314 uint32_t c_hash;
10315 if (isl_int_is_zero(bmap->div[i][0]))
10316 continue;
10317 isl_hash_byte(hash, i & 0xFF);
10318 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
10319 isl_hash_hash(hash, c_hash);
10321 isl_basic_map_free(bmap);
10322 return hash;
10325 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
10327 return isl_basic_map_get_hash(bset_to_bmap(bset));
10330 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
10332 int i;
10333 uint32_t hash;
10335 if (!map)
10336 return 0;
10337 map = isl_map_copy(map);
10338 map = isl_map_normalize(map);
10339 if (!map)
10340 return 0;
10342 hash = isl_hash_init();
10343 for (i = 0; i < map->n; ++i) {
10344 uint32_t bmap_hash;
10345 bmap_hash = isl_basic_map_get_hash(map->p[i]);
10346 isl_hash_hash(hash, bmap_hash);
10349 isl_map_free(map);
10351 return hash;
10354 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
10356 return isl_map_get_hash(set_to_map(set));
10359 /* Return the number of basic maps in the (current) representation of "map".
10361 int isl_map_n_basic_map(__isl_keep isl_map *map)
10363 return map ? map->n : 0;
10366 int isl_set_n_basic_set(__isl_keep isl_set *set)
10368 return set ? set->n : 0;
10371 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
10372 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10374 int i;
10376 if (!map)
10377 return isl_stat_error;
10379 for (i = 0; i < map->n; ++i)
10380 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10381 return isl_stat_error;
10383 return isl_stat_ok;
10386 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10387 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10389 int i;
10391 if (!set)
10392 return isl_stat_error;
10394 for (i = 0; i < set->n; ++i)
10395 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10396 return isl_stat_error;
10398 return isl_stat_ok;
10401 /* Return a list of basic sets, the union of which is equal to "set".
10403 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10404 __isl_keep isl_set *set)
10406 int i;
10407 isl_basic_set_list *list;
10409 if (!set)
10410 return NULL;
10412 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10413 for (i = 0; i < set->n; ++i) {
10414 isl_basic_set *bset;
10416 bset = isl_basic_set_copy(set->p[i]);
10417 list = isl_basic_set_list_add(list, bset);
10420 return list;
10423 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10425 isl_space *space;
10427 if (!bset)
10428 return NULL;
10430 bset = isl_basic_set_cow(bset);
10431 if (!bset)
10432 return NULL;
10434 space = isl_basic_set_get_space(bset);
10435 space = isl_space_lift(space, bset->n_div);
10436 if (!space)
10437 goto error;
10438 isl_space_free(bset->dim);
10439 bset->dim = space;
10440 bset->extra -= bset->n_div;
10441 bset->n_div = 0;
10443 bset = isl_basic_set_finalize(bset);
10445 return bset;
10446 error:
10447 isl_basic_set_free(bset);
10448 return NULL;
10451 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10453 int i;
10454 isl_space *space;
10455 unsigned n_div;
10457 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10459 if (!set)
10460 return NULL;
10462 set = isl_set_cow(set);
10463 if (!set)
10464 return NULL;
10466 n_div = set->p[0]->n_div;
10467 space = isl_set_get_space(set);
10468 space = isl_space_lift(space, n_div);
10469 if (!space)
10470 goto error;
10471 isl_space_free(set->dim);
10472 set->dim = space;
10474 for (i = 0; i < set->n; ++i) {
10475 set->p[i] = isl_basic_set_lift(set->p[i]);
10476 if (!set->p[i])
10477 goto error;
10480 return set;
10481 error:
10482 isl_set_free(set);
10483 return NULL;
10486 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10488 unsigned dim;
10489 int size = 0;
10491 if (!bset)
10492 return -1;
10494 dim = isl_basic_set_total_dim(bset);
10495 size += bset->n_eq * (1 + dim);
10496 size += bset->n_ineq * (1 + dim);
10497 size += bset->n_div * (2 + dim);
10499 return size;
10502 int isl_set_size(__isl_keep isl_set *set)
10504 int i;
10505 int size = 0;
10507 if (!set)
10508 return -1;
10510 for (i = 0; i < set->n; ++i)
10511 size += isl_basic_set_size(set->p[i]);
10513 return size;
10516 /* Check if there is any lower bound (if lower == 0) and/or upper
10517 * bound (if upper == 0) on the specified dim.
10519 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10520 enum isl_dim_type type, unsigned pos, int lower, int upper)
10522 int i;
10524 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10525 return isl_bool_error;
10527 pos += isl_basic_map_offset(bmap, type);
10529 for (i = 0; i < bmap->n_div; ++i) {
10530 if (isl_int_is_zero(bmap->div[i][0]))
10531 continue;
10532 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10533 return isl_bool_true;
10536 for (i = 0; i < bmap->n_eq; ++i)
10537 if (!isl_int_is_zero(bmap->eq[i][pos]))
10538 return isl_bool_true;
10540 for (i = 0; i < bmap->n_ineq; ++i) {
10541 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10542 if (sgn > 0)
10543 lower = 1;
10544 if (sgn < 0)
10545 upper = 1;
10548 return lower && upper;
10551 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10552 enum isl_dim_type type, unsigned pos)
10554 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10557 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10558 enum isl_dim_type type, unsigned pos)
10560 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10563 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10564 enum isl_dim_type type, unsigned pos)
10566 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10569 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10570 enum isl_dim_type type, unsigned pos)
10572 int i;
10574 if (!map)
10575 return isl_bool_error;
10577 for (i = 0; i < map->n; ++i) {
10578 isl_bool bounded;
10579 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10580 if (bounded < 0 || !bounded)
10581 return bounded;
10584 return isl_bool_true;
10587 /* Return true if the specified dim is involved in both an upper bound
10588 * and a lower bound.
10590 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10591 enum isl_dim_type type, unsigned pos)
10593 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10596 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10598 static isl_bool has_any_bound(__isl_keep isl_map *map,
10599 enum isl_dim_type type, unsigned pos,
10600 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10601 enum isl_dim_type type, unsigned pos))
10603 int i;
10605 if (!map)
10606 return isl_bool_error;
10608 for (i = 0; i < map->n; ++i) {
10609 isl_bool bounded;
10610 bounded = fn(map->p[i], type, pos);
10611 if (bounded < 0 || bounded)
10612 return bounded;
10615 return isl_bool_false;
10618 /* Return 1 if the specified dim is involved in any lower bound.
10620 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10621 enum isl_dim_type type, unsigned pos)
10623 return has_any_bound(set, type, pos,
10624 &isl_basic_map_dim_has_lower_bound);
10627 /* Return 1 if the specified dim is involved in any upper bound.
10629 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10630 enum isl_dim_type type, unsigned pos)
10632 return has_any_bound(set, type, pos,
10633 &isl_basic_map_dim_has_upper_bound);
10636 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10638 static isl_bool has_bound(__isl_keep isl_map *map,
10639 enum isl_dim_type type, unsigned pos,
10640 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10641 enum isl_dim_type type, unsigned pos))
10643 int i;
10645 if (!map)
10646 return isl_bool_error;
10648 for (i = 0; i < map->n; ++i) {
10649 isl_bool bounded;
10650 bounded = fn(map->p[i], type, pos);
10651 if (bounded < 0 || !bounded)
10652 return bounded;
10655 return isl_bool_true;
10658 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10660 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10661 enum isl_dim_type type, unsigned pos)
10663 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10666 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10668 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10669 enum isl_dim_type type, unsigned pos)
10671 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10674 /* For each of the "n" variables starting at "first", determine
10675 * the sign of the variable and put the results in the first "n"
10676 * elements of the array "signs".
10677 * Sign
10678 * 1 means that the variable is non-negative
10679 * -1 means that the variable is non-positive
10680 * 0 means the variable attains both positive and negative values.
10682 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10683 unsigned first, unsigned n, int *signs)
10685 isl_vec *bound = NULL;
10686 struct isl_tab *tab = NULL;
10687 struct isl_tab_undo *snap;
10688 int i;
10690 if (!bset || !signs)
10691 return isl_stat_error;
10693 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10694 tab = isl_tab_from_basic_set(bset, 0);
10695 if (!bound || !tab)
10696 goto error;
10698 isl_seq_clr(bound->el, bound->size);
10699 isl_int_set_si(bound->el[0], -1);
10701 snap = isl_tab_snap(tab);
10702 for (i = 0; i < n; ++i) {
10703 int empty;
10705 isl_int_set_si(bound->el[1 + first + i], -1);
10706 if (isl_tab_add_ineq(tab, bound->el) < 0)
10707 goto error;
10708 empty = tab->empty;
10709 isl_int_set_si(bound->el[1 + first + i], 0);
10710 if (isl_tab_rollback(tab, snap) < 0)
10711 goto error;
10713 if (empty) {
10714 signs[i] = 1;
10715 continue;
10718 isl_int_set_si(bound->el[1 + first + i], 1);
10719 if (isl_tab_add_ineq(tab, bound->el) < 0)
10720 goto error;
10721 empty = tab->empty;
10722 isl_int_set_si(bound->el[1 + first + i], 0);
10723 if (isl_tab_rollback(tab, snap) < 0)
10724 goto error;
10726 signs[i] = empty ? -1 : 0;
10729 isl_tab_free(tab);
10730 isl_vec_free(bound);
10731 return isl_stat_ok;
10732 error:
10733 isl_tab_free(tab);
10734 isl_vec_free(bound);
10735 return isl_stat_error;
10738 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10739 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10741 if (!bset || !signs)
10742 return isl_stat_error;
10743 if (isl_basic_set_check_range(bset, type, first, n) < 0)
10744 return isl_stat_error;
10746 first += pos(bset->dim, type) - 1;
10747 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10750 /* Is it possible for the integer division "div" to depend (possibly
10751 * indirectly) on any output dimensions?
10753 * If the div is undefined, then we conservatively assume that it
10754 * may depend on them.
10755 * Otherwise, we check if it actually depends on them or on any integer
10756 * divisions that may depend on them.
10758 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10760 int i;
10761 unsigned n_out, o_out;
10762 unsigned n_div, o_div;
10764 if (isl_int_is_zero(bmap->div[div][0]))
10765 return isl_bool_true;
10767 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10768 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10770 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10771 return isl_bool_true;
10773 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10774 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10776 for (i = 0; i < n_div; ++i) {
10777 isl_bool may_involve;
10779 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10780 continue;
10781 may_involve = div_may_involve_output(bmap, i);
10782 if (may_involve < 0 || may_involve)
10783 return may_involve;
10786 return isl_bool_false;
10789 /* Return the first integer division of "bmap" in the range
10790 * [first, first + n[ that may depend on any output dimensions and
10791 * that has a non-zero coefficient in "c" (where the first coefficient
10792 * in "c" corresponds to integer division "first").
10794 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10795 isl_int *c, int first, int n)
10797 int k;
10799 if (!bmap)
10800 return -1;
10802 for (k = first; k < first + n; ++k) {
10803 isl_bool may_involve;
10805 if (isl_int_is_zero(c[k]))
10806 continue;
10807 may_involve = div_may_involve_output(bmap, k);
10808 if (may_involve < 0)
10809 return -1;
10810 if (may_involve)
10811 return k;
10814 return first + n;
10817 /* Look for a pair of inequality constraints in "bmap" of the form
10819 * -l + i >= 0 or i >= l
10820 * and
10821 * n + l - i >= 0 or i <= l + n
10823 * with n < "m" and i the output dimension at position "pos".
10824 * (Note that n >= 0 as otherwise the two constraints would conflict.)
10825 * Furthermore, "l" is only allowed to involve parameters, input dimensions
10826 * and earlier output dimensions, as well as integer divisions that do
10827 * not involve any of the output dimensions.
10829 * Return the index of the first inequality constraint or bmap->n_ineq
10830 * if no such pair can be found.
10832 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10833 int pos, isl_int m)
10835 int i, j;
10836 isl_ctx *ctx;
10837 unsigned total;
10838 unsigned n_div, o_div;
10839 unsigned n_out, o_out;
10840 int less;
10842 if (!bmap)
10843 return -1;
10845 ctx = isl_basic_map_get_ctx(bmap);
10846 total = isl_basic_map_total_dim(bmap);
10847 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10848 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10849 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10850 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10851 for (i = 0; i < bmap->n_ineq; ++i) {
10852 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
10853 continue;
10854 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
10855 n_out - (pos + 1)) != -1)
10856 continue;
10857 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
10858 0, n_div) < n_div)
10859 continue;
10860 for (j = i + 1; j < bmap->n_ineq; ++j) {
10861 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
10862 ctx->one))
10863 continue;
10864 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
10865 bmap->ineq[j] + 1, total))
10866 continue;
10867 break;
10869 if (j >= bmap->n_ineq)
10870 continue;
10871 isl_int_add(bmap->ineq[i][0],
10872 bmap->ineq[i][0], bmap->ineq[j][0]);
10873 less = isl_int_abs_lt(bmap->ineq[i][0], m);
10874 isl_int_sub(bmap->ineq[i][0],
10875 bmap->ineq[i][0], bmap->ineq[j][0]);
10876 if (!less)
10877 continue;
10878 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
10879 return i;
10880 else
10881 return j;
10884 return bmap->n_ineq;
10887 /* Return the index of the equality of "bmap" that defines
10888 * the output dimension "pos" in terms of earlier dimensions.
10889 * The equality may also involve integer divisions, as long
10890 * as those integer divisions are defined in terms of
10891 * parameters or input dimensions.
10892 * In this case, *div is set to the number of integer divisions and
10893 * *ineq is set to the number of inequality constraints (provided
10894 * div and ineq are not NULL).
10896 * The equality may also involve a single integer division involving
10897 * the output dimensions (typically only output dimension "pos") as
10898 * long as the coefficient of output dimension "pos" is 1 or -1 and
10899 * there is a pair of constraints i >= l and i <= l + n, with i referring
10900 * to output dimension "pos", l an expression involving only earlier
10901 * dimensions and n smaller than the coefficient of the integer division
10902 * in the equality. In this case, the output dimension can be defined
10903 * in terms of a modulo expression that does not involve the integer division.
10904 * *div is then set to this single integer division and
10905 * *ineq is set to the index of constraint i >= l.
10907 * Return bmap->n_eq if there is no such equality.
10908 * Return -1 on error.
10910 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
10911 int pos, int *div, int *ineq)
10913 int j, k, l;
10914 unsigned n_out, o_out;
10915 unsigned n_div, o_div;
10917 if (!bmap)
10918 return -1;
10920 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10921 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10922 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10923 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10925 if (ineq)
10926 *ineq = bmap->n_ineq;
10927 if (div)
10928 *div = n_div;
10929 for (j = 0; j < bmap->n_eq; ++j) {
10930 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
10931 continue;
10932 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
10933 n_out - (pos + 1)) != -1)
10934 continue;
10935 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10936 0, n_div);
10937 if (k >= n_div)
10938 return j;
10939 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
10940 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
10941 continue;
10942 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10943 k + 1, n_div - (k+1)) < n_div)
10944 continue;
10945 l = find_modulo_constraint_pair(bmap, pos,
10946 bmap->eq[j][o_div + k]);
10947 if (l < 0)
10948 return -1;
10949 if (l >= bmap->n_ineq)
10950 continue;
10951 if (div)
10952 *div = k;
10953 if (ineq)
10954 *ineq = l;
10955 return j;
10958 return bmap->n_eq;
10961 /* Check if the given basic map is obviously single-valued.
10962 * In particular, for each output dimension, check that there is
10963 * an equality that defines the output dimension in terms of
10964 * earlier dimensions.
10966 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
10968 int i;
10969 unsigned n_out;
10971 if (!bmap)
10972 return isl_bool_error;
10974 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10976 for (i = 0; i < n_out; ++i) {
10977 int eq;
10979 eq = isl_basic_map_output_defining_equality(bmap, i,
10980 NULL, NULL);
10981 if (eq < 0)
10982 return isl_bool_error;
10983 if (eq >= bmap->n_eq)
10984 return isl_bool_false;
10987 return isl_bool_true;
10990 /* Check if the given basic map is single-valued.
10991 * We simply compute
10993 * M \circ M^-1
10995 * and check if the result is a subset of the identity mapping.
10997 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
10999 isl_space *space;
11000 isl_basic_map *test;
11001 isl_basic_map *id;
11002 isl_bool sv;
11004 sv = isl_basic_map_plain_is_single_valued(bmap);
11005 if (sv < 0 || sv)
11006 return sv;
11008 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11009 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11011 space = isl_basic_map_get_space(bmap);
11012 space = isl_space_map_from_set(isl_space_range(space));
11013 id = isl_basic_map_identity(space);
11015 sv = isl_basic_map_is_subset(test, id);
11017 isl_basic_map_free(test);
11018 isl_basic_map_free(id);
11020 return sv;
11023 /* Check if the given map is obviously single-valued.
11025 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11027 if (!map)
11028 return isl_bool_error;
11029 if (map->n == 0)
11030 return isl_bool_true;
11031 if (map->n >= 2)
11032 return isl_bool_false;
11034 return isl_basic_map_plain_is_single_valued(map->p[0]);
11037 /* Check if the given map is single-valued.
11038 * We simply compute
11040 * M \circ M^-1
11042 * and check if the result is a subset of the identity mapping.
11044 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11046 isl_space *dim;
11047 isl_map *test;
11048 isl_map *id;
11049 isl_bool sv;
11051 sv = isl_map_plain_is_single_valued(map);
11052 if (sv < 0 || sv)
11053 return sv;
11055 test = isl_map_reverse(isl_map_copy(map));
11056 test = isl_map_apply_range(test, isl_map_copy(map));
11058 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11059 id = isl_map_identity(dim);
11061 sv = isl_map_is_subset(test, id);
11063 isl_map_free(test);
11064 isl_map_free(id);
11066 return sv;
11069 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11071 isl_bool in;
11073 map = isl_map_copy(map);
11074 map = isl_map_reverse(map);
11075 in = isl_map_is_single_valued(map);
11076 isl_map_free(map);
11078 return in;
11081 /* Check if the given map is obviously injective.
11083 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11085 isl_bool in;
11087 map = isl_map_copy(map);
11088 map = isl_map_reverse(map);
11089 in = isl_map_plain_is_single_valued(map);
11090 isl_map_free(map);
11092 return in;
11095 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11097 isl_bool sv;
11099 sv = isl_map_is_single_valued(map);
11100 if (sv < 0 || !sv)
11101 return sv;
11103 return isl_map_is_injective(map);
11106 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11108 return isl_map_is_single_valued(set_to_map(set));
11111 /* Does "map" only map elements to themselves?
11113 * If the domain and range spaces are different, then "map"
11114 * is considered not to be an identity relation, even if it is empty.
11115 * Otherwise, construct the maximal identity relation and
11116 * check whether "map" is a subset of this relation.
11118 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11120 isl_space *space;
11121 isl_map *id;
11122 isl_bool equal, is_identity;
11124 space = isl_map_get_space(map);
11125 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
11126 isl_space_free(space);
11127 if (equal < 0 || !equal)
11128 return equal;
11130 id = isl_map_identity(isl_map_get_space(map));
11131 is_identity = isl_map_is_subset(map, id);
11132 isl_map_free(id);
11134 return is_identity;
11137 int isl_map_is_translation(__isl_keep isl_map *map)
11139 int ok;
11140 isl_set *delta;
11142 delta = isl_map_deltas(isl_map_copy(map));
11143 ok = isl_set_is_singleton(delta);
11144 isl_set_free(delta);
11146 return ok;
11149 static int unique(isl_int *p, unsigned pos, unsigned len)
11151 if (isl_seq_first_non_zero(p, pos) != -1)
11152 return 0;
11153 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11154 return 0;
11155 return 1;
11158 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11160 int i, j;
11161 unsigned nvar;
11162 unsigned ovar;
11164 if (!bset)
11165 return isl_bool_error;
11167 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
11168 return isl_bool_false;
11170 nvar = isl_basic_set_dim(bset, isl_dim_set);
11171 ovar = isl_space_offset(bset->dim, isl_dim_set);
11172 for (j = 0; j < nvar; ++j) {
11173 int lower = 0, upper = 0;
11174 for (i = 0; i < bset->n_eq; ++i) {
11175 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11176 continue;
11177 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11178 return isl_bool_false;
11179 break;
11181 if (i < bset->n_eq)
11182 continue;
11183 for (i = 0; i < bset->n_ineq; ++i) {
11184 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11185 continue;
11186 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11187 return isl_bool_false;
11188 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11189 lower = 1;
11190 else
11191 upper = 1;
11193 if (!lower || !upper)
11194 return isl_bool_false;
11197 return isl_bool_true;
11200 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11202 if (!set)
11203 return isl_bool_error;
11204 if (set->n != 1)
11205 return isl_bool_false;
11207 return isl_basic_set_is_box(set->p[0]);
11210 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11212 if (!bset)
11213 return isl_bool_error;
11215 return isl_space_is_wrapping(bset->dim);
11218 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11220 if (!set)
11221 return isl_bool_error;
11223 return isl_space_is_wrapping(set->dim);
11226 /* Modify the space of "map" through a call to "change".
11227 * If "can_change" is set (not NULL), then first call it to check
11228 * if the modification is allowed, printing the error message "cannot_change"
11229 * if it is not.
11231 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11232 isl_bool (*can_change)(__isl_keep isl_map *map),
11233 const char *cannot_change,
11234 __isl_give isl_space *(*change)(__isl_take isl_space *space))
11236 isl_bool ok;
11237 isl_space *space;
11239 if (!map)
11240 return NULL;
11242 ok = can_change ? can_change(map) : isl_bool_true;
11243 if (ok < 0)
11244 return isl_map_free(map);
11245 if (!ok)
11246 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11247 return isl_map_free(map));
11249 space = change(isl_map_get_space(map));
11250 map = isl_map_reset_space(map, space);
11252 return map;
11255 /* Is the domain of "map" a wrapped relation?
11257 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11259 if (!map)
11260 return isl_bool_error;
11262 return isl_space_domain_is_wrapping(map->dim);
11265 /* Does "map" have a wrapped relation in both domain and range?
11267 isl_bool isl_map_is_product(__isl_keep isl_map *map)
11269 return isl_space_is_product(isl_map_peek_space(map));
11272 /* Is the range of "map" a wrapped relation?
11274 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
11276 if (!map)
11277 return isl_bool_error;
11279 return isl_space_range_is_wrapping(map->dim);
11282 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
11284 bmap = isl_basic_map_cow(bmap);
11285 if (!bmap)
11286 return NULL;
11288 bmap->dim = isl_space_wrap(bmap->dim);
11289 if (!bmap->dim)
11290 goto error;
11292 bmap = isl_basic_map_finalize(bmap);
11294 return bset_from_bmap(bmap);
11295 error:
11296 isl_basic_map_free(bmap);
11297 return NULL;
11300 /* Given a map A -> B, return the set (A -> B).
11302 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
11304 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
11307 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
11309 bset = isl_basic_set_cow(bset);
11310 if (!bset)
11311 return NULL;
11313 bset->dim = isl_space_unwrap(bset->dim);
11314 if (!bset->dim)
11315 goto error;
11317 bset = isl_basic_set_finalize(bset);
11319 return bset_to_bmap(bset);
11320 error:
11321 isl_basic_set_free(bset);
11322 return NULL;
11325 /* Given a set (A -> B), return the map A -> B.
11326 * Error out if "set" is not of the form (A -> B).
11328 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
11330 return isl_map_change_space(set, &isl_set_is_wrapping,
11331 "not a wrapping set", &isl_space_unwrap);
11334 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
11335 enum isl_dim_type type)
11337 if (!bmap)
11338 return NULL;
11340 if (!isl_space_is_named_or_nested(bmap->dim, type))
11341 return bmap;
11343 bmap = isl_basic_map_cow(bmap);
11344 if (!bmap)
11345 return NULL;
11347 bmap->dim = isl_space_reset(bmap->dim, type);
11348 if (!bmap->dim)
11349 goto error;
11351 bmap = isl_basic_map_finalize(bmap);
11353 return bmap;
11354 error:
11355 isl_basic_map_free(bmap);
11356 return NULL;
11359 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
11360 enum isl_dim_type type)
11362 int i;
11364 if (!map)
11365 return NULL;
11367 if (!isl_space_is_named_or_nested(map->dim, type))
11368 return map;
11370 map = isl_map_cow(map);
11371 if (!map)
11372 return NULL;
11374 for (i = 0; i < map->n; ++i) {
11375 map->p[i] = isl_basic_map_reset(map->p[i], type);
11376 if (!map->p[i])
11377 goto error;
11379 map->dim = isl_space_reset(map->dim, type);
11380 if (!map->dim)
11381 goto error;
11383 return map;
11384 error:
11385 isl_map_free(map);
11386 return NULL;
11389 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11391 if (!bmap)
11392 return NULL;
11394 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11395 return bmap;
11397 bmap = isl_basic_map_cow(bmap);
11398 if (!bmap)
11399 return NULL;
11401 bmap->dim = isl_space_flatten(bmap->dim);
11402 if (!bmap->dim)
11403 goto error;
11405 bmap = isl_basic_map_finalize(bmap);
11407 return bmap;
11408 error:
11409 isl_basic_map_free(bmap);
11410 return NULL;
11413 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11415 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11418 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11419 __isl_take isl_basic_map *bmap)
11421 if (!bmap)
11422 return NULL;
11424 if (!bmap->dim->nested[0])
11425 return bmap;
11427 bmap = isl_basic_map_cow(bmap);
11428 if (!bmap)
11429 return NULL;
11431 bmap->dim = isl_space_flatten_domain(bmap->dim);
11432 if (!bmap->dim)
11433 goto error;
11435 bmap = isl_basic_map_finalize(bmap);
11437 return bmap;
11438 error:
11439 isl_basic_map_free(bmap);
11440 return NULL;
11443 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11444 __isl_take isl_basic_map *bmap)
11446 if (!bmap)
11447 return NULL;
11449 if (!bmap->dim->nested[1])
11450 return bmap;
11452 bmap = isl_basic_map_cow(bmap);
11453 if (!bmap)
11454 return NULL;
11456 bmap->dim = isl_space_flatten_range(bmap->dim);
11457 if (!bmap->dim)
11458 goto error;
11460 bmap = isl_basic_map_finalize(bmap);
11462 return bmap;
11463 error:
11464 isl_basic_map_free(bmap);
11465 return NULL;
11468 /* Remove any internal structure from the spaces of domain and range of "map".
11470 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11472 if (!map)
11473 return NULL;
11475 if (!map->dim->nested[0] && !map->dim->nested[1])
11476 return map;
11478 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11481 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11483 return set_from_map(isl_map_flatten(set_to_map(set)));
11486 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11488 isl_space *space, *flat_space;
11489 isl_map *map;
11491 space = isl_set_get_space(set);
11492 flat_space = isl_space_flatten(isl_space_copy(space));
11493 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
11494 flat_space));
11495 map = isl_map_intersect_domain(map, set);
11497 return map;
11500 /* Remove any internal structure from the space of the domain of "map".
11502 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11504 if (!map)
11505 return NULL;
11507 if (!map->dim->nested[0])
11508 return map;
11510 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11513 /* Remove any internal structure from the space of the range of "map".
11515 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11517 if (!map)
11518 return NULL;
11520 if (!map->dim->nested[1])
11521 return map;
11523 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11526 /* Reorder the dimensions of "bmap" according to the given dim_map
11527 * and set the dimension specification to "space" and
11528 * perform Gaussian elimination on the result.
11530 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11531 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
11533 isl_basic_map *res;
11534 unsigned flags;
11535 unsigned n_div;
11537 if (!bmap || !space || !dim_map)
11538 goto error;
11540 flags = bmap->flags;
11541 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11542 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
11543 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11544 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11545 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
11546 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11547 if (res)
11548 res->flags = flags;
11549 res = isl_basic_map_gauss(res, NULL);
11550 res = isl_basic_map_finalize(res);
11551 return res;
11552 error:
11553 isl_dim_map_free(dim_map);
11554 isl_basic_map_free(bmap);
11555 isl_space_free(space);
11556 return NULL;
11559 /* Reorder the dimensions of "map" according to given reordering.
11561 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11562 __isl_take isl_reordering *r)
11564 int i;
11565 struct isl_dim_map *dim_map;
11567 map = isl_map_cow(map);
11568 dim_map = isl_dim_map_from_reordering(r);
11569 if (!map || !r || !dim_map)
11570 goto error;
11572 for (i = 0; i < map->n; ++i) {
11573 struct isl_dim_map *dim_map_i;
11574 isl_space *space;
11576 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11578 space = isl_reordering_get_space(r);
11579 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
11581 if (!map->p[i])
11582 goto error;
11585 map = isl_map_reset_space(map, isl_reordering_get_space(r));
11586 map = isl_map_unmark_normalized(map);
11588 isl_reordering_free(r);
11589 isl_dim_map_free(dim_map);
11590 return map;
11591 error:
11592 isl_dim_map_free(dim_map);
11593 isl_map_free(map);
11594 isl_reordering_free(r);
11595 return NULL;
11598 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11599 __isl_take isl_reordering *r)
11601 return set_from_map(isl_map_realign(set_to_map(set), r));
11604 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11605 __isl_take isl_space *model)
11607 isl_ctx *ctx;
11608 isl_bool aligned;
11610 if (!map || !model)
11611 goto error;
11613 ctx = isl_space_get_ctx(model);
11614 if (!isl_space_has_named_params(model))
11615 isl_die(ctx, isl_error_invalid,
11616 "model has unnamed parameters", goto error);
11617 if (isl_map_check_named_params(map) < 0)
11618 goto error;
11619 aligned = isl_map_space_has_equal_params(map, model);
11620 if (aligned < 0)
11621 goto error;
11622 if (!aligned) {
11623 isl_reordering *exp;
11625 exp = isl_parameter_alignment_reordering(map->dim, model);
11626 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11627 map = isl_map_realign(map, exp);
11630 isl_space_free(model);
11631 return map;
11632 error:
11633 isl_space_free(model);
11634 isl_map_free(map);
11635 return NULL;
11638 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11639 __isl_take isl_space *model)
11641 return isl_map_align_params(set, model);
11644 /* Align the parameters of "bmap" to those of "model", introducing
11645 * additional parameters if needed.
11647 __isl_give isl_basic_map *isl_basic_map_align_params(
11648 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11650 isl_ctx *ctx;
11651 isl_bool equal_params;
11653 if (!bmap || !model)
11654 goto error;
11656 ctx = isl_space_get_ctx(model);
11657 if (!isl_space_has_named_params(model))
11658 isl_die(ctx, isl_error_invalid,
11659 "model has unnamed parameters", goto error);
11660 if (isl_basic_map_check_named_params(bmap) < 0)
11661 goto error;
11662 equal_params = isl_space_has_equal_params(bmap->dim, model);
11663 if (equal_params < 0)
11664 goto error;
11665 if (!equal_params) {
11666 isl_reordering *exp;
11667 struct isl_dim_map *dim_map;
11669 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11670 exp = isl_reordering_extend_space(exp,
11671 isl_basic_map_get_space(bmap));
11672 dim_map = isl_dim_map_from_reordering(exp);
11673 bmap = isl_basic_map_realign(bmap,
11674 isl_reordering_get_space(exp),
11675 isl_dim_map_extend(dim_map, bmap));
11676 isl_reordering_free(exp);
11677 isl_dim_map_free(dim_map);
11680 isl_space_free(model);
11681 return bmap;
11682 error:
11683 isl_space_free(model);
11684 isl_basic_map_free(bmap);
11685 return NULL;
11688 /* Do "bset" and "space" have the same parameters?
11690 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
11691 __isl_keep isl_space *space)
11693 isl_space *bset_space;
11695 bset_space = isl_basic_set_peek_space(bset);
11696 return isl_space_has_equal_params(bset_space, space);
11699 /* Do "map" and "space" have the same parameters?
11701 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
11702 __isl_keep isl_space *space)
11704 isl_space *map_space;
11706 map_space = isl_map_peek_space(map);
11707 return isl_space_has_equal_params(map_space, space);
11710 /* Do "set" and "space" have the same parameters?
11712 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
11713 __isl_keep isl_space *space)
11715 return isl_map_space_has_equal_params(set_to_map(set), space);
11718 /* Align the parameters of "bset" to those of "model", introducing
11719 * additional parameters if needed.
11721 __isl_give isl_basic_set *isl_basic_set_align_params(
11722 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11724 return isl_basic_map_align_params(bset, model);
11727 /* Drop all parameters not referenced by "map".
11729 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
11731 int i;
11733 if (isl_map_check_named_params(map) < 0)
11734 return isl_map_free(map);
11736 for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
11737 isl_bool involves;
11739 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
11740 if (involves < 0)
11741 return isl_map_free(map);
11742 if (!involves)
11743 map = isl_map_project_out(map, isl_dim_param, i, 1);
11746 return map;
11749 /* Drop all parameters not referenced by "set".
11751 __isl_give isl_set *isl_set_drop_unused_params(
11752 __isl_take isl_set *set)
11754 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
11757 /* Drop all parameters not referenced by "bmap".
11759 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
11760 __isl_take isl_basic_map *bmap)
11762 int i;
11764 if (isl_basic_map_check_named_params(bmap) < 0)
11765 return isl_basic_map_free(bmap);
11767 for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
11768 isl_bool involves;
11770 involves = isl_basic_map_involves_dims(bmap,
11771 isl_dim_param, i, 1);
11772 if (involves < 0)
11773 return isl_basic_map_free(bmap);
11774 if (!involves)
11775 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
11778 return bmap;
11781 /* Drop all parameters not referenced by "bset".
11783 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
11784 __isl_take isl_basic_set *bset)
11786 return bset_from_bmap(isl_basic_map_drop_unused_params(
11787 bset_to_bmap(bset)));
11790 __isl_give isl_mat *isl_basic_map_equalities_matrix(
11791 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11792 enum isl_dim_type c2, enum isl_dim_type c3,
11793 enum isl_dim_type c4, enum isl_dim_type c5)
11795 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11796 struct isl_mat *mat;
11797 int i, j, k;
11798 int pos;
11800 if (!bmap)
11801 return NULL;
11802 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11803 isl_basic_map_total_dim(bmap) + 1);
11804 if (!mat)
11805 return NULL;
11806 for (i = 0; i < bmap->n_eq; ++i)
11807 for (j = 0, pos = 0; j < 5; ++j) {
11808 int off = isl_basic_map_offset(bmap, c[j]);
11809 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11810 isl_int_set(mat->row[i][pos],
11811 bmap->eq[i][off + k]);
11812 ++pos;
11816 return mat;
11819 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11820 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11821 enum isl_dim_type c2, enum isl_dim_type c3,
11822 enum isl_dim_type c4, enum isl_dim_type c5)
11824 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11825 struct isl_mat *mat;
11826 int i, j, k;
11827 int pos;
11829 if (!bmap)
11830 return NULL;
11831 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11832 isl_basic_map_total_dim(bmap) + 1);
11833 if (!mat)
11834 return NULL;
11835 for (i = 0; i < bmap->n_ineq; ++i)
11836 for (j = 0, pos = 0; j < 5; ++j) {
11837 int off = isl_basic_map_offset(bmap, c[j]);
11838 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11839 isl_int_set(mat->row[i][pos],
11840 bmap->ineq[i][off + k]);
11841 ++pos;
11845 return mat;
11848 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11849 __isl_take isl_space *space,
11850 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11851 enum isl_dim_type c2, enum isl_dim_type c3,
11852 enum isl_dim_type c4, enum isl_dim_type c5)
11854 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11855 isl_basic_map *bmap = NULL;
11856 unsigned total;
11857 unsigned extra;
11858 int i, j, k, l;
11859 int pos;
11861 if (!space || !eq || !ineq)
11862 goto error;
11864 if (eq->n_col != ineq->n_col)
11865 isl_die(space->ctx, isl_error_invalid,
11866 "equalities and inequalities matrices should have "
11867 "same number of columns", goto error);
11869 total = 1 + isl_space_dim(space, isl_dim_all);
11871 if (eq->n_col < total)
11872 isl_die(space->ctx, isl_error_invalid,
11873 "number of columns too small", goto error);
11875 extra = eq->n_col - total;
11877 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
11878 eq->n_row, ineq->n_row);
11879 if (!bmap)
11880 goto error;
11881 for (i = 0; i < extra; ++i) {
11882 k = isl_basic_map_alloc_div(bmap);
11883 if (k < 0)
11884 goto error;
11885 isl_int_set_si(bmap->div[k][0], 0);
11887 for (i = 0; i < eq->n_row; ++i) {
11888 l = isl_basic_map_alloc_equality(bmap);
11889 if (l < 0)
11890 goto error;
11891 for (j = 0, pos = 0; j < 5; ++j) {
11892 int off = isl_basic_map_offset(bmap, c[j]);
11893 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11894 isl_int_set(bmap->eq[l][off + k],
11895 eq->row[i][pos]);
11896 ++pos;
11900 for (i = 0; i < ineq->n_row; ++i) {
11901 l = isl_basic_map_alloc_inequality(bmap);
11902 if (l < 0)
11903 goto error;
11904 for (j = 0, pos = 0; j < 5; ++j) {
11905 int off = isl_basic_map_offset(bmap, c[j]);
11906 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11907 isl_int_set(bmap->ineq[l][off + k],
11908 ineq->row[i][pos]);
11909 ++pos;
11914 isl_space_free(space);
11915 isl_mat_free(eq);
11916 isl_mat_free(ineq);
11918 bmap = isl_basic_map_simplify(bmap);
11919 return isl_basic_map_finalize(bmap);
11920 error:
11921 isl_space_free(space);
11922 isl_mat_free(eq);
11923 isl_mat_free(ineq);
11924 isl_basic_map_free(bmap);
11925 return NULL;
11928 __isl_give isl_mat *isl_basic_set_equalities_matrix(
11929 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11930 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11932 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
11933 c1, c2, c3, c4, isl_dim_in);
11936 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
11937 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11938 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11940 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
11941 c1, c2, c3, c4, isl_dim_in);
11944 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
11945 __isl_take isl_space *dim,
11946 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11947 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11949 isl_basic_map *bmap;
11950 bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
11951 c1, c2, c3, c4, isl_dim_in);
11952 return bset_from_bmap(bmap);
11955 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
11957 if (!bmap)
11958 return isl_bool_error;
11960 return isl_space_can_zip(bmap->dim);
11963 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
11965 if (!map)
11966 return isl_bool_error;
11968 return isl_space_can_zip(map->dim);
11971 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
11972 * (A -> C) -> (B -> D).
11974 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
11976 unsigned pos;
11977 unsigned n1;
11978 unsigned n2;
11980 if (!bmap)
11981 return NULL;
11983 if (!isl_basic_map_can_zip(bmap))
11984 isl_die(bmap->ctx, isl_error_invalid,
11985 "basic map cannot be zipped", goto error);
11986 pos = isl_basic_map_offset(bmap, isl_dim_in) +
11987 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
11988 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
11989 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
11990 bmap = isl_basic_map_cow(bmap);
11991 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
11992 if (!bmap)
11993 return NULL;
11994 bmap->dim = isl_space_zip(bmap->dim);
11995 if (!bmap->dim)
11996 goto error;
11997 bmap = isl_basic_map_mark_final(bmap);
11998 return bmap;
11999 error:
12000 isl_basic_map_free(bmap);
12001 return NULL;
12004 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12005 * (A -> C) -> (B -> D).
12007 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12009 int i;
12011 if (!map)
12012 return NULL;
12014 if (!isl_map_can_zip(map))
12015 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12016 goto error);
12018 map = isl_map_cow(map);
12019 if (!map)
12020 return NULL;
12022 for (i = 0; i < map->n; ++i) {
12023 map->p[i] = isl_basic_map_zip(map->p[i]);
12024 if (!map->p[i])
12025 goto error;
12028 map->dim = isl_space_zip(map->dim);
12029 if (!map->dim)
12030 goto error;
12032 return map;
12033 error:
12034 isl_map_free(map);
12035 return NULL;
12038 /* Can we apply isl_basic_map_curry to "bmap"?
12039 * That is, does it have a nested relation in its domain?
12041 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12043 if (!bmap)
12044 return isl_bool_error;
12046 return isl_space_can_curry(bmap->dim);
12049 /* Can we apply isl_map_curry to "map"?
12050 * That is, does it have a nested relation in its domain?
12052 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12054 if (!map)
12055 return isl_bool_error;
12057 return isl_space_can_curry(map->dim);
12060 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12061 * A -> (B -> C).
12063 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12066 if (!bmap)
12067 return NULL;
12069 if (!isl_basic_map_can_curry(bmap))
12070 isl_die(bmap->ctx, isl_error_invalid,
12071 "basic map cannot be curried", goto error);
12072 bmap = isl_basic_map_cow(bmap);
12073 if (!bmap)
12074 return NULL;
12075 bmap->dim = isl_space_curry(bmap->dim);
12076 if (!bmap->dim)
12077 goto error;
12078 bmap = isl_basic_map_mark_final(bmap);
12079 return bmap;
12080 error:
12081 isl_basic_map_free(bmap);
12082 return NULL;
12085 /* Given a map (A -> B) -> C, return the corresponding map
12086 * A -> (B -> C).
12088 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
12090 return isl_map_change_space(map, &isl_map_can_curry,
12091 "map cannot be curried", &isl_space_curry);
12094 /* Can isl_map_range_curry be applied to "map"?
12095 * That is, does it have a nested relation in its range,
12096 * the domain of which is itself a nested relation?
12098 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
12100 if (!map)
12101 return isl_bool_error;
12103 return isl_space_can_range_curry(map->dim);
12106 /* Given a map A -> ((B -> C) -> D), return the corresponding map
12107 * A -> (B -> (C -> D)).
12109 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
12111 return isl_map_change_space(map, &isl_map_can_range_curry,
12112 "map range cannot be curried",
12113 &isl_space_range_curry);
12116 /* Can we apply isl_basic_map_uncurry to "bmap"?
12117 * That is, does it have a nested relation in its domain?
12119 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
12121 if (!bmap)
12122 return isl_bool_error;
12124 return isl_space_can_uncurry(bmap->dim);
12127 /* Can we apply isl_map_uncurry to "map"?
12128 * That is, does it have a nested relation in its domain?
12130 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
12132 if (!map)
12133 return isl_bool_error;
12135 return isl_space_can_uncurry(map->dim);
12138 /* Given a basic map A -> (B -> C), return the corresponding basic map
12139 * (A -> B) -> C.
12141 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
12144 if (!bmap)
12145 return NULL;
12147 if (!isl_basic_map_can_uncurry(bmap))
12148 isl_die(bmap->ctx, isl_error_invalid,
12149 "basic map cannot be uncurried",
12150 return isl_basic_map_free(bmap));
12151 bmap = isl_basic_map_cow(bmap);
12152 if (!bmap)
12153 return NULL;
12154 bmap->dim = isl_space_uncurry(bmap->dim);
12155 if (!bmap->dim)
12156 return isl_basic_map_free(bmap);
12157 bmap = isl_basic_map_mark_final(bmap);
12158 return bmap;
12161 /* Given a map A -> (B -> C), return the corresponding map
12162 * (A -> B) -> C.
12164 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
12166 return isl_map_change_space(map, &isl_map_can_uncurry,
12167 "map cannot be uncurried", &isl_space_uncurry);
12170 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
12171 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12173 return isl_map_equate(set, type1, pos1, type2, pos2);
12176 /* Construct a basic map where the given dimensions are equal to each other.
12178 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
12179 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12181 isl_basic_map *bmap = NULL;
12182 int i;
12184 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12185 isl_space_check_range(space, type2, pos2, 1) < 0)
12186 goto error;
12188 if (type1 == type2 && pos1 == pos2)
12189 return isl_basic_map_universe(space);
12191 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
12192 i = isl_basic_map_alloc_equality(bmap);
12193 if (i < 0)
12194 goto error;
12195 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12196 pos1 += isl_basic_map_offset(bmap, type1);
12197 pos2 += isl_basic_map_offset(bmap, type2);
12198 isl_int_set_si(bmap->eq[i][pos1], -1);
12199 isl_int_set_si(bmap->eq[i][pos2], 1);
12200 bmap = isl_basic_map_finalize(bmap);
12201 isl_space_free(space);
12202 return bmap;
12203 error:
12204 isl_space_free(space);
12205 isl_basic_map_free(bmap);
12206 return NULL;
12209 /* Add a constraint imposing that the given two dimensions are equal.
12211 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
12212 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12214 isl_basic_map *eq;
12216 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12218 bmap = isl_basic_map_intersect(bmap, eq);
12220 return bmap;
12223 /* Add a constraint imposing that the given two dimensions are equal.
12225 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
12226 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12228 isl_basic_map *bmap;
12230 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
12232 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12234 return map;
12237 /* Add a constraint imposing that the given two dimensions have opposite values.
12239 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
12240 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12242 isl_basic_map *bmap = NULL;
12243 int i;
12245 if (isl_map_check_range(map, type1, pos1, 1) < 0)
12246 return isl_map_free(map);
12247 if (isl_map_check_range(map, type2, pos2, 1) < 0)
12248 return isl_map_free(map);
12250 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
12251 i = isl_basic_map_alloc_equality(bmap);
12252 if (i < 0)
12253 goto error;
12254 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12255 pos1 += isl_basic_map_offset(bmap, type1);
12256 pos2 += isl_basic_map_offset(bmap, type2);
12257 isl_int_set_si(bmap->eq[i][pos1], 1);
12258 isl_int_set_si(bmap->eq[i][pos2], 1);
12259 bmap = isl_basic_map_finalize(bmap);
12261 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12263 return map;
12264 error:
12265 isl_basic_map_free(bmap);
12266 isl_map_free(map);
12267 return NULL;
12270 /* Construct a constraint imposing that the value of the first dimension is
12271 * greater than or equal to that of the second.
12273 static __isl_give isl_constraint *constraint_order_ge(
12274 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
12275 enum isl_dim_type type2, int pos2)
12277 isl_constraint *c;
12279 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12280 isl_space_check_range(space, type2, pos2, 1) < 0)
12281 space = isl_space_free(space);
12282 if (!space)
12283 return NULL;
12285 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
12287 if (type1 == type2 && pos1 == pos2)
12288 return c;
12290 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
12291 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
12293 return c;
12296 /* Add a constraint imposing that the value of the first dimension is
12297 * greater than or equal to that of the second.
12299 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
12300 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12302 isl_constraint *c;
12303 isl_space *space;
12305 if (type1 == type2 && pos1 == pos2)
12306 return bmap;
12307 space = isl_basic_map_get_space(bmap);
12308 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12309 bmap = isl_basic_map_add_constraint(bmap, c);
12311 return bmap;
12314 /* Add a constraint imposing that the value of the first dimension is
12315 * greater than or equal to that of the second.
12317 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12318 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12320 isl_constraint *c;
12321 isl_space *space;
12323 if (type1 == type2 && pos1 == pos2)
12324 return map;
12325 space = isl_map_get_space(map);
12326 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12327 map = isl_map_add_constraint(map, c);
12329 return map;
12332 /* Add a constraint imposing that the value of the first dimension is
12333 * less than or equal to that of the second.
12335 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12336 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12338 return isl_map_order_ge(map, type2, pos2, type1, pos1);
12341 /* Construct a basic map where the value of the first dimension is
12342 * greater than that of the second.
12344 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12345 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12347 isl_basic_map *bmap = NULL;
12348 int i;
12350 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
12351 isl_space_check_range(space, type2, pos2, 1) < 0)
12352 goto error;
12354 if (type1 == type2 && pos1 == pos2)
12355 return isl_basic_map_empty(space);
12357 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12358 i = isl_basic_map_alloc_inequality(bmap);
12359 if (i < 0)
12360 return isl_basic_map_free(bmap);
12361 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12362 pos1 += isl_basic_map_offset(bmap, type1);
12363 pos2 += isl_basic_map_offset(bmap, type2);
12364 isl_int_set_si(bmap->ineq[i][pos1], 1);
12365 isl_int_set_si(bmap->ineq[i][pos2], -1);
12366 isl_int_set_si(bmap->ineq[i][0], -1);
12367 bmap = isl_basic_map_finalize(bmap);
12369 return bmap;
12370 error:
12371 isl_space_free(space);
12372 isl_basic_map_free(bmap);
12373 return NULL;
12376 /* Add a constraint imposing that the value of the first dimension is
12377 * greater than that of the second.
12379 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12380 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12382 isl_basic_map *gt;
12384 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12386 bmap = isl_basic_map_intersect(bmap, gt);
12388 return bmap;
12391 /* Add a constraint imposing that the value of the first dimension is
12392 * greater than that of the second.
12394 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12395 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12397 isl_basic_map *bmap;
12399 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12401 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12403 return map;
12406 /* Add a constraint imposing that the value of the first dimension is
12407 * smaller than that of the second.
12409 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12410 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12412 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12415 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12416 int pos)
12418 isl_aff *div;
12419 isl_local_space *ls;
12421 if (!bmap)
12422 return NULL;
12424 if (!isl_basic_map_divs_known(bmap))
12425 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12426 "some divs are unknown", return NULL);
12428 ls = isl_basic_map_get_local_space(bmap);
12429 div = isl_local_space_get_div(ls, pos);
12430 isl_local_space_free(ls);
12432 return div;
12435 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12436 int pos)
12438 return isl_basic_map_get_div(bset, pos);
12441 /* Plug in "subs" for dimension "type", "pos" of "bset".
12443 * Let i be the dimension to replace and let "subs" be of the form
12445 * f/d
12447 * Any integer division with a non-zero coefficient for i,
12449 * floor((a i + g)/m)
12451 * is replaced by
12453 * floor((a f + d g)/(m d))
12455 * Constraints of the form
12457 * a i + g
12459 * are replaced by
12461 * a f + d g
12463 * We currently require that "subs" is an integral expression.
12464 * Handling rational expressions may require us to add stride constraints
12465 * as we do in isl_basic_set_preimage_multi_aff.
12467 __isl_give isl_basic_set *isl_basic_set_substitute(
12468 __isl_take isl_basic_set *bset,
12469 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12471 int i;
12472 isl_int v;
12473 isl_ctx *ctx;
12475 if (bset && isl_basic_set_plain_is_empty(bset))
12476 return bset;
12478 bset = isl_basic_set_cow(bset);
12479 if (!bset || !subs)
12480 goto error;
12482 ctx = isl_basic_set_get_ctx(bset);
12483 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12484 isl_die(ctx, isl_error_invalid,
12485 "spaces don't match", goto error);
12486 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12487 isl_die(ctx, isl_error_unsupported,
12488 "cannot handle divs yet", goto error);
12489 if (!isl_int_is_one(subs->v->el[0]))
12490 isl_die(ctx, isl_error_invalid,
12491 "can only substitute integer expressions", goto error);
12493 pos += isl_basic_set_offset(bset, type);
12495 isl_int_init(v);
12497 for (i = 0; i < bset->n_eq; ++i) {
12498 if (isl_int_is_zero(bset->eq[i][pos]))
12499 continue;
12500 isl_int_set(v, bset->eq[i][pos]);
12501 isl_int_set_si(bset->eq[i][pos], 0);
12502 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12503 v, subs->v->el + 1, subs->v->size - 1);
12506 for (i = 0; i < bset->n_ineq; ++i) {
12507 if (isl_int_is_zero(bset->ineq[i][pos]))
12508 continue;
12509 isl_int_set(v, bset->ineq[i][pos]);
12510 isl_int_set_si(bset->ineq[i][pos], 0);
12511 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12512 v, subs->v->el + 1, subs->v->size - 1);
12515 for (i = 0; i < bset->n_div; ++i) {
12516 if (isl_int_is_zero(bset->div[i][1 + pos]))
12517 continue;
12518 isl_int_set(v, bset->div[i][1 + pos]);
12519 isl_int_set_si(bset->div[i][1 + pos], 0);
12520 isl_seq_combine(bset->div[i] + 1,
12521 subs->v->el[0], bset->div[i] + 1,
12522 v, subs->v->el + 1, subs->v->size - 1);
12523 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12526 isl_int_clear(v);
12528 bset = isl_basic_set_simplify(bset);
12529 return isl_basic_set_finalize(bset);
12530 error:
12531 isl_basic_set_free(bset);
12532 return NULL;
12535 /* Plug in "subs" for dimension "type", "pos" of "set".
12537 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12538 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12540 int i;
12542 if (set && isl_set_plain_is_empty(set))
12543 return set;
12545 set = isl_set_cow(set);
12546 if (!set || !subs)
12547 goto error;
12549 for (i = set->n - 1; i >= 0; --i) {
12550 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12551 set = set_from_map(remove_if_empty(set_to_map(set), i));
12552 if (!set)
12553 return NULL;
12556 return set;
12557 error:
12558 isl_set_free(set);
12559 return NULL;
12562 /* Check if the range of "ma" is compatible with the domain or range
12563 * (depending on "type") of "bmap".
12565 static isl_stat check_basic_map_compatible_range_multi_aff(
12566 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12567 __isl_keep isl_multi_aff *ma)
12569 isl_bool m;
12570 isl_space *ma_space;
12572 ma_space = isl_multi_aff_get_space(ma);
12574 m = isl_space_has_equal_params(bmap->dim, ma_space);
12575 if (m < 0)
12576 goto error;
12577 if (!m)
12578 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12579 "parameters don't match", goto error);
12580 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12581 if (m < 0)
12582 goto error;
12583 if (!m)
12584 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12585 "spaces don't match", goto error);
12587 isl_space_free(ma_space);
12588 return isl_stat_ok;
12589 error:
12590 isl_space_free(ma_space);
12591 return isl_stat_error;
12594 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12595 * coefficients before the transformed range of dimensions,
12596 * the "n_after" coefficients after the transformed range of dimensions
12597 * and the coefficients of the other divs in "bmap".
12599 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
12600 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12602 int i;
12603 int n_param;
12604 int n_set;
12605 isl_local_space *ls;
12607 if (n_div == 0)
12608 return bmap;
12610 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
12611 if (!ls)
12612 return isl_basic_map_free(bmap);
12614 n_param = isl_local_space_dim(ls, isl_dim_param);
12615 n_set = isl_local_space_dim(ls, isl_dim_set);
12616 for (i = 0; i < n_div; ++i) {
12617 int o_bmap = 0, o_ls = 0;
12619 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12620 o_bmap += 1 + 1 + n_param;
12621 o_ls += 1 + 1 + n_param;
12622 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12623 o_bmap += n_before;
12624 isl_seq_cpy(bmap->div[i] + o_bmap,
12625 ls->div->row[i] + o_ls, n_set);
12626 o_bmap += n_set;
12627 o_ls += n_set;
12628 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12629 o_bmap += n_after;
12630 isl_seq_cpy(bmap->div[i] + o_bmap,
12631 ls->div->row[i] + o_ls, n_div);
12632 o_bmap += n_div;
12633 o_ls += n_div;
12634 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12635 bmap = isl_basic_map_add_div_constraints(bmap, i);
12636 if (!bmap)
12637 goto error;
12640 isl_local_space_free(ls);
12641 return bmap;
12642 error:
12643 isl_local_space_free(ls);
12644 return isl_basic_map_free(bmap);
12647 /* How many stride constraints does "ma" enforce?
12648 * That is, how many of the affine expressions have a denominator
12649 * different from one?
12651 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12653 int i;
12654 int strides = 0;
12656 for (i = 0; i < ma->n; ++i)
12657 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
12658 strides++;
12660 return strides;
12663 /* For each affine expression in ma of the form
12665 * x_i = (f_i y + h_i)/m_i
12667 * with m_i different from one, add a constraint to "bmap"
12668 * of the form
12670 * f_i y + h_i = m_i alpha_i
12672 * with alpha_i an additional existentially quantified variable.
12674 * The input variables of "ma" correspond to a subset of the variables
12675 * of "bmap". There are "n_before" variables in "bmap" before this
12676 * subset and "n_after" variables after this subset.
12677 * The integer divisions of the affine expressions in "ma" are assumed
12678 * to have been aligned. There are "n_div_ma" of them and
12679 * they appear first in "bmap", straight after the "n_after" variables.
12681 static __isl_give isl_basic_map *add_ma_strides(
12682 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12683 int n_before, int n_after, int n_div_ma)
12685 int i, k;
12686 int div;
12687 int total;
12688 int n_param;
12689 int n_in;
12691 total = isl_basic_map_total_dim(bmap);
12692 n_param = isl_multi_aff_dim(ma, isl_dim_param);
12693 n_in = isl_multi_aff_dim(ma, isl_dim_in);
12694 for (i = 0; i < ma->n; ++i) {
12695 int o_bmap = 0, o_ma = 1;
12697 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
12698 continue;
12699 div = isl_basic_map_alloc_div(bmap);
12700 k = isl_basic_map_alloc_equality(bmap);
12701 if (div < 0 || k < 0)
12702 goto error;
12703 isl_int_set_si(bmap->div[div][0], 0);
12704 isl_seq_cpy(bmap->eq[k] + o_bmap,
12705 ma->u.p[i]->v->el + o_ma, 1 + n_param);
12706 o_bmap += 1 + n_param;
12707 o_ma += 1 + n_param;
12708 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12709 o_bmap += n_before;
12710 isl_seq_cpy(bmap->eq[k] + o_bmap,
12711 ma->u.p[i]->v->el + o_ma, n_in);
12712 o_bmap += n_in;
12713 o_ma += n_in;
12714 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12715 o_bmap += n_after;
12716 isl_seq_cpy(bmap->eq[k] + o_bmap,
12717 ma->u.p[i]->v->el + o_ma, n_div_ma);
12718 o_bmap += n_div_ma;
12719 o_ma += n_div_ma;
12720 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12721 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
12722 total++;
12725 return bmap;
12726 error:
12727 isl_basic_map_free(bmap);
12728 return NULL;
12731 /* Replace the domain or range space (depending on "type) of "space" by "set".
12733 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12734 enum isl_dim_type type, __isl_take isl_space *set)
12736 if (type == isl_dim_in) {
12737 space = isl_space_range(space);
12738 space = isl_space_map_from_domain_and_range(set, space);
12739 } else {
12740 space = isl_space_domain(space);
12741 space = isl_space_map_from_domain_and_range(space, set);
12744 return space;
12747 /* Compute the preimage of the domain or range (depending on "type")
12748 * of "bmap" under the function represented by "ma".
12749 * In other words, plug in "ma" in the domain or range of "bmap".
12750 * The result is a basic map that lives in the same space as "bmap"
12751 * except that the domain or range has been replaced by
12752 * the domain space of "ma".
12754 * If bmap is represented by
12756 * A(p) + S u + B x + T v + C(divs) >= 0,
12758 * where u and x are input and output dimensions if type == isl_dim_out
12759 * while x and v are input and output dimensions if type == isl_dim_in,
12760 * and ma is represented by
12762 * x = D(p) + F(y) + G(divs')
12764 * then the result is
12766 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12768 * The divs in the input set are similarly adjusted.
12769 * In particular
12771 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12773 * becomes
12775 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12776 * B_i G(divs') + c_i(divs))/n_i)
12778 * If bmap is not a rational map and if F(y) involves any denominators
12780 * x_i = (f_i y + h_i)/m_i
12782 * then additional constraints are added to ensure that we only
12783 * map back integer points. That is we enforce
12785 * f_i y + h_i = m_i alpha_i
12787 * with alpha_i an additional existentially quantified variable.
12789 * We first copy over the divs from "ma".
12790 * Then we add the modified constraints and divs from "bmap".
12791 * Finally, we add the stride constraints, if needed.
12793 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12794 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12795 __isl_take isl_multi_aff *ma)
12797 int i, k;
12798 isl_space *space;
12799 isl_basic_map *res = NULL;
12800 int n_before, n_after, n_div_bmap, n_div_ma;
12801 isl_int f, c1, c2, g;
12802 isl_bool rational;
12803 int strides;
12805 isl_int_init(f);
12806 isl_int_init(c1);
12807 isl_int_init(c2);
12808 isl_int_init(g);
12810 ma = isl_multi_aff_align_divs(ma);
12811 if (!bmap || !ma)
12812 goto error;
12813 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12814 goto error;
12816 if (type == isl_dim_in) {
12817 n_before = 0;
12818 n_after = isl_basic_map_dim(bmap, isl_dim_out);
12819 } else {
12820 n_before = isl_basic_map_dim(bmap, isl_dim_in);
12821 n_after = 0;
12823 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12824 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
12826 space = isl_multi_aff_get_domain_space(ma);
12827 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12828 rational = isl_basic_map_is_rational(bmap);
12829 strides = rational ? 0 : multi_aff_strides(ma);
12830 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12831 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12832 if (rational)
12833 res = isl_basic_map_set_rational(res);
12835 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12836 if (isl_basic_map_alloc_div(res) < 0)
12837 goto error;
12839 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
12840 if (!res)
12841 goto error;
12843 for (i = 0; i < bmap->n_eq; ++i) {
12844 k = isl_basic_map_alloc_equality(res);
12845 if (k < 0)
12846 goto error;
12847 if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
12848 n_after, n_div_ma, n_div_bmap,
12849 f, c1, c2, g, 0) < 0)
12850 goto error;
12853 for (i = 0; i < bmap->n_ineq; ++i) {
12854 k = isl_basic_map_alloc_inequality(res);
12855 if (k < 0)
12856 goto error;
12857 if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
12858 n_after, n_div_ma, n_div_bmap,
12859 f, c1, c2, g, 0) < 0)
12860 goto error;
12863 for (i = 0; i < bmap->n_div; ++i) {
12864 if (isl_int_is_zero(bmap->div[i][0])) {
12865 isl_int_set_si(res->div[n_div_ma + i][0], 0);
12866 continue;
12868 if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
12869 n_before, n_after, n_div_ma, n_div_bmap,
12870 f, c1, c2, g, 1) < 0)
12871 goto error;
12874 if (strides)
12875 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
12877 isl_int_clear(f);
12878 isl_int_clear(c1);
12879 isl_int_clear(c2);
12880 isl_int_clear(g);
12881 isl_basic_map_free(bmap);
12882 isl_multi_aff_free(ma);
12883 res = isl_basic_map_simplify(res);
12884 return isl_basic_map_finalize(res);
12885 error:
12886 isl_int_clear(f);
12887 isl_int_clear(c1);
12888 isl_int_clear(c2);
12889 isl_int_clear(g);
12890 isl_basic_map_free(bmap);
12891 isl_multi_aff_free(ma);
12892 isl_basic_map_free(res);
12893 return NULL;
12896 /* Compute the preimage of "bset" under the function represented by "ma".
12897 * In other words, plug in "ma" in "bset". The result is a basic set
12898 * that lives in the domain space of "ma".
12900 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
12901 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
12903 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
12906 /* Compute the preimage of the domain of "bmap" under the function
12907 * represented by "ma".
12908 * In other words, plug in "ma" in the domain of "bmap".
12909 * The result is a basic map that lives in the same space as "bmap"
12910 * except that the domain has been replaced by the domain space of "ma".
12912 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
12913 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12915 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
12918 /* Compute the preimage of the range of "bmap" under the function
12919 * represented by "ma".
12920 * In other words, plug in "ma" in the range of "bmap".
12921 * The result is a basic map that lives in the same space as "bmap"
12922 * except that the range has been replaced by the domain space of "ma".
12924 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
12925 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12927 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
12930 /* Check if the range of "ma" is compatible with the domain or range
12931 * (depending on "type") of "map".
12932 * Return isl_stat_error if anything is wrong.
12934 static isl_stat check_map_compatible_range_multi_aff(
12935 __isl_keep isl_map *map, enum isl_dim_type type,
12936 __isl_keep isl_multi_aff *ma)
12938 isl_bool m;
12939 isl_space *ma_space;
12941 ma_space = isl_multi_aff_get_space(ma);
12942 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
12943 isl_space_free(ma_space);
12944 if (m < 0)
12945 return isl_stat_error;
12946 if (!m)
12947 isl_die(isl_map_get_ctx(map), isl_error_invalid,
12948 "spaces don't match", return isl_stat_error);
12949 return isl_stat_ok;
12952 /* Compute the preimage of the domain or range (depending on "type")
12953 * of "map" under the function represented by "ma".
12954 * In other words, plug in "ma" in the domain or range of "map".
12955 * The result is a map that lives in the same space as "map"
12956 * except that the domain or range has been replaced by
12957 * the domain space of "ma".
12959 * The parameters are assumed to have been aligned.
12961 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
12962 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12964 int i;
12965 isl_space *space;
12967 map = isl_map_cow(map);
12968 ma = isl_multi_aff_align_divs(ma);
12969 if (!map || !ma)
12970 goto error;
12971 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
12972 goto error;
12974 for (i = 0; i < map->n; ++i) {
12975 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
12976 isl_multi_aff_copy(ma));
12977 if (!map->p[i])
12978 goto error;
12981 space = isl_multi_aff_get_domain_space(ma);
12982 space = isl_space_set(isl_map_get_space(map), type, space);
12984 isl_space_free(map->dim);
12985 map->dim = space;
12986 if (!map->dim)
12987 goto error;
12989 isl_multi_aff_free(ma);
12990 if (map->n > 1)
12991 ISL_F_CLR(map, ISL_MAP_DISJOINT);
12992 ISL_F_CLR(map, ISL_SET_NORMALIZED);
12993 return map;
12994 error:
12995 isl_multi_aff_free(ma);
12996 isl_map_free(map);
12997 return NULL;
13000 /* Compute the preimage of the domain or range (depending on "type")
13001 * of "map" under the function represented by "ma".
13002 * In other words, plug in "ma" in the domain or range of "map".
13003 * The result is a map that lives in the same space as "map"
13004 * except that the domain or range has been replaced by
13005 * the domain space of "ma".
13007 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13008 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13010 isl_bool aligned;
13012 if (!map || !ma)
13013 goto error;
13015 aligned = isl_map_space_has_equal_params(map, ma->space);
13016 if (aligned < 0)
13017 goto error;
13018 if (aligned)
13019 return map_preimage_multi_aff(map, type, ma);
13021 if (isl_map_check_named_params(map) < 0)
13022 goto error;
13023 if (!isl_space_has_named_params(ma->space))
13024 isl_die(map->ctx, isl_error_invalid,
13025 "unaligned unnamed parameters", goto error);
13026 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13027 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13029 return map_preimage_multi_aff(map, type, ma);
13030 error:
13031 isl_multi_aff_free(ma);
13032 return isl_map_free(map);
13035 /* Compute the preimage of "set" under the function represented by "ma".
13036 * In other words, plug in "ma" in "set". The result is a set
13037 * that lives in the domain space of "ma".
13039 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13040 __isl_take isl_multi_aff *ma)
13042 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13045 /* Compute the preimage of the domain of "map" under the function
13046 * represented by "ma".
13047 * In other words, plug in "ma" in the domain of "map".
13048 * The result is a map that lives in the same space as "map"
13049 * except that the domain has been replaced by the domain space of "ma".
13051 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13052 __isl_take isl_multi_aff *ma)
13054 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13057 /* Compute the preimage of the range of "map" under the function
13058 * represented by "ma".
13059 * In other words, plug in "ma" in the range of "map".
13060 * The result is a map that lives in the same space as "map"
13061 * except that the range has been replaced by the domain space of "ma".
13063 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13064 __isl_take isl_multi_aff *ma)
13066 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
13069 /* Compute the preimage of "map" under the function represented by "pma".
13070 * In other words, plug in "pma" in the domain or range of "map".
13071 * The result is a map that lives in the same space as "map",
13072 * except that the space of type "type" has been replaced by
13073 * the domain space of "pma".
13075 * The parameters of "map" and "pma" are assumed to have been aligned.
13077 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
13078 __isl_take isl_map *map, enum isl_dim_type type,
13079 __isl_take isl_pw_multi_aff *pma)
13081 int i;
13082 isl_map *res;
13084 if (!pma)
13085 goto error;
13087 if (pma->n == 0) {
13088 isl_pw_multi_aff_free(pma);
13089 res = isl_map_empty(isl_map_get_space(map));
13090 isl_map_free(map);
13091 return res;
13094 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13095 isl_multi_aff_copy(pma->p[0].maff));
13096 if (type == isl_dim_in)
13097 res = isl_map_intersect_domain(res,
13098 isl_map_copy(pma->p[0].set));
13099 else
13100 res = isl_map_intersect_range(res,
13101 isl_map_copy(pma->p[0].set));
13103 for (i = 1; i < pma->n; ++i) {
13104 isl_map *res_i;
13106 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13107 isl_multi_aff_copy(pma->p[i].maff));
13108 if (type == isl_dim_in)
13109 res_i = isl_map_intersect_domain(res_i,
13110 isl_map_copy(pma->p[i].set));
13111 else
13112 res_i = isl_map_intersect_range(res_i,
13113 isl_map_copy(pma->p[i].set));
13114 res = isl_map_union(res, res_i);
13117 isl_pw_multi_aff_free(pma);
13118 isl_map_free(map);
13119 return res;
13120 error:
13121 isl_pw_multi_aff_free(pma);
13122 isl_map_free(map);
13123 return NULL;
13126 /* Compute the preimage of "map" under the function represented by "pma".
13127 * In other words, plug in "pma" in the domain or range of "map".
13128 * The result is a map that lives in the same space as "map",
13129 * except that the space of type "type" has been replaced by
13130 * the domain space of "pma".
13132 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
13133 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
13135 isl_bool aligned;
13137 if (!map || !pma)
13138 goto error;
13140 aligned = isl_map_space_has_equal_params(map, pma->dim);
13141 if (aligned < 0)
13142 goto error;
13143 if (aligned)
13144 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13146 if (isl_map_check_named_params(map) < 0)
13147 goto error;
13148 if (isl_pw_multi_aff_check_named_params(pma) < 0)
13149 goto error;
13150 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
13151 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
13153 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13154 error:
13155 isl_pw_multi_aff_free(pma);
13156 return isl_map_free(map);
13159 /* Compute the preimage of "set" under the function represented by "pma".
13160 * In other words, plug in "pma" in "set". The result is a set
13161 * that lives in the domain space of "pma".
13163 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
13164 __isl_take isl_pw_multi_aff *pma)
13166 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
13169 /* Compute the preimage of the domain of "map" under the function
13170 * represented by "pma".
13171 * In other words, plug in "pma" in the domain of "map".
13172 * The result is a map that lives in the same space as "map",
13173 * except that domain space has been replaced by the domain space of "pma".
13175 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
13176 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13178 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
13181 /* Compute the preimage of the range of "map" under the function
13182 * represented by "pma".
13183 * In other words, plug in "pma" in the range of "map".
13184 * The result is a map that lives in the same space as "map",
13185 * except that range space has been replaced by the domain space of "pma".
13187 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
13188 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13190 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
13193 /* Compute the preimage of "map" under the function represented by "mpa".
13194 * In other words, plug in "mpa" in the domain or range of "map".
13195 * The result is a map that lives in the same space as "map",
13196 * except that the space of type "type" has been replaced by
13197 * the domain space of "mpa".
13199 * If the map does not involve any constraints that refer to the
13200 * dimensions of the substituted space, then the only possible
13201 * effect of "mpa" on the map is to map the space to a different space.
13202 * We create a separate isl_multi_aff to effectuate this change
13203 * in order to avoid spurious splitting of the map along the pieces
13204 * of "mpa".
13205 * If "mpa" has a non-trivial explicit domain, however,
13206 * then the full substitution should be performed.
13208 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
13209 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
13211 int n;
13212 isl_bool full;
13213 isl_pw_multi_aff *pma;
13215 if (!map || !mpa)
13216 goto error;
13218 n = isl_map_dim(map, type);
13219 full = isl_map_involves_dims(map, type, 0, n);
13220 if (full >= 0 && !full)
13221 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
13222 if (full < 0)
13223 goto error;
13224 if (!full) {
13225 isl_space *space;
13226 isl_multi_aff *ma;
13228 space = isl_multi_pw_aff_get_space(mpa);
13229 isl_multi_pw_aff_free(mpa);
13230 ma = isl_multi_aff_zero(space);
13231 return isl_map_preimage_multi_aff(map, type, ma);
13234 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
13235 return isl_map_preimage_pw_multi_aff(map, type, pma);
13236 error:
13237 isl_map_free(map);
13238 isl_multi_pw_aff_free(mpa);
13239 return NULL;
13242 /* Compute the preimage of "map" under the function represented by "mpa".
13243 * In other words, plug in "mpa" in the domain "map".
13244 * The result is a map that lives in the same space as "map",
13245 * except that domain space has been replaced by the domain space of "mpa".
13247 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
13248 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
13250 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
13253 /* Compute the preimage of "set" by the function represented by "mpa".
13254 * In other words, plug in "mpa" in "set".
13256 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
13257 __isl_take isl_multi_pw_aff *mpa)
13259 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
13262 /* Return a copy of the equality constraints of "bset" as a matrix.
13264 __isl_give isl_mat *isl_basic_set_extract_equalities(
13265 __isl_keep isl_basic_set *bset)
13267 isl_ctx *ctx;
13268 unsigned total;
13270 if (!bset)
13271 return NULL;
13273 ctx = isl_basic_set_get_ctx(bset);
13274 total = 1 + isl_basic_set_dim(bset, isl_dim_all);
13275 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
13278 /* Are the "n" "coefficients" starting at "first" of the integer division
13279 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
13280 * to each other?
13281 * The "coefficient" at position 0 is the denominator.
13282 * The "coefficient" at position 1 is the constant term.
13284 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
13285 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
13286 unsigned first, unsigned n)
13288 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
13289 return isl_bool_error;
13290 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
13291 return isl_bool_error;
13292 return isl_seq_eq(bmap1->div[pos1] + first,
13293 bmap2->div[pos2] + first, n);
13296 /* Are the integer division expressions at position "pos1" in "bmap1" and
13297 * "pos2" in "bmap2" equal to each other, except that the constant terms
13298 * are different?
13300 isl_bool isl_basic_map_equal_div_expr_except_constant(
13301 __isl_keep isl_basic_map *bmap1, int pos1,
13302 __isl_keep isl_basic_map *bmap2, int pos2)
13304 isl_bool equal;
13305 unsigned total;
13307 if (!bmap1 || !bmap2)
13308 return isl_bool_error;
13309 total = isl_basic_map_total_dim(bmap1);
13310 if (total != isl_basic_map_total_dim(bmap2))
13311 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
13312 "incomparable div expressions", return isl_bool_error);
13313 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13314 0, 1);
13315 if (equal < 0 || !equal)
13316 return equal;
13317 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13318 1, 1);
13319 if (equal < 0 || equal)
13320 return isl_bool_not(equal);
13321 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13322 2, total);
13325 /* Replace the numerator of the constant term of the integer division
13326 * expression at position "div" in "bmap" by "value".
13327 * The caller guarantees that this does not change the meaning
13328 * of the input.
13330 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
13331 __isl_take isl_basic_map *bmap, int div, int value)
13333 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
13334 return isl_basic_map_free(bmap);
13336 isl_int_set_si(bmap->div[div][1], value);
13338 return bmap;
13341 /* Is the point "inner" internal to inequality constraint "ineq"
13342 * of "bset"?
13343 * The point is considered to be internal to the inequality constraint,
13344 * if it strictly lies on the positive side of the inequality constraint,
13345 * or if it lies on the constraint and the constraint is lexico-positive.
13347 static isl_bool is_internal(__isl_keep isl_vec *inner,
13348 __isl_keep isl_basic_set *bset, int ineq)
13350 isl_ctx *ctx;
13351 int pos;
13352 unsigned total;
13354 if (!inner || !bset)
13355 return isl_bool_error;
13357 ctx = isl_basic_set_get_ctx(bset);
13358 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13359 &ctx->normalize_gcd);
13360 if (!isl_int_is_zero(ctx->normalize_gcd))
13361 return isl_int_is_nonneg(ctx->normalize_gcd);
13363 total = isl_basic_set_dim(bset, isl_dim_all);
13364 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13365 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13368 /* Tighten the inequality constraints of "bset" that are outward with respect
13369 * to the point "vec".
13370 * That is, tighten the constraints that are not satisfied by "vec".
13372 * "vec" is a point internal to some superset S of "bset" that is used
13373 * to make the subsets of S disjoint, by tightening one half of the constraints
13374 * that separate two subsets. In particular, the constraints of S
13375 * are all satisfied by "vec" and should not be tightened.
13376 * Of the internal constraints, those that have "vec" on the outside
13377 * are tightened. The shared facet is included in the adjacent subset
13378 * with the opposite constraint.
13379 * For constraints that saturate "vec", this criterion cannot be used
13380 * to determine which of the two sides should be tightened.
13381 * Instead, the sign of the first non-zero coefficient is used
13382 * to make this choice. Note that this second criterion is never used
13383 * on the constraints of S since "vec" is interior to "S".
13385 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13386 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13388 int j;
13390 bset = isl_basic_set_cow(bset);
13391 if (!bset)
13392 return NULL;
13393 for (j = 0; j < bset->n_ineq; ++j) {
13394 isl_bool internal;
13396 internal = is_internal(vec, bset, j);
13397 if (internal < 0)
13398 return isl_basic_set_free(bset);
13399 if (internal)
13400 continue;
13401 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13404 return bset;
13407 /* Replace the variables x of type "type" starting at "first" in "bmap"
13408 * by x' with x = M x' with M the matrix trans.
13409 * That is, replace the corresponding coefficients c by c M.
13411 * The transformation matrix should be a square matrix.
13413 __isl_give isl_basic_map *isl_basic_map_transform_dims(
13414 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
13415 __isl_take isl_mat *trans)
13417 unsigned pos;
13419 bmap = isl_basic_map_cow(bmap);
13420 if (!bmap || !trans)
13421 goto error;
13423 if (trans->n_row != trans->n_col)
13424 isl_die(trans->ctx, isl_error_invalid,
13425 "expecting square transformation matrix", goto error);
13426 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
13427 goto error;
13429 pos = isl_basic_map_offset(bmap, type) + first;
13431 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
13432 isl_mat_copy(trans)) < 0)
13433 goto error;
13434 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
13435 isl_mat_copy(trans)) < 0)
13436 goto error;
13437 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
13438 isl_mat_copy(trans)) < 0)
13439 goto error;
13441 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
13442 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
13444 isl_mat_free(trans);
13445 return bmap;
13446 error:
13447 isl_mat_free(trans);
13448 isl_basic_map_free(bmap);
13449 return NULL;
13452 /* Replace the variables x of type "type" starting at "first" in "bset"
13453 * by x' with x = M x' with M the matrix trans.
13454 * That is, replace the corresponding coefficients c by c M.
13456 * The transformation matrix should be a square matrix.
13458 __isl_give isl_basic_set *isl_basic_set_transform_dims(
13459 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
13460 __isl_take isl_mat *trans)
13462 return isl_basic_map_transform_dims(bset, type, first, trans);