isl_basic_map_offset: use isl_basic_map_peek_space
[isl.git] / isl_map.c
blob9e5cb3154f817a5ee121301b591a27d2de407495
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2014 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
6 * Copyright 2016 INRIA Paris
7 * Copyright 2016 Sven Verdoolaege
9 * Use of this software is governed by the MIT license
11 * Written by Sven Verdoolaege, K.U.Leuven, Departement
12 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
13 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
14 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
15 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
16 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
17 * B.P. 105 - 78153 Le Chesnay, France
18 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
19 * CS 42112, 75589 Paris Cedex 12, France
22 #include <string.h>
23 #include <isl_ctx_private.h>
24 #include <isl_map_private.h>
25 #include <isl_blk.h>
26 #include <isl/id.h>
27 #include <isl/constraint.h>
28 #include "isl_space_private.h"
29 #include "isl_equalities.h"
30 #include <isl_lp_private.h>
31 #include <isl_seq.h>
32 #include <isl/set.h>
33 #include <isl/map.h>
34 #include <isl_reordering.h>
35 #include "isl_sample.h"
36 #include <isl_sort.h>
37 #include "isl_tab.h"
38 #include <isl/vec.h>
39 #include <isl_mat_private.h>
40 #include <isl_vec_private.h>
41 #include <isl_dim_map.h>
42 #include <isl_local_space_private.h>
43 #include <isl_aff_private.h>
44 #include <isl_options_private.h>
45 #include <isl_morph.h>
46 #include <isl_val_private.h>
48 #include <bset_to_bmap.c>
49 #include <bset_from_bmap.c>
50 #include <set_to_map.c>
51 #include <set_from_map.c>
53 /* Treat "bset" as a basic map.
54 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
55 * this function performs a redundant cast.
57 static __isl_keep const isl_basic_map *const_bset_to_bmap(
58 __isl_keep const isl_basic_set *bset)
60 return (const isl_basic_map *) bset;
63 static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
65 switch (type) {
66 case isl_dim_param: return dim->nparam;
67 case isl_dim_in: return dim->n_in;
68 case isl_dim_out: return dim->n_out;
69 case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
70 default: return 0;
74 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
76 switch (type) {
77 case isl_dim_param: return 1;
78 case isl_dim_in: return 1 + dim->nparam;
79 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
80 default: return 0;
84 unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
85 enum isl_dim_type type)
87 if (!bmap)
88 return 0;
89 switch (type) {
90 case isl_dim_cst: return 1;
91 case isl_dim_param:
92 case isl_dim_in:
93 case isl_dim_out: return isl_space_dim(bmap->dim, type);
94 case isl_dim_div: return bmap->n_div;
95 case isl_dim_all: return isl_basic_map_total_dim(bmap);
96 default: return 0;
100 /* Return the space of "map".
102 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
104 return map ? map->dim : NULL;
107 /* Return the space of "set".
109 __isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
111 return isl_map_peek_space(set_to_map(set));
114 unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
116 return map ? n(map->dim, type) : 0;
119 unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
121 return set ? n(set->dim, type) : 0;
124 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
125 enum isl_dim_type type)
127 isl_space *space;
129 space = isl_basic_map_peek_space(bmap);
130 if (!space)
131 return 0;
133 switch (type) {
134 case isl_dim_cst: return 0;
135 case isl_dim_param:
136 case isl_dim_in:
137 case isl_dim_out:
138 return 1 + isl_space_offset(space, type);
139 case isl_dim_div:
140 return 1 + isl_space_dim(space, isl_dim_all);
141 default: return 0;
145 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
146 enum isl_dim_type type)
148 return isl_basic_map_offset(bset, type);
151 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
153 return pos(map->dim, type);
156 unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
157 enum isl_dim_type type)
159 return isl_basic_map_dim(bset, type);
162 unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
164 return isl_basic_set_dim(bset, isl_dim_set);
167 unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
169 return isl_basic_set_dim(bset, isl_dim_param);
172 unsigned isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
174 return isl_basic_map_total_dim(const_bset_to_bmap(bset));
177 unsigned isl_set_n_dim(__isl_keep isl_set *set)
179 return isl_set_dim(set, isl_dim_set);
182 unsigned isl_set_n_param(__isl_keep isl_set *set)
184 return isl_set_dim(set, isl_dim_param);
187 unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap)
189 return bmap ? bmap->dim->n_in : 0;
192 unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap)
194 return bmap ? bmap->dim->n_out : 0;
197 unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap)
199 return bmap ? bmap->dim->nparam : 0;
202 unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap)
204 return bmap ? bmap->n_div : 0;
207 unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
209 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
212 unsigned isl_map_n_in(__isl_keep const isl_map *map)
214 return map ? map->dim->n_in : 0;
217 unsigned isl_map_n_out(__isl_keep const isl_map *map)
219 return map ? map->dim->n_out : 0;
222 unsigned isl_map_n_param(__isl_keep const isl_map *map)
224 return map ? map->dim->nparam : 0;
227 /* Return the number of equality constraints in the description of "bmap".
228 * Return -1 on error.
230 int isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
232 if (!bmap)
233 return -1;
234 return bmap->n_eq;
237 /* Return the number of equality constraints in the description of "bset".
238 * Return -1 on error.
240 int isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
242 return isl_basic_map_n_equality(bset_to_bmap(bset));
245 /* Return the number of inequality constraints in the description of "bmap".
246 * Return -1 on error.
248 int isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
250 if (!bmap)
251 return -1;
252 return bmap->n_ineq;
255 /* Return the number of inequality constraints in the description of "bset".
256 * Return -1 on error.
258 int isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
260 return isl_basic_map_n_inequality(bset_to_bmap(bset));
263 /* Do "bmap1" and "bmap2" have the same parameters?
265 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
266 __isl_keep isl_basic_map *bmap2)
268 isl_space *space1, *space2;
270 space1 = isl_basic_map_peek_space(bmap1);
271 space2 = isl_basic_map_peek_space(bmap2);
272 return isl_space_has_equal_params(space1, space2);
275 /* Do "map1" and "map2" have the same parameters?
277 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
278 __isl_keep isl_map *map2)
280 isl_space *space1, *space2;
282 space1 = isl_map_peek_space(map1);
283 space2 = isl_map_peek_space(map2);
284 return isl_space_has_equal_params(space1, space2);
287 /* Do "map" and "set" have the same parameters?
289 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
290 __isl_keep isl_set *set)
292 return isl_map_has_equal_params(map, set_to_map(set));
295 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
296 __isl_keep isl_set *set)
298 isl_bool m;
299 if (!map || !set)
300 return isl_bool_error;
301 m = isl_map_has_equal_params(map, set_to_map(set));
302 if (m < 0 || !m)
303 return m;
304 return isl_space_tuple_is_equal(map->dim, isl_dim_in,
305 set->dim, isl_dim_set);
308 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
309 __isl_keep isl_basic_set *bset)
311 isl_bool m;
312 if (!bmap || !bset)
313 return isl_bool_error;
314 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
315 if (m < 0 || !m)
316 return m;
317 return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
318 bset->dim, isl_dim_set);
321 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
322 __isl_keep isl_set *set)
324 isl_bool m;
325 if (!map || !set)
326 return isl_bool_error;
327 m = isl_map_has_equal_params(map, set_to_map(set));
328 if (m < 0 || !m)
329 return m;
330 return isl_space_tuple_is_equal(map->dim, isl_dim_out,
331 set->dim, isl_dim_set);
334 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
335 __isl_keep isl_basic_set *bset)
337 isl_bool m;
338 if (!bmap || !bset)
339 return isl_bool_error;
340 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
341 if (m < 0 || !m)
342 return m;
343 return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
344 bset->dim, isl_dim_set);
347 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
349 return bmap ? bmap->ctx : NULL;
352 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
354 return bset ? bset->ctx : NULL;
357 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
359 return map ? map->ctx : NULL;
362 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
364 return set ? set->ctx : NULL;
367 /* Return the space of "bmap".
369 __isl_keep isl_space *isl_basic_map_peek_space(
370 __isl_keep const isl_basic_map *bmap)
372 return bmap ? bmap->dim : NULL;
375 /* Return the space of "bset".
377 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
379 return isl_basic_map_peek_space(bset_to_bmap(bset));
382 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
384 return isl_space_copy(isl_basic_map_peek_space(bmap));
387 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
389 return isl_basic_map_get_space(bset_to_bmap(bset));
392 /* Extract the divs in "bmap" as a matrix.
394 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
396 int i;
397 isl_ctx *ctx;
398 isl_mat *div;
399 unsigned total;
400 unsigned cols;
402 if (!bmap)
403 return NULL;
405 ctx = isl_basic_map_get_ctx(bmap);
406 total = isl_space_dim(bmap->dim, isl_dim_all);
407 cols = 1 + 1 + total + bmap->n_div;
408 div = isl_mat_alloc(ctx, bmap->n_div, cols);
409 if (!div)
410 return NULL;
412 for (i = 0; i < bmap->n_div; ++i)
413 isl_seq_cpy(div->row[i], bmap->div[i], cols);
415 return div;
418 /* Extract the divs in "bset" as a matrix.
420 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
422 return isl_basic_map_get_divs(bset);
425 __isl_give isl_local_space *isl_basic_map_get_local_space(
426 __isl_keep isl_basic_map *bmap)
428 isl_mat *div;
430 if (!bmap)
431 return NULL;
433 div = isl_basic_map_get_divs(bmap);
434 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
437 __isl_give isl_local_space *isl_basic_set_get_local_space(
438 __isl_keep isl_basic_set *bset)
440 return isl_basic_map_get_local_space(bset);
443 /* For each known div d = floor(f/m), add the constraints
445 * f - m d >= 0
446 * -(f-(m-1)) + m d >= 0
448 * Do not finalize the result.
450 static __isl_give isl_basic_map *add_known_div_constraints(
451 __isl_take isl_basic_map *bmap)
453 int i;
454 unsigned n_div;
456 if (!bmap)
457 return NULL;
458 n_div = isl_basic_map_dim(bmap, isl_dim_div);
459 if (n_div == 0)
460 return bmap;
461 bmap = isl_basic_map_cow(bmap);
462 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
463 if (!bmap)
464 return NULL;
465 for (i = 0; i < n_div; ++i) {
466 if (isl_int_is_zero(bmap->div[i][0]))
467 continue;
468 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
469 return isl_basic_map_free(bmap);
472 return bmap;
475 __isl_give isl_basic_map *isl_basic_map_from_local_space(
476 __isl_take isl_local_space *ls)
478 int i;
479 int n_div;
480 isl_basic_map *bmap;
482 if (!ls)
483 return NULL;
485 n_div = isl_local_space_dim(ls, isl_dim_div);
486 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
487 n_div, 0, 2 * n_div);
489 for (i = 0; i < n_div; ++i)
490 if (isl_basic_map_alloc_div(bmap) < 0)
491 goto error;
493 for (i = 0; i < n_div; ++i)
494 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
495 bmap = add_known_div_constraints(bmap);
497 isl_local_space_free(ls);
498 return bmap;
499 error:
500 isl_local_space_free(ls);
501 isl_basic_map_free(bmap);
502 return NULL;
505 __isl_give isl_basic_set *isl_basic_set_from_local_space(
506 __isl_take isl_local_space *ls)
508 return isl_basic_map_from_local_space(ls);
511 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
513 return isl_space_copy(isl_map_peek_space(map));
516 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
518 if (!set)
519 return NULL;
520 return isl_space_copy(set->dim);
523 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
524 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
526 bmap = isl_basic_map_cow(bmap);
527 if (!bmap)
528 return NULL;
529 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
530 if (!bmap->dim)
531 goto error;
532 bmap = isl_basic_map_finalize(bmap);
533 return bmap;
534 error:
535 isl_basic_map_free(bmap);
536 return NULL;
539 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
540 __isl_take isl_basic_set *bset, const char *s)
542 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
545 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
546 enum isl_dim_type type)
548 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
551 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
552 enum isl_dim_type type, const char *s)
554 int i;
556 map = isl_map_cow(map);
557 if (!map)
558 return NULL;
560 map->dim = isl_space_set_tuple_name(map->dim, type, s);
561 if (!map->dim)
562 goto error;
564 for (i = 0; i < map->n; ++i) {
565 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
566 if (!map->p[i])
567 goto error;
570 return map;
571 error:
572 isl_map_free(map);
573 return NULL;
576 /* Replace the identifier of the tuple of type "type" by "id".
578 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
579 __isl_take isl_basic_map *bmap,
580 enum isl_dim_type type, __isl_take isl_id *id)
582 bmap = isl_basic_map_cow(bmap);
583 if (!bmap)
584 goto error;
585 bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
586 if (!bmap->dim)
587 return isl_basic_map_free(bmap);
588 bmap = isl_basic_map_finalize(bmap);
589 return bmap;
590 error:
591 isl_id_free(id);
592 return NULL;
595 /* Replace the identifier of the tuple by "id".
597 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
598 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
600 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
603 /* Does the input or output tuple have a name?
605 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
607 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
610 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
611 enum isl_dim_type type)
613 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
616 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
617 const char *s)
619 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
620 isl_dim_set, s));
623 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
624 enum isl_dim_type type, __isl_take isl_id *id)
626 map = isl_map_cow(map);
627 if (!map)
628 goto error;
630 map->dim = isl_space_set_tuple_id(map->dim, type, id);
632 return isl_map_reset_space(map, isl_space_copy(map->dim));
633 error:
634 isl_id_free(id);
635 return NULL;
638 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
639 __isl_take isl_id *id)
641 return isl_map_set_tuple_id(set, isl_dim_set, id);
644 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
645 enum isl_dim_type type)
647 map = isl_map_cow(map);
648 if (!map)
649 return NULL;
651 map->dim = isl_space_reset_tuple_id(map->dim, type);
653 return isl_map_reset_space(map, isl_space_copy(map->dim));
656 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
658 return isl_map_reset_tuple_id(set, isl_dim_set);
661 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
663 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
666 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
667 enum isl_dim_type type)
669 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
672 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
674 return isl_map_has_tuple_id(set, isl_dim_set);
677 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
679 return isl_map_get_tuple_id(set, isl_dim_set);
682 /* Does the set tuple have a name?
684 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
686 if (!set)
687 return isl_bool_error;
688 return isl_space_has_tuple_name(set->dim, isl_dim_set);
692 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
694 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
697 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
699 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
702 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
703 enum isl_dim_type type, unsigned pos)
705 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
708 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
709 enum isl_dim_type type, unsigned pos)
711 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
714 /* Does the given dimension have a name?
716 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
717 enum isl_dim_type type, unsigned pos)
719 if (!map)
720 return isl_bool_error;
721 return isl_space_has_dim_name(map->dim, type, pos);
724 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
725 enum isl_dim_type type, unsigned pos)
727 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
730 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
731 enum isl_dim_type type, unsigned pos)
733 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
736 /* Does the given dimension have a name?
738 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
739 enum isl_dim_type type, unsigned pos)
741 if (!set)
742 return isl_bool_error;
743 return isl_space_has_dim_name(set->dim, type, pos);
746 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
747 __isl_take isl_basic_map *bmap,
748 enum isl_dim_type type, unsigned pos, const char *s)
750 bmap = isl_basic_map_cow(bmap);
751 if (!bmap)
752 return NULL;
753 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
754 if (!bmap->dim)
755 goto error;
756 return isl_basic_map_finalize(bmap);
757 error:
758 isl_basic_map_free(bmap);
759 return NULL;
762 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
763 enum isl_dim_type type, unsigned pos, const char *s)
765 int i;
767 map = isl_map_cow(map);
768 if (!map)
769 return NULL;
771 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
772 if (!map->dim)
773 goto error;
775 for (i = 0; i < map->n; ++i) {
776 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
777 if (!map->p[i])
778 goto error;
781 return map;
782 error:
783 isl_map_free(map);
784 return NULL;
787 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
788 __isl_take isl_basic_set *bset,
789 enum isl_dim_type type, unsigned pos, const char *s)
791 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
792 type, pos, s));
795 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
796 enum isl_dim_type type, unsigned pos, const char *s)
798 return set_from_map(isl_map_set_dim_name(set_to_map(set),
799 type, pos, s));
802 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
803 enum isl_dim_type type, unsigned pos)
805 if (!bmap)
806 return isl_bool_error;
807 return isl_space_has_dim_id(bmap->dim, type, pos);
810 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
811 enum isl_dim_type type, unsigned pos)
813 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
816 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
817 enum isl_dim_type type, unsigned pos)
819 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
822 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
823 enum isl_dim_type type, unsigned pos)
825 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
828 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
829 enum isl_dim_type type, unsigned pos)
831 return isl_map_has_dim_id(set, type, pos);
834 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
835 enum isl_dim_type type, unsigned pos)
837 return isl_map_get_dim_id(set, type, pos);
840 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
841 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
843 map = isl_map_cow(map);
844 if (!map)
845 goto error;
847 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
849 return isl_map_reset_space(map, isl_space_copy(map->dim));
850 error:
851 isl_id_free(id);
852 return NULL;
855 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
856 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
858 return isl_map_set_dim_id(set, type, pos, id);
861 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
862 __isl_keep isl_id *id)
864 if (!map)
865 return -1;
866 return isl_space_find_dim_by_id(map->dim, type, id);
869 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
870 __isl_keep isl_id *id)
872 return isl_map_find_dim_by_id(set, type, id);
875 /* Return the position of the dimension of the given type and name
876 * in "bmap".
877 * Return -1 if no such dimension can be found.
879 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
880 enum isl_dim_type type, const char *name)
882 if (!bmap)
883 return -1;
884 return isl_space_find_dim_by_name(bmap->dim, type, name);
887 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
888 const char *name)
890 if (!map)
891 return -1;
892 return isl_space_find_dim_by_name(map->dim, type, name);
895 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
896 const char *name)
898 return isl_map_find_dim_by_name(set, type, name);
901 /* Check whether equality i of bset is a pure stride constraint
902 * on a single dimension, i.e., of the form
904 * v = k e
906 * with k a constant and e an existentially quantified variable.
908 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
910 unsigned nparam;
911 unsigned d;
912 unsigned n_div;
913 int pos1;
914 int pos2;
916 if (!bset)
917 return isl_bool_error;
919 if (!isl_int_is_zero(bset->eq[i][0]))
920 return isl_bool_false;
922 nparam = isl_basic_set_dim(bset, isl_dim_param);
923 d = isl_basic_set_dim(bset, isl_dim_set);
924 n_div = isl_basic_set_dim(bset, isl_dim_div);
926 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
927 return isl_bool_false;
928 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
929 if (pos1 == -1)
930 return isl_bool_false;
931 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
932 d - pos1 - 1) != -1)
933 return isl_bool_false;
935 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
936 if (pos2 == -1)
937 return isl_bool_false;
938 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
939 n_div - pos2 - 1) != -1)
940 return isl_bool_false;
941 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
942 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
943 return isl_bool_false;
945 return isl_bool_true;
948 /* Reset the user pointer on all identifiers of parameters and tuples
949 * of the space of "map".
951 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
953 isl_space *space;
955 space = isl_map_get_space(map);
956 space = isl_space_reset_user(space);
957 map = isl_map_reset_space(map, space);
959 return map;
962 /* Reset the user pointer on all identifiers of parameters and tuples
963 * of the space of "set".
965 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
967 return isl_map_reset_user(set);
970 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
972 if (!bmap)
973 return isl_bool_error;
974 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
977 /* Has "map" been marked as a rational map?
978 * In particular, have all basic maps in "map" been marked this way?
979 * An empty map is not considered to be rational.
980 * Maps where only some of the basic maps are marked rational
981 * are not allowed.
983 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
985 int i;
986 isl_bool rational;
988 if (!map)
989 return isl_bool_error;
990 if (map->n == 0)
991 return isl_bool_false;
992 rational = isl_basic_map_is_rational(map->p[0]);
993 if (rational < 0)
994 return rational;
995 for (i = 1; i < map->n; ++i) {
996 isl_bool rational_i;
998 rational_i = isl_basic_map_is_rational(map->p[i]);
999 if (rational_i < 0)
1000 return rational_i;
1001 if (rational != rational_i)
1002 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1003 "mixed rational and integer basic maps "
1004 "not supported", return isl_bool_error);
1007 return rational;
1010 /* Has "set" been marked as a rational set?
1011 * In particular, have all basic set in "set" been marked this way?
1012 * An empty set is not considered to be rational.
1013 * Sets where only some of the basic sets are marked rational
1014 * are not allowed.
1016 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1018 return isl_map_is_rational(set);
1021 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1023 return isl_basic_map_is_rational(bset);
1026 /* Does "bmap" contain any rational points?
1028 * If "bmap" has an equality for each dimension, equating the dimension
1029 * to an integer constant, then it has no rational points, even if it
1030 * is marked as rational.
1032 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1034 isl_bool has_rational = isl_bool_true;
1035 unsigned total;
1037 if (!bmap)
1038 return isl_bool_error;
1039 if (isl_basic_map_plain_is_empty(bmap))
1040 return isl_bool_false;
1041 if (!isl_basic_map_is_rational(bmap))
1042 return isl_bool_false;
1043 bmap = isl_basic_map_copy(bmap);
1044 bmap = isl_basic_map_implicit_equalities(bmap);
1045 if (!bmap)
1046 return isl_bool_error;
1047 total = isl_basic_map_total_dim(bmap);
1048 if (bmap->n_eq == total) {
1049 int i, j;
1050 for (i = 0; i < bmap->n_eq; ++i) {
1051 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1052 if (j < 0)
1053 break;
1054 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1055 !isl_int_is_negone(bmap->eq[i][1 + j]))
1056 break;
1057 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1058 total - j - 1);
1059 if (j >= 0)
1060 break;
1062 if (i == bmap->n_eq)
1063 has_rational = isl_bool_false;
1065 isl_basic_map_free(bmap);
1067 return has_rational;
1070 /* Does "map" contain any rational points?
1072 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1074 int i;
1075 isl_bool has_rational;
1077 if (!map)
1078 return isl_bool_error;
1079 for (i = 0; i < map->n; ++i) {
1080 has_rational = isl_basic_map_has_rational(map->p[i]);
1081 if (has_rational < 0 || has_rational)
1082 return has_rational;
1084 return isl_bool_false;
1087 /* Does "set" contain any rational points?
1089 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1091 return isl_map_has_rational(set);
1094 /* Is this basic set a parameter domain?
1096 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1098 if (!bset)
1099 return isl_bool_error;
1100 return isl_space_is_params(bset->dim);
1103 /* Is this set a parameter domain?
1105 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1107 if (!set)
1108 return isl_bool_error;
1109 return isl_space_is_params(set->dim);
1112 /* Is this map actually a parameter domain?
1113 * Users should never call this function. Outside of isl,
1114 * a map can never be a parameter domain.
1116 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1118 if (!map)
1119 return isl_bool_error;
1120 return isl_space_is_params(map->dim);
1123 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1124 __isl_take isl_basic_map *bmap, unsigned extra,
1125 unsigned n_eq, unsigned n_ineq)
1127 int i;
1128 size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
1130 bmap->ctx = ctx;
1131 isl_ctx_ref(ctx);
1133 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1134 if (isl_blk_is_error(bmap->block))
1135 goto error;
1137 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1138 if ((n_ineq + n_eq) && !bmap->ineq)
1139 goto error;
1141 if (extra == 0) {
1142 bmap->block2 = isl_blk_empty();
1143 bmap->div = NULL;
1144 } else {
1145 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1146 if (isl_blk_is_error(bmap->block2))
1147 goto error;
1149 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1150 if (!bmap->div)
1151 goto error;
1154 for (i = 0; i < n_ineq + n_eq; ++i)
1155 bmap->ineq[i] = bmap->block.data + i * row_size;
1157 for (i = 0; i < extra; ++i)
1158 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1160 bmap->ref = 1;
1161 bmap->flags = 0;
1162 bmap->c_size = n_eq + n_ineq;
1163 bmap->eq = bmap->ineq + n_ineq;
1164 bmap->extra = extra;
1165 bmap->n_eq = 0;
1166 bmap->n_ineq = 0;
1167 bmap->n_div = 0;
1168 bmap->sample = NULL;
1170 return bmap;
1171 error:
1172 isl_basic_map_free(bmap);
1173 return NULL;
1176 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1177 unsigned nparam, unsigned dim, unsigned extra,
1178 unsigned n_eq, unsigned n_ineq)
1180 struct isl_basic_map *bmap;
1181 isl_space *space;
1183 space = isl_space_set_alloc(ctx, nparam, dim);
1184 if (!space)
1185 return NULL;
1187 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1188 return bset_from_bmap(bmap);
1191 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1192 unsigned extra, unsigned n_eq, unsigned n_ineq)
1194 struct isl_basic_map *bmap;
1195 if (!dim)
1196 return NULL;
1197 isl_assert(dim->ctx, dim->n_in == 0, goto error);
1198 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1199 return bset_from_bmap(bmap);
1200 error:
1201 isl_space_free(dim);
1202 return NULL;
1205 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1206 unsigned extra, unsigned n_eq, unsigned n_ineq)
1208 struct isl_basic_map *bmap;
1210 if (!space)
1211 return NULL;
1212 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1213 if (!bmap)
1214 goto error;
1215 bmap->dim = space;
1217 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1218 error:
1219 isl_space_free(space);
1220 return NULL;
1223 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1224 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1225 unsigned n_eq, unsigned n_ineq)
1227 struct isl_basic_map *bmap;
1228 isl_space *dim;
1230 dim = isl_space_alloc(ctx, nparam, in, out);
1231 if (!dim)
1232 return NULL;
1234 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1235 return bmap;
1238 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1239 __isl_keep isl_basic_map *src)
1241 int i;
1242 unsigned total = isl_basic_map_total_dim(src);
1244 if (!dst)
1245 return NULL;
1247 for (i = 0; i < src->n_eq; ++i) {
1248 int j = isl_basic_map_alloc_equality(dst);
1249 if (j < 0)
1250 return isl_basic_map_free(dst);
1251 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1254 for (i = 0; i < src->n_ineq; ++i) {
1255 int j = isl_basic_map_alloc_inequality(dst);
1256 if (j < 0)
1257 return isl_basic_map_free(dst);
1258 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1261 for (i = 0; i < src->n_div; ++i) {
1262 int j = isl_basic_map_alloc_div(dst);
1263 if (j < 0)
1264 return isl_basic_map_free(dst);
1265 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1267 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1268 return dst;
1271 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1273 struct isl_basic_map *dup;
1275 if (!bmap)
1276 return NULL;
1277 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1278 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1279 dup = dup_constraints(dup, bmap);
1280 if (!dup)
1281 return NULL;
1282 dup->flags = bmap->flags;
1283 dup->sample = isl_vec_copy(bmap->sample);
1284 return dup;
1287 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1289 struct isl_basic_map *dup;
1291 dup = isl_basic_map_dup(bset_to_bmap(bset));
1292 return bset_from_bmap(dup);
1295 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1297 if (!bset)
1298 return NULL;
1300 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1301 bset->ref++;
1302 return bset;
1304 return isl_basic_set_dup(bset);
1307 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1309 if (!set)
1310 return NULL;
1312 set->ref++;
1313 return set;
1316 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1318 if (!bmap)
1319 return NULL;
1321 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1322 bmap->ref++;
1323 return bmap;
1325 bmap = isl_basic_map_dup(bmap);
1326 if (bmap)
1327 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1328 return bmap;
1331 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1333 if (!map)
1334 return NULL;
1336 map->ref++;
1337 return map;
1340 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1342 if (!bmap)
1343 return NULL;
1345 if (--bmap->ref > 0)
1346 return NULL;
1348 isl_ctx_deref(bmap->ctx);
1349 free(bmap->div);
1350 isl_blk_free(bmap->ctx, bmap->block2);
1351 free(bmap->ineq);
1352 isl_blk_free(bmap->ctx, bmap->block);
1353 isl_vec_free(bmap->sample);
1354 isl_space_free(bmap->dim);
1355 free(bmap);
1357 return NULL;
1360 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1362 return isl_basic_map_free(bset_to_bmap(bset));
1365 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1367 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1370 /* Check that "map" has only named parameters, reporting an error
1371 * if it does not.
1373 isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1375 return isl_space_check_named_params(isl_map_peek_space(map));
1378 /* Check that "bmap" has only named parameters, reporting an error
1379 * if it does not.
1381 static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
1383 return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
1386 /* Check that "bmap1" and "bmap2" have the same parameters,
1387 * reporting an error if they do not.
1389 static isl_stat isl_basic_map_check_equal_params(
1390 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1392 isl_bool match;
1394 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1395 if (match < 0)
1396 return isl_stat_error;
1397 if (!match)
1398 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1399 "parameters don't match", return isl_stat_error);
1400 return isl_stat_ok;
1403 __isl_give isl_map *isl_map_align_params_map_map_and(
1404 __isl_take isl_map *map1, __isl_take isl_map *map2,
1405 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1406 __isl_take isl_map *map2))
1408 if (!map1 || !map2)
1409 goto error;
1410 if (isl_map_has_equal_params(map1, map2))
1411 return fn(map1, map2);
1412 if (isl_map_check_named_params(map1) < 0)
1413 goto error;
1414 if (isl_map_check_named_params(map2) < 0)
1415 goto error;
1416 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1417 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1418 return fn(map1, map2);
1419 error:
1420 isl_map_free(map1);
1421 isl_map_free(map2);
1422 return NULL;
1425 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1426 __isl_keep isl_map *map2,
1427 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1429 isl_bool r;
1431 if (!map1 || !map2)
1432 return isl_bool_error;
1433 if (isl_map_has_equal_params(map1, map2))
1434 return fn(map1, map2);
1435 if (isl_map_check_named_params(map1) < 0)
1436 return isl_bool_error;
1437 if (isl_map_check_named_params(map2) < 0)
1438 return isl_bool_error;
1439 map1 = isl_map_copy(map1);
1440 map2 = isl_map_copy(map2);
1441 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1442 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1443 r = fn(map1, map2);
1444 isl_map_free(map1);
1445 isl_map_free(map2);
1446 return r;
1449 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1451 struct isl_ctx *ctx;
1452 if (!bmap)
1453 return -1;
1454 ctx = bmap->ctx;
1455 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1456 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1457 return -1);
1458 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1459 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1460 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1461 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1462 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1463 isl_int *t;
1464 int j = isl_basic_map_alloc_inequality(bmap);
1465 if (j < 0)
1466 return -1;
1467 t = bmap->ineq[j];
1468 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1469 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1470 bmap->eq[-1] = t;
1471 bmap->n_eq++;
1472 bmap->n_ineq--;
1473 bmap->eq--;
1474 return 0;
1476 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1477 bmap->extra - bmap->n_div);
1478 return bmap->n_eq++;
1481 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1483 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1486 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1488 if (!bmap)
1489 return -1;
1490 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1491 bmap->n_eq -= n;
1492 return 0;
1495 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1497 return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1500 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1502 isl_int *t;
1503 if (!bmap)
1504 return -1;
1505 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1507 if (pos != bmap->n_eq - 1) {
1508 t = bmap->eq[pos];
1509 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1510 bmap->eq[bmap->n_eq - 1] = t;
1512 bmap->n_eq--;
1513 return 0;
1516 /* Turn inequality "pos" of "bmap" into an equality.
1518 * In particular, we move the inequality in front of the equalities
1519 * and move the last inequality in the position of the moved inequality.
1520 * Note that isl_tab_make_equalities_explicit depends on this particular
1521 * change in the ordering of the constraints.
1523 void isl_basic_map_inequality_to_equality(
1524 struct isl_basic_map *bmap, unsigned pos)
1526 isl_int *t;
1528 t = bmap->ineq[pos];
1529 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1530 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1531 bmap->eq[-1] = t;
1532 bmap->n_eq++;
1533 bmap->n_ineq--;
1534 bmap->eq--;
1535 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1536 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1537 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1538 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1541 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1543 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1546 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1548 struct isl_ctx *ctx;
1549 if (!bmap)
1550 return -1;
1551 ctx = bmap->ctx;
1552 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1553 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1554 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1555 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1556 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1557 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1558 1 + isl_basic_map_total_dim(bmap),
1559 bmap->extra - bmap->n_div);
1560 return bmap->n_ineq++;
1563 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1565 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1568 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1570 if (!bmap)
1571 return -1;
1572 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1573 bmap->n_ineq -= n;
1574 return 0;
1577 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1579 return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1582 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1584 isl_int *t;
1585 if (!bmap)
1586 return -1;
1587 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1589 if (pos != bmap->n_ineq - 1) {
1590 t = bmap->ineq[pos];
1591 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1592 bmap->ineq[bmap->n_ineq - 1] = t;
1593 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1595 bmap->n_ineq--;
1596 return 0;
1599 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1601 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1604 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1605 isl_int *eq)
1607 isl_bool empty;
1608 int k;
1610 empty = isl_basic_map_plain_is_empty(bmap);
1611 if (empty < 0)
1612 return isl_basic_map_free(bmap);
1613 if (empty)
1614 return bmap;
1616 bmap = isl_basic_map_cow(bmap);
1617 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1618 if (!bmap)
1619 return NULL;
1620 k = isl_basic_map_alloc_equality(bmap);
1621 if (k < 0)
1622 goto error;
1623 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1624 return bmap;
1625 error:
1626 isl_basic_map_free(bmap);
1627 return NULL;
1630 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1631 isl_int *eq)
1633 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1636 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1637 isl_int *ineq)
1639 int k;
1641 bmap = isl_basic_map_cow(bmap);
1642 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1643 if (!bmap)
1644 return NULL;
1645 k = isl_basic_map_alloc_inequality(bmap);
1646 if (k < 0)
1647 goto error;
1648 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1649 return bmap;
1650 error:
1651 isl_basic_map_free(bmap);
1652 return NULL;
1655 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1656 isl_int *ineq)
1658 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1661 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1663 if (!bmap)
1664 return -1;
1665 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1666 isl_seq_clr(bmap->div[bmap->n_div] +
1667 1 + 1 + isl_basic_map_total_dim(bmap),
1668 bmap->extra - bmap->n_div);
1669 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1670 return bmap->n_div++;
1673 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1675 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1678 /* Check that there are "n" dimensions of type "type" starting at "first"
1679 * in "bmap".
1681 static isl_stat isl_basic_map_check_range(__isl_keep isl_basic_map *bmap,
1682 enum isl_dim_type type, unsigned first, unsigned n)
1684 unsigned dim;
1686 if (!bmap)
1687 return isl_stat_error;
1688 dim = isl_basic_map_dim(bmap, type);
1689 if (first + n > dim || first + n < first)
1690 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1691 "position or range out of bounds",
1692 return isl_stat_error);
1693 return isl_stat_ok;
1696 /* Insert an extra integer division, prescribed by "div", to "bmap"
1697 * at (integer division) position "pos".
1699 * The integer division is first added at the end and then moved
1700 * into the right position.
1702 __isl_give isl_basic_map *isl_basic_map_insert_div(
1703 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1705 int i, k;
1707 bmap = isl_basic_map_cow(bmap);
1708 if (!bmap || !div)
1709 return isl_basic_map_free(bmap);
1711 if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1712 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1713 "unexpected size", return isl_basic_map_free(bmap));
1714 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1715 return isl_basic_map_free(bmap);
1717 bmap = isl_basic_map_extend_space(bmap,
1718 isl_basic_map_get_space(bmap), 1, 0, 2);
1719 k = isl_basic_map_alloc_div(bmap);
1720 if (k < 0)
1721 return isl_basic_map_free(bmap);
1722 isl_seq_cpy(bmap->div[k], div->el, div->size);
1723 isl_int_set_si(bmap->div[k][div->size], 0);
1725 for (i = k; i > pos; --i)
1726 isl_basic_map_swap_div(bmap, i, i - 1);
1728 return bmap;
1731 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1733 if (!bmap)
1734 return isl_stat_error;
1735 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1736 bmap->n_div -= n;
1737 return isl_stat_ok;
1740 static __isl_give isl_basic_map *add_constraints(
1741 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1742 unsigned i_pos, unsigned o_pos)
1744 unsigned total, n_param, n_in, o_in, n_out, o_out, n_div;
1745 isl_ctx *ctx;
1746 isl_space *space;
1747 struct isl_dim_map *dim_map;
1749 space = isl_basic_map_peek_space(bmap2);
1750 if (!bmap1 || !space)
1751 goto error;
1753 total = isl_basic_map_dim(bmap1, isl_dim_all);
1754 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1755 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1756 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1757 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1758 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1759 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1760 ctx = isl_basic_map_get_ctx(bmap1);
1761 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1762 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1763 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1764 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1765 isl_dim_map_div(dim_map, bmap2, total);
1767 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1768 error:
1769 isl_basic_map_free(bmap1);
1770 isl_basic_map_free(bmap2);
1771 return NULL;
1774 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1775 struct isl_basic_set *bset2, unsigned pos)
1777 return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1778 bset_to_bmap(bset2), 0, pos));
1781 __isl_give isl_basic_map *isl_basic_map_extend_space(
1782 __isl_take isl_basic_map *base, __isl_take isl_space *space,
1783 unsigned extra, unsigned n_eq, unsigned n_ineq)
1785 struct isl_basic_map *ext;
1786 unsigned flags;
1787 int dims_ok;
1789 if (!space)
1790 goto error;
1792 if (!base)
1793 goto error;
1795 dims_ok = isl_space_is_equal(base->dim, space) &&
1796 base->extra >= base->n_div + extra;
1798 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1799 room_for_ineq(base, n_ineq)) {
1800 isl_space_free(space);
1801 return base;
1804 isl_assert(base->ctx, base->dim->nparam <= space->nparam, goto error);
1805 isl_assert(base->ctx, base->dim->n_in <= space->n_in, goto error);
1806 isl_assert(base->ctx, base->dim->n_out <= space->n_out, goto error);
1807 extra += base->extra;
1808 n_eq += base->n_eq;
1809 n_ineq += base->n_ineq;
1811 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1812 space = NULL;
1813 if (!ext)
1814 goto error;
1816 if (dims_ok)
1817 ext->sample = isl_vec_copy(base->sample);
1818 flags = base->flags;
1819 ext = add_constraints(ext, base, 0, 0);
1820 if (ext) {
1821 ext->flags = flags;
1822 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1825 return ext;
1827 error:
1828 isl_space_free(space);
1829 isl_basic_map_free(base);
1830 return NULL;
1833 __isl_give isl_basic_set *isl_basic_set_extend_space(
1834 __isl_take isl_basic_set *base,
1835 __isl_take isl_space *dim, unsigned extra,
1836 unsigned n_eq, unsigned n_ineq)
1838 return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1839 dim, extra, n_eq, n_ineq));
1842 struct isl_basic_map *isl_basic_map_extend_constraints(
1843 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1845 if (!base)
1846 return NULL;
1847 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1848 0, n_eq, n_ineq);
1851 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1852 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1853 unsigned n_eq, unsigned n_ineq)
1855 struct isl_basic_map *bmap;
1856 isl_space *dim;
1858 if (!base)
1859 return NULL;
1860 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1861 if (!dim)
1862 goto error;
1864 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1865 return bmap;
1866 error:
1867 isl_basic_map_free(base);
1868 return NULL;
1871 struct isl_basic_set *isl_basic_set_extend_constraints(
1872 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1874 isl_basic_map *bmap = bset_to_bmap(base);
1875 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1876 return bset_from_bmap(bmap);
1879 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1881 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1884 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1886 if (!bmap)
1887 return NULL;
1889 if (bmap->ref > 1) {
1890 bmap->ref--;
1891 bmap = isl_basic_map_dup(bmap);
1893 if (bmap) {
1894 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1895 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1897 return bmap;
1900 /* Clear all cached information in "map", either because it is about
1901 * to be modified or because it is being freed.
1902 * Always return the same pointer that is passed in.
1903 * This is needed for the use in isl_map_free.
1905 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1907 isl_basic_map_free(map->cached_simple_hull[0]);
1908 isl_basic_map_free(map->cached_simple_hull[1]);
1909 map->cached_simple_hull[0] = NULL;
1910 map->cached_simple_hull[1] = NULL;
1911 return map;
1914 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
1916 return isl_map_cow(set);
1919 /* Return an isl_map that is equal to "map" and that has only
1920 * a single reference.
1922 * If the original input already has only one reference, then
1923 * simply return it, but clear all cached information, since
1924 * it may be rendered invalid by the operations that will be
1925 * performed on the result.
1927 * Otherwise, create a duplicate (without any cached information).
1929 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
1931 if (!map)
1932 return NULL;
1934 if (map->ref == 1)
1935 return clear_caches(map);
1936 map->ref--;
1937 return isl_map_dup(map);
1940 static void swap_vars(struct isl_blk blk, isl_int *a,
1941 unsigned a_len, unsigned b_len)
1943 isl_seq_cpy(blk.data, a+a_len, b_len);
1944 isl_seq_cpy(blk.data+b_len, a, a_len);
1945 isl_seq_cpy(a, blk.data, b_len+a_len);
1948 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1949 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1951 int i;
1952 struct isl_blk blk;
1954 if (!bmap)
1955 goto error;
1957 isl_assert(bmap->ctx,
1958 pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
1960 if (n1 == 0 || n2 == 0)
1961 return bmap;
1963 bmap = isl_basic_map_cow(bmap);
1964 if (!bmap)
1965 return NULL;
1967 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
1968 if (isl_blk_is_error(blk))
1969 goto error;
1971 for (i = 0; i < bmap->n_eq; ++i)
1972 swap_vars(blk,
1973 bmap->eq[i] + pos, n1, n2);
1975 for (i = 0; i < bmap->n_ineq; ++i)
1976 swap_vars(blk,
1977 bmap->ineq[i] + pos, n1, n2);
1979 for (i = 0; i < bmap->n_div; ++i)
1980 swap_vars(blk,
1981 bmap->div[i]+1 + pos, n1, n2);
1983 isl_blk_free(bmap->ctx, blk);
1985 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
1986 bmap = isl_basic_map_gauss(bmap, NULL);
1987 return isl_basic_map_finalize(bmap);
1988 error:
1989 isl_basic_map_free(bmap);
1990 return NULL;
1993 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
1994 __isl_take isl_basic_map *bmap)
1996 int i = 0;
1997 unsigned total;
1998 if (!bmap)
1999 goto error;
2000 total = isl_basic_map_total_dim(bmap);
2001 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2002 return isl_basic_map_free(bmap);
2003 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2004 if (bmap->n_eq > 0)
2005 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
2006 else {
2007 i = isl_basic_map_alloc_equality(bmap);
2008 if (i < 0)
2009 goto error;
2011 isl_int_set_si(bmap->eq[i][0], 1);
2012 isl_seq_clr(bmap->eq[i]+1, total);
2013 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2014 isl_vec_free(bmap->sample);
2015 bmap->sample = NULL;
2016 return isl_basic_map_finalize(bmap);
2017 error:
2018 isl_basic_map_free(bmap);
2019 return NULL;
2022 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2023 __isl_take isl_basic_set *bset)
2025 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2028 __isl_give isl_basic_map *isl_basic_map_set_rational(
2029 __isl_take isl_basic_map *bmap)
2031 if (!bmap)
2032 return NULL;
2034 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2035 return bmap;
2037 bmap = isl_basic_map_cow(bmap);
2038 if (!bmap)
2039 return NULL;
2041 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2043 return isl_basic_map_finalize(bmap);
2046 __isl_give isl_basic_set *isl_basic_set_set_rational(
2047 __isl_take isl_basic_set *bset)
2049 return isl_basic_map_set_rational(bset);
2052 __isl_give isl_basic_set *isl_basic_set_set_integral(
2053 __isl_take isl_basic_set *bset)
2055 if (!bset)
2056 return NULL;
2058 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2059 return bset;
2061 bset = isl_basic_set_cow(bset);
2062 if (!bset)
2063 return NULL;
2065 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2067 return isl_basic_set_finalize(bset);
2070 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2072 int i;
2074 map = isl_map_cow(map);
2075 if (!map)
2076 return NULL;
2077 for (i = 0; i < map->n; ++i) {
2078 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2079 if (!map->p[i])
2080 goto error;
2082 return map;
2083 error:
2084 isl_map_free(map);
2085 return NULL;
2088 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2090 return isl_map_set_rational(set);
2093 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2094 * of "bmap").
2096 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2098 isl_int *t = bmap->div[a];
2099 bmap->div[a] = bmap->div[b];
2100 bmap->div[b] = t;
2103 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2104 * div definitions accordingly.
2106 void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
2108 int i;
2109 unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
2111 swap_div(bmap, a, b);
2113 for (i = 0; i < bmap->n_eq; ++i)
2114 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2116 for (i = 0; i < bmap->n_ineq; ++i)
2117 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2119 for (i = 0; i < bmap->n_div; ++i)
2120 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2121 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2124 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2126 isl_seq_cpy(c, c + n, rem);
2127 isl_seq_clr(c + rem, n);
2130 /* Drop n dimensions starting at first.
2132 * In principle, this frees up some extra variables as the number
2133 * of columns remains constant, but we would have to extend
2134 * the div array too as the number of rows in this array is assumed
2135 * to be equal to extra.
2137 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2138 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2140 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2143 /* Move "n" divs starting at "first" to the end of the list of divs.
2145 static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
2146 unsigned first, unsigned n)
2148 isl_int **div;
2149 int i;
2151 if (first + n == bmap->n_div)
2152 return bmap;
2154 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2155 if (!div)
2156 goto error;
2157 for (i = 0; i < n; ++i)
2158 div[i] = bmap->div[first + i];
2159 for (i = 0; i < bmap->n_div - first - n; ++i)
2160 bmap->div[first + i] = bmap->div[first + n + i];
2161 for (i = 0; i < n; ++i)
2162 bmap->div[bmap->n_div - n + i] = div[i];
2163 free(div);
2164 return bmap;
2165 error:
2166 isl_basic_map_free(bmap);
2167 return NULL;
2170 /* Check that there are "n" dimensions of type "type" starting at "first"
2171 * in "map".
2173 static isl_stat isl_map_check_range(__isl_keep isl_map *map,
2174 enum isl_dim_type type, unsigned first, unsigned n)
2176 if (!map)
2177 return isl_stat_error;
2178 if (first + n > isl_map_dim(map, type) || first + n < first)
2179 isl_die(isl_map_get_ctx(map), isl_error_invalid,
2180 "position or range out of bounds",
2181 return isl_stat_error);
2182 return isl_stat_ok;
2185 /* Drop "n" dimensions of type "type" starting at "first".
2187 * In principle, this frees up some extra variables as the number
2188 * of columns remains constant, but we would have to extend
2189 * the div array too as the number of rows in this array is assumed
2190 * to be equal to extra.
2192 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2193 enum isl_dim_type type, unsigned first, unsigned n)
2195 int i;
2196 unsigned dim;
2197 unsigned offset;
2198 unsigned left;
2200 if (!bmap)
2201 goto error;
2203 dim = isl_basic_map_dim(bmap, type);
2204 isl_assert(bmap->ctx, first + n <= dim, goto error);
2206 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2207 return bmap;
2209 bmap = isl_basic_map_cow(bmap);
2210 if (!bmap)
2211 return NULL;
2213 offset = isl_basic_map_offset(bmap, type) + first;
2214 left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
2215 for (i = 0; i < bmap->n_eq; ++i)
2216 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2218 for (i = 0; i < bmap->n_ineq; ++i)
2219 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2221 for (i = 0; i < bmap->n_div; ++i)
2222 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2224 if (type == isl_dim_div) {
2225 bmap = move_divs_last(bmap, first, n);
2226 if (!bmap)
2227 goto error;
2228 if (isl_basic_map_free_div(bmap, n) < 0)
2229 return isl_basic_map_free(bmap);
2230 } else
2231 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2232 if (!bmap->dim)
2233 goto error;
2235 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2236 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2237 bmap = isl_basic_map_simplify(bmap);
2238 return isl_basic_map_finalize(bmap);
2239 error:
2240 isl_basic_map_free(bmap);
2241 return NULL;
2244 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2245 enum isl_dim_type type, unsigned first, unsigned n)
2247 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2248 type, first, n));
2251 /* No longer consider "map" to be normalized.
2253 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2255 if (!map)
2256 return NULL;
2257 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2258 return map;
2261 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2262 enum isl_dim_type type, unsigned first, unsigned n)
2264 int i;
2266 if (isl_map_check_range(map, type, first, n) < 0)
2267 return isl_map_free(map);
2269 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2270 return map;
2271 map = isl_map_cow(map);
2272 if (!map)
2273 goto error;
2274 map->dim = isl_space_drop_dims(map->dim, type, first, n);
2275 if (!map->dim)
2276 goto error;
2278 for (i = 0; i < map->n; ++i) {
2279 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2280 if (!map->p[i])
2281 goto error;
2283 map = isl_map_unmark_normalized(map);
2285 return map;
2286 error:
2287 isl_map_free(map);
2288 return NULL;
2291 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2292 enum isl_dim_type type, unsigned first, unsigned n)
2294 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2298 * We don't cow, as the div is assumed to be redundant.
2300 __isl_give isl_basic_map *isl_basic_map_drop_div(
2301 __isl_take isl_basic_map *bmap, unsigned div)
2303 int i;
2304 unsigned pos;
2306 if (!bmap)
2307 goto error;
2309 pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
2311 isl_assert(bmap->ctx, div < bmap->n_div, goto error);
2313 for (i = 0; i < bmap->n_eq; ++i)
2314 constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
2316 for (i = 0; i < bmap->n_ineq; ++i) {
2317 if (!isl_int_is_zero(bmap->ineq[i][pos])) {
2318 isl_basic_map_drop_inequality(bmap, i);
2319 --i;
2320 continue;
2322 constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
2325 for (i = 0; i < bmap->n_div; ++i)
2326 constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
2328 if (div != bmap->n_div - 1) {
2329 int j;
2330 isl_int *t = bmap->div[div];
2332 for (j = div; j < bmap->n_div - 1; ++j)
2333 bmap->div[j] = bmap->div[j+1];
2335 bmap->div[bmap->n_div - 1] = t;
2337 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2338 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2339 if (isl_basic_map_free_div(bmap, 1) < 0)
2340 return isl_basic_map_free(bmap);
2342 return bmap;
2343 error:
2344 isl_basic_map_free(bmap);
2345 return NULL;
2348 /* Eliminate the specified n dimensions starting at first from the
2349 * constraints, without removing the dimensions from the space.
2350 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2352 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2353 enum isl_dim_type type, unsigned first, unsigned n)
2355 int i;
2357 if (n == 0)
2358 return map;
2360 if (isl_map_check_range(map, type, first, n) < 0)
2361 return isl_map_free(map);
2363 map = isl_map_cow(map);
2364 if (!map)
2365 return NULL;
2367 for (i = 0; i < map->n; ++i) {
2368 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2369 if (!map->p[i])
2370 goto error;
2372 return map;
2373 error:
2374 isl_map_free(map);
2375 return NULL;
2378 /* Eliminate the specified n dimensions starting at first from the
2379 * constraints, without removing the dimensions from the space.
2380 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2382 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2383 enum isl_dim_type type, unsigned first, unsigned n)
2385 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2388 /* Eliminate the specified n dimensions starting at first from the
2389 * constraints, without removing the dimensions from the space.
2390 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2392 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2393 unsigned first, unsigned n)
2395 return isl_set_eliminate(set, isl_dim_set, first, n);
2398 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2399 __isl_take isl_basic_map *bmap)
2401 if (!bmap)
2402 return NULL;
2403 bmap = isl_basic_map_eliminate_vars(bmap,
2404 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
2405 if (!bmap)
2406 return NULL;
2407 bmap->n_div = 0;
2408 return isl_basic_map_finalize(bmap);
2411 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2412 __isl_take isl_basic_set *bset)
2414 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2417 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2419 int i;
2421 if (!map)
2422 return NULL;
2423 if (map->n == 0)
2424 return map;
2426 map = isl_map_cow(map);
2427 if (!map)
2428 return NULL;
2430 for (i = 0; i < map->n; ++i) {
2431 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2432 if (!map->p[i])
2433 goto error;
2435 return map;
2436 error:
2437 isl_map_free(map);
2438 return NULL;
2441 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2443 return isl_map_remove_divs(set);
2446 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2447 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2448 unsigned first, unsigned n)
2450 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2451 return isl_basic_map_free(bmap);
2452 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2453 return bmap;
2454 bmap = isl_basic_map_eliminate_vars(bmap,
2455 isl_basic_map_offset(bmap, type) - 1 + first, n);
2456 if (!bmap)
2457 return bmap;
2458 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2459 return bmap;
2460 bmap = isl_basic_map_drop(bmap, type, first, n);
2461 return bmap;
2464 /* Return true if the definition of the given div (recursively) involves
2465 * any of the given variables.
2467 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2468 unsigned first, unsigned n)
2470 int i;
2471 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2473 if (isl_int_is_zero(bmap->div[div][0]))
2474 return isl_bool_false;
2475 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2476 return isl_bool_true;
2478 for (i = bmap->n_div - 1; i >= 0; --i) {
2479 isl_bool involves;
2481 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2482 continue;
2483 involves = div_involves_vars(bmap, i, first, n);
2484 if (involves < 0 || involves)
2485 return involves;
2488 return isl_bool_false;
2491 /* Try and add a lower and/or upper bound on "div" to "bmap"
2492 * based on inequality "i".
2493 * "total" is the total number of variables (excluding the divs).
2494 * "v" is a temporary object that can be used during the calculations.
2495 * If "lb" is set, then a lower bound should be constructed.
2496 * If "ub" is set, then an upper bound should be constructed.
2498 * The calling function has already checked that the inequality does not
2499 * reference "div", but we still need to check that the inequality is
2500 * of the right form. We'll consider the case where we want to construct
2501 * a lower bound. The construction of upper bounds is similar.
2503 * Let "div" be of the form
2505 * q = floor((a + f(x))/d)
2507 * We essentially check if constraint "i" is of the form
2509 * b + f(x) >= 0
2511 * so that we can use it to derive a lower bound on "div".
2512 * However, we allow a slightly more general form
2514 * b + g(x) >= 0
2516 * with the condition that the coefficients of g(x) - f(x) are all
2517 * divisible by d.
2518 * Rewriting this constraint as
2520 * 0 >= -b - g(x)
2522 * adding a + f(x) to both sides and dividing by d, we obtain
2524 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2526 * Taking the floor on both sides, we obtain
2528 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2530 * or
2532 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2534 * In the case of an upper bound, we construct the constraint
2536 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2539 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2540 __isl_take isl_basic_map *bmap, int div, int i,
2541 unsigned total, isl_int v, int lb, int ub)
2543 int j;
2545 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2546 if (lb) {
2547 isl_int_sub(v, bmap->ineq[i][1 + j],
2548 bmap->div[div][1 + 1 + j]);
2549 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2551 if (ub) {
2552 isl_int_add(v, bmap->ineq[i][1 + j],
2553 bmap->div[div][1 + 1 + j]);
2554 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2557 if (!lb && !ub)
2558 return bmap;
2560 bmap = isl_basic_map_cow(bmap);
2561 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2562 if (lb) {
2563 int k = isl_basic_map_alloc_inequality(bmap);
2564 if (k < 0)
2565 goto error;
2566 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2567 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2568 bmap->div[div][1 + j]);
2569 isl_int_cdiv_q(bmap->ineq[k][j],
2570 bmap->ineq[k][j], bmap->div[div][0]);
2572 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2574 if (ub) {
2575 int k = isl_basic_map_alloc_inequality(bmap);
2576 if (k < 0)
2577 goto error;
2578 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2579 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2580 bmap->div[div][1 + j]);
2581 isl_int_fdiv_q(bmap->ineq[k][j],
2582 bmap->ineq[k][j], bmap->div[div][0]);
2584 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2587 return bmap;
2588 error:
2589 isl_basic_map_free(bmap);
2590 return NULL;
2593 /* This function is called right before "div" is eliminated from "bmap"
2594 * using Fourier-Motzkin.
2595 * Look through the constraints of "bmap" for constraints on the argument
2596 * of the integer division and use them to construct constraints on the
2597 * integer division itself. These constraints can then be combined
2598 * during the Fourier-Motzkin elimination.
2599 * Note that it is only useful to introduce lower bounds on "div"
2600 * if "bmap" already contains upper bounds on "div" as the newly
2601 * introduce lower bounds can then be combined with the pre-existing
2602 * upper bounds. Similarly for upper bounds.
2603 * We therefore first check if "bmap" contains any lower and/or upper bounds
2604 * on "div".
2606 * It is interesting to note that the introduction of these constraints
2607 * can indeed lead to more accurate results, even when compared to
2608 * deriving constraints on the argument of "div" from constraints on "div".
2609 * Consider, for example, the set
2611 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2613 * The second constraint can be rewritten as
2615 * 2 * [(-i-2j+3)/4] + k >= 0
2617 * from which we can derive
2619 * -i - 2j + 3 >= -2k
2621 * or
2623 * i + 2j <= 3 + 2k
2625 * Combined with the first constraint, we obtain
2627 * -3 <= 3 + 2k or k >= -3
2629 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2630 * the first constraint, we obtain
2632 * [(i + 2j)/4] >= [-3/4] = -1
2634 * Combining this constraint with the second constraint, we obtain
2636 * k >= -2
2638 static __isl_give isl_basic_map *insert_bounds_on_div(
2639 __isl_take isl_basic_map *bmap, int div)
2641 int i;
2642 int check_lb, check_ub;
2643 isl_int v;
2644 unsigned total;
2646 if (!bmap)
2647 return NULL;
2649 if (isl_int_is_zero(bmap->div[div][0]))
2650 return bmap;
2652 total = isl_space_dim(bmap->dim, isl_dim_all);
2654 check_lb = 0;
2655 check_ub = 0;
2656 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2657 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2658 if (s > 0)
2659 check_ub = 1;
2660 if (s < 0)
2661 check_lb = 1;
2664 if (!check_lb && !check_ub)
2665 return bmap;
2667 isl_int_init(v);
2669 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2670 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2671 continue;
2673 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2674 check_lb, check_ub);
2677 isl_int_clear(v);
2679 return bmap;
2682 /* Remove all divs (recursively) involving any of the given dimensions
2683 * in their definitions.
2685 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2686 __isl_take isl_basic_map *bmap,
2687 enum isl_dim_type type, unsigned first, unsigned n)
2689 int i;
2691 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2692 return isl_basic_map_free(bmap);
2693 first += isl_basic_map_offset(bmap, type);
2695 for (i = bmap->n_div - 1; i >= 0; --i) {
2696 isl_bool involves;
2698 involves = div_involves_vars(bmap, i, first, n);
2699 if (involves < 0)
2700 return isl_basic_map_free(bmap);
2701 if (!involves)
2702 continue;
2703 bmap = insert_bounds_on_div(bmap, i);
2704 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2705 if (!bmap)
2706 return NULL;
2707 i = bmap->n_div;
2710 return bmap;
2713 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2714 __isl_take isl_basic_set *bset,
2715 enum isl_dim_type type, unsigned first, unsigned n)
2717 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2720 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2721 enum isl_dim_type type, unsigned first, unsigned n)
2723 int i;
2725 if (!map)
2726 return NULL;
2727 if (map->n == 0)
2728 return map;
2730 map = isl_map_cow(map);
2731 if (!map)
2732 return NULL;
2734 for (i = 0; i < map->n; ++i) {
2735 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2736 type, first, n);
2737 if (!map->p[i])
2738 goto error;
2740 return map;
2741 error:
2742 isl_map_free(map);
2743 return NULL;
2746 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2747 enum isl_dim_type type, unsigned first, unsigned n)
2749 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2750 type, first, n));
2753 /* Does the description of "bmap" depend on the specified dimensions?
2754 * We also check whether the dimensions appear in any of the div definitions.
2755 * In principle there is no need for this check. If the dimensions appear
2756 * in a div definition, they also appear in the defining constraints of that
2757 * div.
2759 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2760 enum isl_dim_type type, unsigned first, unsigned n)
2762 int i;
2764 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2765 return isl_bool_error;
2767 first += isl_basic_map_offset(bmap, type);
2768 for (i = 0; i < bmap->n_eq; ++i)
2769 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2770 return isl_bool_true;
2771 for (i = 0; i < bmap->n_ineq; ++i)
2772 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2773 return isl_bool_true;
2774 for (i = 0; i < bmap->n_div; ++i) {
2775 if (isl_int_is_zero(bmap->div[i][0]))
2776 continue;
2777 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2778 return isl_bool_true;
2781 return isl_bool_false;
2784 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2785 enum isl_dim_type type, unsigned first, unsigned n)
2787 int i;
2789 if (isl_map_check_range(map, type, first, n) < 0)
2790 return isl_bool_error;
2792 for (i = 0; i < map->n; ++i) {
2793 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2794 type, first, n);
2795 if (involves < 0 || involves)
2796 return involves;
2799 return isl_bool_false;
2802 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2803 enum isl_dim_type type, unsigned first, unsigned n)
2805 return isl_basic_map_involves_dims(bset, type, first, n);
2808 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2809 enum isl_dim_type type, unsigned first, unsigned n)
2811 return isl_map_involves_dims(set, type, first, n);
2814 /* Drop all constraints in bmap that involve any of the dimensions
2815 * first to first+n-1.
2817 static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2818 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2820 int i;
2822 if (n == 0)
2823 return bmap;
2825 bmap = isl_basic_map_cow(bmap);
2827 if (!bmap)
2828 return NULL;
2830 for (i = bmap->n_eq - 1; i >= 0; --i) {
2831 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2832 continue;
2833 isl_basic_map_drop_equality(bmap, i);
2836 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2837 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2838 continue;
2839 isl_basic_map_drop_inequality(bmap, i);
2842 bmap = isl_basic_map_add_known_div_constraints(bmap);
2843 return bmap;
2846 /* Drop all constraints in bset that involve any of the dimensions
2847 * first to first+n-1.
2849 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2850 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2852 return isl_basic_map_drop_constraints_involving(bset, first, n);
2855 /* Drop all constraints in bmap that do not involve any of the dimensions
2856 * first to first + n - 1 of the given type.
2858 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2859 __isl_take isl_basic_map *bmap,
2860 enum isl_dim_type type, unsigned first, unsigned n)
2862 int i;
2864 if (n == 0) {
2865 isl_space *space = isl_basic_map_get_space(bmap);
2866 isl_basic_map_free(bmap);
2867 return isl_basic_map_universe(space);
2869 bmap = isl_basic_map_cow(bmap);
2870 if (!bmap)
2871 return NULL;
2873 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2874 return isl_basic_map_free(bmap);
2876 first += isl_basic_map_offset(bmap, type) - 1;
2878 for (i = bmap->n_eq - 1; i >= 0; --i) {
2879 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2880 continue;
2881 isl_basic_map_drop_equality(bmap, i);
2884 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2885 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2886 continue;
2887 isl_basic_map_drop_inequality(bmap, i);
2890 bmap = isl_basic_map_add_known_div_constraints(bmap);
2891 return bmap;
2894 /* Drop all constraints in bset that do not involve any of the dimensions
2895 * first to first + n - 1 of the given type.
2897 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2898 __isl_take isl_basic_set *bset,
2899 enum isl_dim_type type, unsigned first, unsigned n)
2901 return isl_basic_map_drop_constraints_not_involving_dims(bset,
2902 type, first, n);
2905 /* Drop all constraints in bmap that involve any of the dimensions
2906 * first to first + n - 1 of the given type.
2908 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2909 __isl_take isl_basic_map *bmap,
2910 enum isl_dim_type type, unsigned first, unsigned n)
2912 if (!bmap)
2913 return NULL;
2914 if (n == 0)
2915 return bmap;
2917 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2918 return isl_basic_map_free(bmap);
2920 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2921 first += isl_basic_map_offset(bmap, type) - 1;
2922 return isl_basic_map_drop_constraints_involving(bmap, first, n);
2925 /* Drop all constraints in bset that involve any of the dimensions
2926 * first to first + n - 1 of the given type.
2928 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2929 __isl_take isl_basic_set *bset,
2930 enum isl_dim_type type, unsigned first, unsigned n)
2932 return isl_basic_map_drop_constraints_involving_dims(bset,
2933 type, first, n);
2936 /* Drop constraints from "map" by applying "drop" to each basic map.
2938 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2939 enum isl_dim_type type, unsigned first, unsigned n,
2940 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2941 enum isl_dim_type type, unsigned first, unsigned n))
2943 int i;
2945 if (isl_map_check_range(map, type, first, n) < 0)
2946 return isl_map_free(map);
2948 map = isl_map_cow(map);
2949 if (!map)
2950 return NULL;
2952 for (i = 0; i < map->n; ++i) {
2953 map->p[i] = drop(map->p[i], type, first, n);
2954 if (!map->p[i])
2955 return isl_map_free(map);
2958 if (map->n > 1)
2959 ISL_F_CLR(map, ISL_MAP_DISJOINT);
2961 return map;
2964 /* Drop all constraints in map that involve any of the dimensions
2965 * first to first + n - 1 of the given type.
2967 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
2968 __isl_take isl_map *map,
2969 enum isl_dim_type type, unsigned first, unsigned n)
2971 if (n == 0)
2972 return map;
2973 return drop_constraints(map, type, first, n,
2974 &isl_basic_map_drop_constraints_involving_dims);
2977 /* Drop all constraints in "map" that do not involve any of the dimensions
2978 * first to first + n - 1 of the given type.
2980 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
2981 __isl_take isl_map *map,
2982 enum isl_dim_type type, unsigned first, unsigned n)
2984 if (n == 0) {
2985 isl_space *space = isl_map_get_space(map);
2986 isl_map_free(map);
2987 return isl_map_universe(space);
2989 return drop_constraints(map, type, first, n,
2990 &isl_basic_map_drop_constraints_not_involving_dims);
2993 /* Drop all constraints in set that involve any of the dimensions
2994 * first to first + n - 1 of the given type.
2996 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
2997 __isl_take isl_set *set,
2998 enum isl_dim_type type, unsigned first, unsigned n)
3000 return isl_map_drop_constraints_involving_dims(set, type, first, n);
3003 /* Drop all constraints in "set" that do not involve any of the dimensions
3004 * first to first + n - 1 of the given type.
3006 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3007 __isl_take isl_set *set,
3008 enum isl_dim_type type, unsigned first, unsigned n)
3010 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3013 /* Does local variable "div" of "bmap" have a complete explicit representation?
3014 * Having a complete explicit representation requires not only
3015 * an explicit representation, but also that all local variables
3016 * that appear in this explicit representation in turn have
3017 * a complete explicit representation.
3019 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3021 int i;
3022 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3023 isl_bool marked;
3025 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3026 if (marked < 0 || marked)
3027 return isl_bool_not(marked);
3029 for (i = bmap->n_div - 1; i >= 0; --i) {
3030 isl_bool known;
3032 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3033 continue;
3034 known = isl_basic_map_div_is_known(bmap, i);
3035 if (known < 0 || !known)
3036 return known;
3039 return isl_bool_true;
3042 /* Remove all divs that are unknown or defined in terms of unknown divs.
3044 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3045 __isl_take isl_basic_map *bmap)
3047 int i;
3049 if (!bmap)
3050 return NULL;
3052 for (i = bmap->n_div - 1; i >= 0; --i) {
3053 if (isl_basic_map_div_is_known(bmap, i))
3054 continue;
3055 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3056 if (!bmap)
3057 return NULL;
3058 i = bmap->n_div;
3061 return bmap;
3064 /* Remove all divs that are unknown or defined in terms of unknown divs.
3066 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3067 __isl_take isl_basic_set *bset)
3069 return isl_basic_map_remove_unknown_divs(bset);
3072 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3074 int i;
3076 if (!map)
3077 return NULL;
3078 if (map->n == 0)
3079 return map;
3081 map = isl_map_cow(map);
3082 if (!map)
3083 return NULL;
3085 for (i = 0; i < map->n; ++i) {
3086 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3087 if (!map->p[i])
3088 goto error;
3090 return map;
3091 error:
3092 isl_map_free(map);
3093 return NULL;
3096 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3098 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3101 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3102 __isl_take isl_basic_set *bset,
3103 enum isl_dim_type type, unsigned first, unsigned n)
3105 isl_basic_map *bmap = bset_to_bmap(bset);
3106 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3107 return bset_from_bmap(bmap);
3110 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3111 enum isl_dim_type type, unsigned first, unsigned n)
3113 int i;
3115 if (n == 0)
3116 return map;
3118 map = isl_map_cow(map);
3119 if (isl_map_check_range(map, type, first, n) < 0)
3120 return isl_map_free(map);
3122 for (i = 0; i < map->n; ++i) {
3123 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3124 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3125 if (!map->p[i])
3126 goto error;
3128 map = isl_map_drop(map, type, first, n);
3129 return map;
3130 error:
3131 isl_map_free(map);
3132 return NULL;
3135 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3136 enum isl_dim_type type, unsigned first, unsigned n)
3138 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3139 type, first, n));
3142 /* Project out n inputs starting at first using Fourier-Motzkin */
3143 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
3144 unsigned first, unsigned n)
3146 return isl_map_remove_dims(map, isl_dim_in, first, n);
3149 static void dump_term(struct isl_basic_map *bmap,
3150 isl_int c, int pos, FILE *out)
3152 const char *name;
3153 unsigned in = isl_basic_map_dim(bmap, isl_dim_in);
3154 unsigned dim = in + isl_basic_map_dim(bmap, isl_dim_out);
3155 unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
3156 if (!pos)
3157 isl_int_print(out, c, 0);
3158 else {
3159 if (!isl_int_is_one(c))
3160 isl_int_print(out, c, 0);
3161 if (pos < 1 + nparam) {
3162 name = isl_space_get_dim_name(bmap->dim,
3163 isl_dim_param, pos - 1);
3164 if (name)
3165 fprintf(out, "%s", name);
3166 else
3167 fprintf(out, "p%d", pos - 1);
3168 } else if (pos < 1 + nparam + in)
3169 fprintf(out, "i%d", pos - 1 - nparam);
3170 else if (pos < 1 + nparam + dim)
3171 fprintf(out, "o%d", pos - 1 - nparam - in);
3172 else
3173 fprintf(out, "e%d", pos - 1 - nparam - dim);
3177 static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
3178 int sign, FILE *out)
3180 int i;
3181 int first;
3182 unsigned len = 1 + isl_basic_map_total_dim(bmap);
3183 isl_int v;
3185 isl_int_init(v);
3186 for (i = 0, first = 1; i < len; ++i) {
3187 if (isl_int_sgn(c[i]) * sign <= 0)
3188 continue;
3189 if (!first)
3190 fprintf(out, " + ");
3191 first = 0;
3192 isl_int_abs(v, c[i]);
3193 dump_term(bmap, v, i, out);
3195 isl_int_clear(v);
3196 if (first)
3197 fprintf(out, "0");
3200 static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
3201 const char *op, FILE *out, int indent)
3203 int i;
3205 fprintf(out, "%*s", indent, "");
3207 dump_constraint_sign(bmap, c, 1, out);
3208 fprintf(out, " %s ", op);
3209 dump_constraint_sign(bmap, c, -1, out);
3211 fprintf(out, "\n");
3213 for (i = bmap->n_div; i < bmap->extra; ++i) {
3214 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
3215 continue;
3216 fprintf(out, "%*s", indent, "");
3217 fprintf(out, "ERROR: unused div coefficient not zero\n");
3218 abort();
3222 static void dump_constraints(struct isl_basic_map *bmap,
3223 isl_int **c, unsigned n,
3224 const char *op, FILE *out, int indent)
3226 int i;
3228 for (i = 0; i < n; ++i)
3229 dump_constraint(bmap, c[i], op, out, indent);
3232 static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
3234 int j;
3235 int first = 1;
3236 unsigned total = isl_basic_map_total_dim(bmap);
3238 for (j = 0; j < 1 + total; ++j) {
3239 if (isl_int_is_zero(exp[j]))
3240 continue;
3241 if (!first && isl_int_is_pos(exp[j]))
3242 fprintf(out, "+");
3243 dump_term(bmap, exp[j], j, out);
3244 first = 0;
3248 static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
3250 int i;
3252 dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
3253 dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
3255 for (i = 0; i < bmap->n_div; ++i) {
3256 fprintf(out, "%*s", indent, "");
3257 fprintf(out, "e%d = [(", i);
3258 dump_affine(bmap, bmap->div[i]+1, out);
3259 fprintf(out, ")/");
3260 isl_int_print(out, bmap->div[i][0], 0);
3261 fprintf(out, "]\n");
3265 void isl_basic_set_print_internal(struct isl_basic_set *bset,
3266 FILE *out, int indent)
3268 if (!bset) {
3269 fprintf(out, "null basic set\n");
3270 return;
3273 fprintf(out, "%*s", indent, "");
3274 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3275 bset->ref, bset->dim->nparam, bset->dim->n_out,
3276 bset->extra, bset->flags);
3277 dump(bset_to_bmap(bset), out, indent);
3280 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
3281 FILE *out, int indent)
3283 if (!bmap) {
3284 fprintf(out, "null basic map\n");
3285 return;
3288 fprintf(out, "%*s", indent, "");
3289 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3290 "flags: %x, n_name: %d\n",
3291 bmap->ref,
3292 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3293 bmap->extra, bmap->flags, bmap->dim->n_id);
3294 dump(bmap, out, indent);
3297 int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
3299 unsigned total;
3300 if (!bmap)
3301 return -1;
3302 total = isl_basic_map_total_dim(bmap);
3303 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
3304 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3305 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3306 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3307 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3308 return 0;
3311 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3312 unsigned flags)
3314 if (isl_space_check_is_set(space) < 0)
3315 goto error;
3316 return isl_map_alloc_space(space, n, flags);
3317 error:
3318 isl_space_free(space);
3319 return NULL;
3322 /* Make sure "map" has room for at least "n" more basic maps.
3324 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3326 int i;
3327 struct isl_map *grown = NULL;
3329 if (!map)
3330 return NULL;
3331 isl_assert(map->ctx, n >= 0, goto error);
3332 if (map->n + n <= map->size)
3333 return map;
3334 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3335 if (!grown)
3336 goto error;
3337 for (i = 0; i < map->n; ++i) {
3338 grown->p[i] = isl_basic_map_copy(map->p[i]);
3339 if (!grown->p[i])
3340 goto error;
3341 grown->n++;
3343 isl_map_free(map);
3344 return grown;
3345 error:
3346 isl_map_free(grown);
3347 isl_map_free(map);
3348 return NULL;
3351 /* Make sure "set" has room for at least "n" more basic sets.
3353 struct isl_set *isl_set_grow(struct isl_set *set, int n)
3355 return set_from_map(isl_map_grow(set_to_map(set), n));
3358 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3360 return isl_map_from_basic_map(bset);
3363 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3365 struct isl_map *map;
3367 if (!bmap)
3368 return NULL;
3370 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3371 return isl_map_add_basic_map(map, bmap);
3374 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3375 __isl_take isl_basic_set *bset)
3377 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3378 bset_to_bmap(bset)));
3381 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3383 return isl_map_free(set);
3386 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3388 int i;
3390 if (!set) {
3391 fprintf(out, "null set\n");
3392 return;
3395 fprintf(out, "%*s", indent, "");
3396 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3397 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3398 set->flags);
3399 for (i = 0; i < set->n; ++i) {
3400 fprintf(out, "%*s", indent, "");
3401 fprintf(out, "basic set %d:\n", i);
3402 isl_basic_set_print_internal(set->p[i], out, indent+4);
3406 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3408 int i;
3410 if (!map) {
3411 fprintf(out, "null map\n");
3412 return;
3415 fprintf(out, "%*s", indent, "");
3416 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3417 "flags: %x, n_name: %d\n",
3418 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3419 map->dim->n_out, map->flags, map->dim->n_id);
3420 for (i = 0; i < map->n; ++i) {
3421 fprintf(out, "%*s", indent, "");
3422 fprintf(out, "basic map %d:\n", i);
3423 isl_basic_map_print_internal(map->p[i], out, indent+4);
3427 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3428 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3430 struct isl_basic_map *bmap_domain;
3432 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3433 goto error;
3435 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
3436 isl_assert(bset->ctx,
3437 isl_basic_map_compatible_domain(bmap, bset), goto error);
3439 bmap = isl_basic_map_cow(bmap);
3440 if (!bmap)
3441 goto error;
3442 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3443 bset->n_div, bset->n_eq, bset->n_ineq);
3444 bmap_domain = isl_basic_map_from_domain(bset);
3445 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3447 bmap = isl_basic_map_simplify(bmap);
3448 return isl_basic_map_finalize(bmap);
3449 error:
3450 isl_basic_map_free(bmap);
3451 isl_basic_set_free(bset);
3452 return NULL;
3455 /* Check that the space of "bset" is the same as that of the range of "bmap".
3457 static isl_stat isl_basic_map_check_compatible_range(
3458 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3460 isl_bool ok;
3462 ok = isl_basic_map_compatible_range(bmap, bset);
3463 if (ok < 0)
3464 return isl_stat_error;
3465 if (!ok)
3466 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3467 "incompatible spaces", return isl_stat_error);
3469 return isl_stat_ok;
3472 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3473 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3475 struct isl_basic_map *bmap_range;
3477 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3478 goto error;
3480 if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
3481 isl_basic_map_check_compatible_range(bmap, bset) < 0)
3482 goto error;
3484 if (isl_basic_set_plain_is_universe(bset)) {
3485 isl_basic_set_free(bset);
3486 return bmap;
3489 bmap = isl_basic_map_cow(bmap);
3490 if (!bmap)
3491 goto error;
3492 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3493 bset->n_div, bset->n_eq, bset->n_ineq);
3494 bmap_range = bset_to_bmap(bset);
3495 bmap = add_constraints(bmap, bmap_range, 0, 0);
3497 bmap = isl_basic_map_simplify(bmap);
3498 return isl_basic_map_finalize(bmap);
3499 error:
3500 isl_basic_map_free(bmap);
3501 isl_basic_set_free(bset);
3502 return NULL;
3505 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3506 __isl_keep isl_vec *vec)
3508 int i;
3509 unsigned total;
3510 isl_int s;
3512 if (!bmap || !vec)
3513 return isl_bool_error;
3515 total = 1 + isl_basic_map_total_dim(bmap);
3516 if (total != vec->size)
3517 return isl_bool_false;
3519 isl_int_init(s);
3521 for (i = 0; i < bmap->n_eq; ++i) {
3522 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3523 if (!isl_int_is_zero(s)) {
3524 isl_int_clear(s);
3525 return isl_bool_false;
3529 for (i = 0; i < bmap->n_ineq; ++i) {
3530 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3531 if (isl_int_is_neg(s)) {
3532 isl_int_clear(s);
3533 return isl_bool_false;
3537 isl_int_clear(s);
3539 return isl_bool_true;
3542 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3543 __isl_keep isl_vec *vec)
3545 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3548 __isl_give isl_basic_map *isl_basic_map_intersect(
3549 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3551 struct isl_vec *sample = NULL;
3553 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3554 goto error;
3555 if (isl_space_dim(bmap1->dim, isl_dim_all) ==
3556 isl_space_dim(bmap1->dim, isl_dim_param) &&
3557 isl_space_dim(bmap2->dim, isl_dim_all) !=
3558 isl_space_dim(bmap2->dim, isl_dim_param))
3559 return isl_basic_map_intersect(bmap2, bmap1);
3561 if (isl_space_dim(bmap2->dim, isl_dim_all) !=
3562 isl_space_dim(bmap2->dim, isl_dim_param))
3563 isl_assert(bmap1->ctx,
3564 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3566 if (isl_basic_map_plain_is_empty(bmap1)) {
3567 isl_basic_map_free(bmap2);
3568 return bmap1;
3570 if (isl_basic_map_plain_is_empty(bmap2)) {
3571 isl_basic_map_free(bmap1);
3572 return bmap2;
3575 if (bmap1->sample &&
3576 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3577 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3578 sample = isl_vec_copy(bmap1->sample);
3579 else if (bmap2->sample &&
3580 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3581 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3582 sample = isl_vec_copy(bmap2->sample);
3584 bmap1 = isl_basic_map_cow(bmap1);
3585 if (!bmap1)
3586 goto error;
3587 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3588 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3589 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3591 if (!bmap1)
3592 isl_vec_free(sample);
3593 else if (sample) {
3594 isl_vec_free(bmap1->sample);
3595 bmap1->sample = sample;
3598 bmap1 = isl_basic_map_simplify(bmap1);
3599 return isl_basic_map_finalize(bmap1);
3600 error:
3601 if (sample)
3602 isl_vec_free(sample);
3603 isl_basic_map_free(bmap1);
3604 isl_basic_map_free(bmap2);
3605 return NULL;
3608 struct isl_basic_set *isl_basic_set_intersect(
3609 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3611 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3612 bset_to_bmap(bset2)));
3615 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3616 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3618 return isl_basic_set_intersect(bset1, bset2);
3621 /* Special case of isl_map_intersect, where both map1 and map2
3622 * are convex, without any divs and such that either map1 or map2
3623 * contains a single constraint. This constraint is then simply
3624 * added to the other map.
3626 static __isl_give isl_map *map_intersect_add_constraint(
3627 __isl_take isl_map *map1, __isl_take isl_map *map2)
3629 isl_assert(map1->ctx, map1->n == 1, goto error);
3630 isl_assert(map2->ctx, map1->n == 1, goto error);
3631 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3632 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3634 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3635 return isl_map_intersect(map2, map1);
3637 map1 = isl_map_cow(map1);
3638 if (!map1)
3639 goto error;
3640 if (isl_map_plain_is_empty(map1)) {
3641 isl_map_free(map2);
3642 return map1;
3644 if (map2->p[0]->n_eq == 1)
3645 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3646 else
3647 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3648 map2->p[0]->ineq[0]);
3650 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3651 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3652 if (!map1->p[0])
3653 goto error;
3655 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3656 isl_basic_map_free(map1->p[0]);
3657 map1->n = 0;
3660 isl_map_free(map2);
3662 map1 = isl_map_unmark_normalized(map1);
3663 return map1;
3664 error:
3665 isl_map_free(map1);
3666 isl_map_free(map2);
3667 return NULL;
3670 /* map2 may be either a parameter domain or a map living in the same
3671 * space as map1.
3673 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3674 __isl_take isl_map *map2)
3676 unsigned flags = 0;
3677 isl_bool equal;
3678 isl_map *result;
3679 int i, j;
3681 if (!map1 || !map2)
3682 goto error;
3684 if ((isl_map_plain_is_empty(map1) ||
3685 isl_map_plain_is_universe(map2)) &&
3686 isl_space_is_equal(map1->dim, map2->dim)) {
3687 isl_map_free(map2);
3688 return map1;
3690 if ((isl_map_plain_is_empty(map2) ||
3691 isl_map_plain_is_universe(map1)) &&
3692 isl_space_is_equal(map1->dim, map2->dim)) {
3693 isl_map_free(map1);
3694 return map2;
3697 if (map1->n == 1 && map2->n == 1 &&
3698 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3699 isl_space_is_equal(map1->dim, map2->dim) &&
3700 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3701 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3702 return map_intersect_add_constraint(map1, map2);
3704 equal = isl_map_plain_is_equal(map1, map2);
3705 if (equal < 0)
3706 goto error;
3707 if (equal) {
3708 isl_map_free(map2);
3709 return map1;
3712 if (isl_space_dim(map2->dim, isl_dim_all) !=
3713 isl_space_dim(map2->dim, isl_dim_param))
3714 isl_assert(map1->ctx,
3715 isl_space_is_equal(map1->dim, map2->dim), goto error);
3717 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3718 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3719 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3721 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3722 map1->n * map2->n, flags);
3723 if (!result)
3724 goto error;
3725 for (i = 0; i < map1->n; ++i)
3726 for (j = 0; j < map2->n; ++j) {
3727 struct isl_basic_map *part;
3728 part = isl_basic_map_intersect(
3729 isl_basic_map_copy(map1->p[i]),
3730 isl_basic_map_copy(map2->p[j]));
3731 if (isl_basic_map_is_empty(part) < 0)
3732 part = isl_basic_map_free(part);
3733 result = isl_map_add_basic_map(result, part);
3734 if (!result)
3735 goto error;
3737 isl_map_free(map1);
3738 isl_map_free(map2);
3739 return result;
3740 error:
3741 isl_map_free(map1);
3742 isl_map_free(map2);
3743 return NULL;
3746 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3747 __isl_take isl_map *map2)
3749 if (!map1 || !map2)
3750 goto error;
3751 if (!isl_space_is_equal(map1->dim, map2->dim))
3752 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3753 "spaces don't match", goto error);
3754 return map_intersect_internal(map1, map2);
3755 error:
3756 isl_map_free(map1);
3757 isl_map_free(map2);
3758 return NULL;
3761 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3762 __isl_take isl_map *map2)
3764 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3767 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3769 return set_from_map(isl_map_intersect(set_to_map(set1),
3770 set_to_map(set2)));
3773 /* map_intersect_internal accepts intersections
3774 * with parameter domains, so we can just call that function.
3776 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3777 __isl_take isl_set *params)
3779 return map_intersect_internal(map, params);
3782 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3783 __isl_take isl_map *map2)
3785 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3788 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3789 __isl_take isl_set *params)
3791 return isl_map_intersect_params(set, params);
3794 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3796 isl_space *space;
3797 unsigned pos, n1, n2;
3799 if (!bmap)
3800 return NULL;
3801 bmap = isl_basic_map_cow(bmap);
3802 if (!bmap)
3803 return NULL;
3804 space = isl_space_reverse(isl_space_copy(bmap->dim));
3805 pos = isl_basic_map_offset(bmap, isl_dim_in);
3806 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3807 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3808 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3809 return isl_basic_map_reset_space(bmap, space);
3812 static __isl_give isl_basic_map *basic_map_space_reset(
3813 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3815 isl_space *space;
3817 if (!bmap)
3818 return NULL;
3819 if (!isl_space_is_named_or_nested(bmap->dim, type))
3820 return bmap;
3822 space = isl_basic_map_get_space(bmap);
3823 space = isl_space_reset(space, type);
3824 bmap = isl_basic_map_reset_space(bmap, space);
3825 return bmap;
3828 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3829 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3830 unsigned pos, unsigned n)
3832 isl_bool rational;
3833 isl_space *res_space;
3834 struct isl_basic_map *res;
3835 struct isl_dim_map *dim_map;
3836 unsigned total, off;
3837 enum isl_dim_type t;
3839 if (n == 0)
3840 return basic_map_space_reset(bmap, type);
3842 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3843 type, pos, n);
3844 if (!res_space)
3845 return isl_basic_map_free(bmap);
3847 total = isl_basic_map_total_dim(bmap) + n;
3848 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3849 off = 0;
3850 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3851 if (t != type) {
3852 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3853 } else {
3854 unsigned size = isl_basic_map_dim(bmap, t);
3855 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3856 0, pos, off);
3857 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3858 pos, size - pos, off + pos + n);
3860 off += isl_space_dim(res_space, t);
3862 isl_dim_map_div(dim_map, bmap, off);
3864 res = isl_basic_map_alloc_space(res_space,
3865 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3866 rational = isl_basic_map_is_rational(bmap);
3867 if (rational < 0)
3868 res = isl_basic_map_free(res);
3869 if (rational)
3870 res = isl_basic_map_set_rational(res);
3871 if (isl_basic_map_plain_is_empty(bmap)) {
3872 isl_basic_map_free(bmap);
3873 free(dim_map);
3874 return isl_basic_map_set_to_empty(res);
3876 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3877 return isl_basic_map_finalize(res);
3880 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3881 __isl_take isl_basic_set *bset,
3882 enum isl_dim_type type, unsigned pos, unsigned n)
3884 return isl_basic_map_insert_dims(bset, type, pos, n);
3887 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3888 enum isl_dim_type type, unsigned n)
3890 if (!bmap)
3891 return NULL;
3892 return isl_basic_map_insert_dims(bmap, type,
3893 isl_basic_map_dim(bmap, type), n);
3896 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3897 enum isl_dim_type type, unsigned n)
3899 if (!bset)
3900 return NULL;
3901 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3902 return isl_basic_map_add_dims(bset, type, n);
3903 error:
3904 isl_basic_set_free(bset);
3905 return NULL;
3908 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3909 enum isl_dim_type type)
3911 isl_space *space;
3913 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3914 return map;
3916 space = isl_map_get_space(map);
3917 space = isl_space_reset(space, type);
3918 map = isl_map_reset_space(map, space);
3919 return map;
3922 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3923 enum isl_dim_type type, unsigned pos, unsigned n)
3925 int i;
3927 if (n == 0)
3928 return map_space_reset(map, type);
3930 map = isl_map_cow(map);
3931 if (!map)
3932 return NULL;
3934 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3935 if (!map->dim)
3936 goto error;
3938 for (i = 0; i < map->n; ++i) {
3939 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3940 if (!map->p[i])
3941 goto error;
3944 return map;
3945 error:
3946 isl_map_free(map);
3947 return NULL;
3950 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3951 enum isl_dim_type type, unsigned pos, unsigned n)
3953 return isl_map_insert_dims(set, type, pos, n);
3956 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3957 enum isl_dim_type type, unsigned n)
3959 if (!map)
3960 return NULL;
3961 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3964 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3965 enum isl_dim_type type, unsigned n)
3967 if (!set)
3968 return NULL;
3969 isl_assert(set->ctx, type != isl_dim_in, goto error);
3970 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
3971 error:
3972 isl_set_free(set);
3973 return NULL;
3976 __isl_give isl_basic_map *isl_basic_map_move_dims(
3977 __isl_take isl_basic_map *bmap,
3978 enum isl_dim_type dst_type, unsigned dst_pos,
3979 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3981 struct isl_dim_map *dim_map;
3982 struct isl_basic_map *res;
3983 enum isl_dim_type t;
3984 unsigned total, off;
3986 if (!bmap)
3987 return NULL;
3988 if (n == 0) {
3989 bmap = isl_basic_map_reset(bmap, src_type);
3990 bmap = isl_basic_map_reset(bmap, dst_type);
3991 return bmap;
3994 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
3995 return isl_basic_map_free(bmap);
3997 if (dst_type == src_type && dst_pos == src_pos)
3998 return bmap;
4000 isl_assert(bmap->ctx, dst_type != src_type, goto error);
4002 if (pos(bmap->dim, dst_type) + dst_pos ==
4003 pos(bmap->dim, src_type) + src_pos +
4004 ((src_type < dst_type) ? n : 0)) {
4005 bmap = isl_basic_map_cow(bmap);
4006 if (!bmap)
4007 return NULL;
4009 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4010 src_type, src_pos, n);
4011 if (!bmap->dim)
4012 goto error;
4014 bmap = isl_basic_map_finalize(bmap);
4016 return bmap;
4019 total = isl_basic_map_total_dim(bmap);
4020 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4022 off = 0;
4023 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4024 unsigned size = isl_space_dim(bmap->dim, t);
4025 if (t == dst_type) {
4026 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4027 0, dst_pos, off);
4028 off += dst_pos;
4029 isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
4030 src_pos, n, off);
4031 off += n;
4032 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4033 dst_pos, size - dst_pos, off);
4034 off += size - dst_pos;
4035 } else if (t == src_type) {
4036 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4037 0, src_pos, off);
4038 off += src_pos;
4039 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4040 src_pos + n, size - src_pos - n, off);
4041 off += size - src_pos - n;
4042 } else {
4043 isl_dim_map_dim(dim_map, bmap->dim, t, off);
4044 off += size;
4047 isl_dim_map_div(dim_map, bmap, off);
4049 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4050 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4051 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4052 if (!bmap)
4053 goto error;
4055 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4056 src_type, src_pos, n);
4057 if (!bmap->dim)
4058 goto error;
4060 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4061 bmap = isl_basic_map_gauss(bmap, NULL);
4062 bmap = isl_basic_map_finalize(bmap);
4064 return bmap;
4065 error:
4066 isl_basic_map_free(bmap);
4067 return NULL;
4070 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4071 enum isl_dim_type dst_type, unsigned dst_pos,
4072 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4074 isl_basic_map *bmap = bset_to_bmap(bset);
4075 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4076 src_type, src_pos, n);
4077 return bset_from_bmap(bmap);
4080 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4081 enum isl_dim_type dst_type, unsigned dst_pos,
4082 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4084 if (!set)
4085 return NULL;
4086 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4087 return set_from_map(isl_map_move_dims(set_to_map(set),
4088 dst_type, dst_pos, src_type, src_pos, n));
4089 error:
4090 isl_set_free(set);
4091 return NULL;
4094 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4095 enum isl_dim_type dst_type, unsigned dst_pos,
4096 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4098 int i;
4100 if (n == 0) {
4101 map = isl_map_reset(map, src_type);
4102 map = isl_map_reset(map, dst_type);
4103 return map;
4106 if (isl_map_check_range(map, src_type, src_pos, n))
4107 return isl_map_free(map);
4109 if (dst_type == src_type && dst_pos == src_pos)
4110 return map;
4112 isl_assert(map->ctx, dst_type != src_type, goto error);
4114 map = isl_map_cow(map);
4115 if (!map)
4116 return NULL;
4118 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
4119 if (!map->dim)
4120 goto error;
4122 for (i = 0; i < map->n; ++i) {
4123 map->p[i] = isl_basic_map_move_dims(map->p[i],
4124 dst_type, dst_pos,
4125 src_type, src_pos, n);
4126 if (!map->p[i])
4127 goto error;
4130 return map;
4131 error:
4132 isl_map_free(map);
4133 return NULL;
4136 /* Move the specified dimensions to the last columns right before
4137 * the divs. Don't change the dimension specification of bmap.
4138 * That's the responsibility of the caller.
4140 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4141 enum isl_dim_type type, unsigned first, unsigned n)
4143 struct isl_dim_map *dim_map;
4144 struct isl_basic_map *res;
4145 enum isl_dim_type t;
4146 unsigned total, off;
4148 if (!bmap)
4149 return NULL;
4150 if (pos(bmap->dim, type) + first + n ==
4151 1 + isl_space_dim(bmap->dim, isl_dim_all))
4152 return bmap;
4154 total = isl_basic_map_total_dim(bmap);
4155 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4157 off = 0;
4158 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4159 unsigned size = isl_space_dim(bmap->dim, t);
4160 if (t == type) {
4161 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4162 0, first, off);
4163 off += first;
4164 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4165 first, n, total - bmap->n_div - n);
4166 isl_dim_map_dim_range(dim_map, bmap->dim, t,
4167 first + n, size - (first + n), off);
4168 off += size - (first + n);
4169 } else {
4170 isl_dim_map_dim(dim_map, bmap->dim, t, off);
4171 off += size;
4174 isl_dim_map_div(dim_map, bmap, off + n);
4176 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4177 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4178 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4179 return res;
4182 /* Insert "n" rows in the divs of "bmap".
4184 * The number of columns is not changed, which means that the last
4185 * dimensions of "bmap" are being reintepreted as the new divs.
4186 * The space of "bmap" is not adjusted, however, which means
4187 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4188 * from the space of "bmap" is the responsibility of the caller.
4190 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4191 int n)
4193 int i;
4194 size_t row_size;
4195 isl_int **new_div;
4196 isl_int *old;
4198 bmap = isl_basic_map_cow(bmap);
4199 if (!bmap)
4200 return NULL;
4202 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
4203 old = bmap->block2.data;
4204 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4205 (bmap->extra + n) * (1 + row_size));
4206 if (!bmap->block2.data)
4207 return isl_basic_map_free(bmap);
4208 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4209 if (!new_div)
4210 return isl_basic_map_free(bmap);
4211 for (i = 0; i < n; ++i) {
4212 new_div[i] = bmap->block2.data +
4213 (bmap->extra + i) * (1 + row_size);
4214 isl_seq_clr(new_div[i], 1 + row_size);
4216 for (i = 0; i < bmap->extra; ++i)
4217 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4218 free(bmap->div);
4219 bmap->div = new_div;
4220 bmap->n_div += n;
4221 bmap->extra += n;
4223 return bmap;
4226 /* Drop constraints from "bmap" that only involve the variables
4227 * of "type" in the range [first, first + n] that are not related
4228 * to any of the variables outside that interval.
4229 * These constraints cannot influence the values for the variables
4230 * outside the interval, except in case they cause "bmap" to be empty.
4231 * Only drop the constraints if "bmap" is known to be non-empty.
4233 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4234 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4235 unsigned first, unsigned n)
4237 int i;
4238 int *groups;
4239 unsigned dim, n_div;
4240 isl_bool non_empty;
4242 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4243 if (non_empty < 0)
4244 return isl_basic_map_free(bmap);
4245 if (!non_empty)
4246 return bmap;
4248 dim = isl_basic_map_dim(bmap, isl_dim_all);
4249 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4250 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4251 if (!groups)
4252 return isl_basic_map_free(bmap);
4253 first += isl_basic_map_offset(bmap, type) - 1;
4254 for (i = 0; i < first; ++i)
4255 groups[i] = -1;
4256 for (i = first + n; i < dim - n_div; ++i)
4257 groups[i] = -1;
4259 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4261 return bmap;
4264 /* Turn the n dimensions of type type, starting at first
4265 * into existentially quantified variables.
4267 * If a subset of the projected out variables are unrelated
4268 * to any of the variables that remain, then the constraints
4269 * involving this subset are simply dropped first.
4271 __isl_give isl_basic_map *isl_basic_map_project_out(
4272 __isl_take isl_basic_map *bmap,
4273 enum isl_dim_type type, unsigned first, unsigned n)
4275 isl_bool empty;
4277 if (n == 0)
4278 return basic_map_space_reset(bmap, type);
4279 if (type == isl_dim_div)
4280 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4281 "cannot project out existentially quantified variables",
4282 return isl_basic_map_free(bmap));
4284 empty = isl_basic_map_plain_is_empty(bmap);
4285 if (empty < 0)
4286 return isl_basic_map_free(bmap);
4287 if (empty)
4288 bmap = isl_basic_map_set_to_empty(bmap);
4290 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4291 if (!bmap)
4292 return NULL;
4294 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4295 return isl_basic_map_remove_dims(bmap, type, first, n);
4297 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4298 return isl_basic_map_free(bmap);
4300 bmap = move_last(bmap, type, first, n);
4301 bmap = isl_basic_map_cow(bmap);
4302 bmap = insert_div_rows(bmap, n);
4303 if (!bmap)
4304 return NULL;
4306 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
4307 if (!bmap->dim)
4308 goto error;
4309 bmap = isl_basic_map_simplify(bmap);
4310 bmap = isl_basic_map_drop_redundant_divs(bmap);
4311 return isl_basic_map_finalize(bmap);
4312 error:
4313 isl_basic_map_free(bmap);
4314 return NULL;
4317 /* Turn the n dimensions of type type, starting at first
4318 * into existentially quantified variables.
4320 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
4321 enum isl_dim_type type, unsigned first, unsigned n)
4323 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4324 type, first, n));
4327 /* Turn the n dimensions of type type, starting at first
4328 * into existentially quantified variables.
4330 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4331 enum isl_dim_type type, unsigned first, unsigned n)
4333 int i;
4335 if (n == 0)
4336 return map_space_reset(map, type);
4338 if (isl_map_check_range(map, type, first, n) < 0)
4339 return isl_map_free(map);
4341 map = isl_map_cow(map);
4342 if (!map)
4343 return NULL;
4345 map->dim = isl_space_drop_dims(map->dim, type, first, n);
4346 if (!map->dim)
4347 goto error;
4349 for (i = 0; i < map->n; ++i) {
4350 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4351 if (!map->p[i])
4352 goto error;
4355 return map;
4356 error:
4357 isl_map_free(map);
4358 return NULL;
4361 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4362 * into existentially quantified variables.
4364 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4365 enum isl_dim_type type, unsigned first, unsigned n)
4367 unsigned dim;
4369 if (isl_map_check_range(map, type, first, n) < 0)
4370 return isl_map_free(map);
4371 dim = isl_map_dim(map, type);
4372 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4373 map = isl_map_project_out(map, type, 0, first);
4374 return map;
4377 /* Turn the n dimensions of type type, starting at first
4378 * into existentially quantified variables.
4380 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4381 enum isl_dim_type type, unsigned first, unsigned n)
4383 return set_from_map(isl_map_project_out(set_to_map(set),
4384 type, first, n));
4387 /* Return a map that projects the elements in "set" onto their
4388 * "n" set dimensions starting at "first".
4389 * "type" should be equal to isl_dim_set.
4391 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4392 enum isl_dim_type type, unsigned first, unsigned n)
4394 int i;
4395 int dim;
4396 isl_map *map;
4398 if (!set)
4399 return NULL;
4400 if (type != isl_dim_set)
4401 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4402 "only set dimensions can be projected out", goto error);
4403 dim = isl_set_dim(set, isl_dim_set);
4404 if (first + n > dim || first + n < first)
4405 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4406 "index out of bounds", goto error);
4408 map = isl_map_from_domain(set);
4409 map = isl_map_add_dims(map, isl_dim_out, n);
4410 for (i = 0; i < n; ++i)
4411 map = isl_map_equate(map, isl_dim_in, first + i,
4412 isl_dim_out, i);
4413 return map;
4414 error:
4415 isl_set_free(set);
4416 return NULL;
4419 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4420 unsigned n)
4422 int i, j;
4424 for (i = 0; i < n; ++i) {
4425 j = isl_basic_map_alloc_div(bmap);
4426 if (j < 0)
4427 goto error;
4428 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4430 return bmap;
4431 error:
4432 isl_basic_map_free(bmap);
4433 return NULL;
4436 struct isl_basic_map *isl_basic_map_apply_range(
4437 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4439 isl_space *space_result = NULL;
4440 struct isl_basic_map *bmap;
4441 unsigned n_in, n_out, n, nparam, total, pos;
4442 struct isl_dim_map *dim_map1, *dim_map2;
4444 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4445 goto error;
4446 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4447 bmap2->dim, isl_dim_in))
4448 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4449 "spaces don't match", goto error);
4451 space_result = isl_space_join(isl_space_copy(bmap1->dim),
4452 isl_space_copy(bmap2->dim));
4454 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4455 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4456 n = isl_basic_map_dim(bmap1, isl_dim_out);
4457 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4459 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4460 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4461 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4462 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4463 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4464 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4465 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4466 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4467 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4468 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4469 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4471 bmap = isl_basic_map_alloc_space(space_result,
4472 bmap1->n_div + bmap2->n_div + n,
4473 bmap1->n_eq + bmap2->n_eq,
4474 bmap1->n_ineq + bmap2->n_ineq);
4475 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4476 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4477 bmap = add_divs(bmap, n);
4478 bmap = isl_basic_map_simplify(bmap);
4479 bmap = isl_basic_map_drop_redundant_divs(bmap);
4480 return isl_basic_map_finalize(bmap);
4481 error:
4482 isl_basic_map_free(bmap1);
4483 isl_basic_map_free(bmap2);
4484 return NULL;
4487 struct isl_basic_set *isl_basic_set_apply(
4488 struct isl_basic_set *bset, struct isl_basic_map *bmap)
4490 if (!bset || !bmap)
4491 goto error;
4493 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4494 goto error);
4496 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4497 bmap));
4498 error:
4499 isl_basic_set_free(bset);
4500 isl_basic_map_free(bmap);
4501 return NULL;
4504 struct isl_basic_map *isl_basic_map_apply_domain(
4505 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4507 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4508 goto error;
4509 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4510 bmap2->dim, isl_dim_in))
4511 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4512 "spaces don't match", goto error);
4514 bmap1 = isl_basic_map_reverse(bmap1);
4515 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4516 return isl_basic_map_reverse(bmap1);
4517 error:
4518 isl_basic_map_free(bmap1);
4519 isl_basic_map_free(bmap2);
4520 return NULL;
4523 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4524 * A \cap B -> f(A) + f(B)
4526 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4527 __isl_take isl_basic_map *bmap2)
4529 unsigned n_in, n_out, nparam, total, pos;
4530 struct isl_basic_map *bmap = NULL;
4531 struct isl_dim_map *dim_map1, *dim_map2;
4532 int i;
4534 if (!bmap1 || !bmap2)
4535 goto error;
4537 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4538 goto error);
4540 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4541 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4542 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4544 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4545 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4546 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4547 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4548 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4549 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4550 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4551 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4552 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4553 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4554 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4556 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4557 bmap1->n_div + bmap2->n_div + 2 * n_out,
4558 bmap1->n_eq + bmap2->n_eq + n_out,
4559 bmap1->n_ineq + bmap2->n_ineq);
4560 for (i = 0; i < n_out; ++i) {
4561 int j = isl_basic_map_alloc_equality(bmap);
4562 if (j < 0)
4563 goto error;
4564 isl_seq_clr(bmap->eq[j], 1+total);
4565 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4566 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4567 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4569 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4570 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4571 bmap = add_divs(bmap, 2 * n_out);
4573 bmap = isl_basic_map_simplify(bmap);
4574 return isl_basic_map_finalize(bmap);
4575 error:
4576 isl_basic_map_free(bmap);
4577 isl_basic_map_free(bmap1);
4578 isl_basic_map_free(bmap2);
4579 return NULL;
4582 /* Given two maps A -> f(A) and B -> g(B), construct a map
4583 * A \cap B -> f(A) + f(B)
4585 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4586 __isl_take isl_map *map2)
4588 struct isl_map *result;
4589 int i, j;
4591 if (!map1 || !map2)
4592 goto error;
4594 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4596 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4597 map1->n * map2->n, 0);
4598 if (!result)
4599 goto error;
4600 for (i = 0; i < map1->n; ++i)
4601 for (j = 0; j < map2->n; ++j) {
4602 struct isl_basic_map *part;
4603 part = isl_basic_map_sum(
4604 isl_basic_map_copy(map1->p[i]),
4605 isl_basic_map_copy(map2->p[j]));
4606 if (isl_basic_map_is_empty(part))
4607 isl_basic_map_free(part);
4608 else
4609 result = isl_map_add_basic_map(result, part);
4610 if (!result)
4611 goto error;
4613 isl_map_free(map1);
4614 isl_map_free(map2);
4615 return result;
4616 error:
4617 isl_map_free(map1);
4618 isl_map_free(map2);
4619 return NULL;
4622 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4623 __isl_take isl_set *set2)
4625 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4628 /* Given a basic map A -> f(A), construct A -> -f(A).
4630 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4632 int i, j;
4633 unsigned off, n;
4635 bmap = isl_basic_map_cow(bmap);
4636 if (!bmap)
4637 return NULL;
4639 n = isl_basic_map_dim(bmap, isl_dim_out);
4640 off = isl_basic_map_offset(bmap, isl_dim_out);
4641 for (i = 0; i < bmap->n_eq; ++i)
4642 for (j = 0; j < n; ++j)
4643 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4644 for (i = 0; i < bmap->n_ineq; ++i)
4645 for (j = 0; j < n; ++j)
4646 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4647 for (i = 0; i < bmap->n_div; ++i)
4648 for (j = 0; j < n; ++j)
4649 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4650 bmap = isl_basic_map_gauss(bmap, NULL);
4651 return isl_basic_map_finalize(bmap);
4654 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4656 return isl_basic_map_neg(bset);
4659 /* Given a map A -> f(A), construct A -> -f(A).
4661 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4663 int i;
4665 map = isl_map_cow(map);
4666 if (!map)
4667 return NULL;
4669 for (i = 0; i < map->n; ++i) {
4670 map->p[i] = isl_basic_map_neg(map->p[i]);
4671 if (!map->p[i])
4672 goto error;
4675 return map;
4676 error:
4677 isl_map_free(map);
4678 return NULL;
4681 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4683 return set_from_map(isl_map_neg(set_to_map(set)));
4686 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4687 * A -> floor(f(A)/d).
4689 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4690 isl_int d)
4692 unsigned n_in, n_out, nparam, total, pos;
4693 struct isl_basic_map *result = NULL;
4694 struct isl_dim_map *dim_map;
4695 int i;
4697 if (!bmap)
4698 return NULL;
4700 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4701 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4702 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4704 total = nparam + n_in + n_out + bmap->n_div + n_out;
4705 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4706 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4707 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4708 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4709 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4711 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4712 bmap->n_div + n_out,
4713 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4714 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4715 result = add_divs(result, n_out);
4716 for (i = 0; i < n_out; ++i) {
4717 int j;
4718 j = isl_basic_map_alloc_inequality(result);
4719 if (j < 0)
4720 goto error;
4721 isl_seq_clr(result->ineq[j], 1+total);
4722 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4723 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4724 j = isl_basic_map_alloc_inequality(result);
4725 if (j < 0)
4726 goto error;
4727 isl_seq_clr(result->ineq[j], 1+total);
4728 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4729 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4730 isl_int_sub_ui(result->ineq[j][0], d, 1);
4733 result = isl_basic_map_simplify(result);
4734 return isl_basic_map_finalize(result);
4735 error:
4736 isl_basic_map_free(result);
4737 return NULL;
4740 /* Given a map A -> f(A) and an integer d, construct a map
4741 * A -> floor(f(A)/d).
4743 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4745 int i;
4747 map = isl_map_cow(map);
4748 if (!map)
4749 return NULL;
4751 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4752 for (i = 0; i < map->n; ++i) {
4753 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4754 if (!map->p[i])
4755 goto error;
4757 map = isl_map_unmark_normalized(map);
4759 return map;
4760 error:
4761 isl_map_free(map);
4762 return NULL;
4765 /* Given a map A -> f(A) and an integer d, construct a map
4766 * A -> floor(f(A)/d).
4768 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4769 __isl_take isl_val *d)
4771 if (!map || !d)
4772 goto error;
4773 if (!isl_val_is_int(d))
4774 isl_die(isl_val_get_ctx(d), isl_error_invalid,
4775 "expecting integer denominator", goto error);
4776 map = isl_map_floordiv(map, d->n);
4777 isl_val_free(d);
4778 return map;
4779 error:
4780 isl_map_free(map);
4781 isl_val_free(d);
4782 return NULL;
4785 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
4786 unsigned pos)
4788 int i;
4789 unsigned nparam;
4790 unsigned n_in;
4792 i = isl_basic_map_alloc_equality(bmap);
4793 if (i < 0)
4794 goto error;
4795 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4796 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4797 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4798 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4799 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4800 return isl_basic_map_finalize(bmap);
4801 error:
4802 isl_basic_map_free(bmap);
4803 return NULL;
4806 /* Add a constraint to "bmap" expressing i_pos < o_pos
4808 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
4809 unsigned pos)
4811 int i;
4812 unsigned nparam;
4813 unsigned n_in;
4815 i = isl_basic_map_alloc_inequality(bmap);
4816 if (i < 0)
4817 goto error;
4818 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4819 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4820 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4821 isl_int_set_si(bmap->ineq[i][0], -1);
4822 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4823 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4824 return isl_basic_map_finalize(bmap);
4825 error:
4826 isl_basic_map_free(bmap);
4827 return NULL;
4830 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4832 static __isl_give isl_basic_map *var_less_or_equal(
4833 __isl_take isl_basic_map *bmap, unsigned pos)
4835 int i;
4836 unsigned nparam;
4837 unsigned n_in;
4839 i = isl_basic_map_alloc_inequality(bmap);
4840 if (i < 0)
4841 goto error;
4842 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4843 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4844 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4845 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4846 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4847 return isl_basic_map_finalize(bmap);
4848 error:
4849 isl_basic_map_free(bmap);
4850 return NULL;
4853 /* Add a constraint to "bmap" expressing i_pos > o_pos
4855 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
4856 unsigned pos)
4858 int i;
4859 unsigned nparam;
4860 unsigned n_in;
4862 i = isl_basic_map_alloc_inequality(bmap);
4863 if (i < 0)
4864 goto error;
4865 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4866 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4867 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4868 isl_int_set_si(bmap->ineq[i][0], -1);
4869 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4870 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4871 return isl_basic_map_finalize(bmap);
4872 error:
4873 isl_basic_map_free(bmap);
4874 return NULL;
4877 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4879 static __isl_give isl_basic_map *var_more_or_equal(
4880 __isl_take isl_basic_map *bmap, unsigned pos)
4882 int i;
4883 unsigned nparam;
4884 unsigned n_in;
4886 i = isl_basic_map_alloc_inequality(bmap);
4887 if (i < 0)
4888 goto error;
4889 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4890 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4891 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4892 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4893 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4894 return isl_basic_map_finalize(bmap);
4895 error:
4896 isl_basic_map_free(bmap);
4897 return NULL;
4900 __isl_give isl_basic_map *isl_basic_map_equal(
4901 __isl_take isl_space *space, unsigned n_equal)
4903 int i;
4904 struct isl_basic_map *bmap;
4905 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
4906 if (!bmap)
4907 return NULL;
4908 for (i = 0; i < n_equal && bmap; ++i)
4909 bmap = var_equal(bmap, i);
4910 return isl_basic_map_finalize(bmap);
4913 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
4915 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
4916 unsigned pos)
4918 int i;
4919 struct isl_basic_map *bmap;
4920 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4921 if (!bmap)
4922 return NULL;
4923 for (i = 0; i < pos && bmap; ++i)
4924 bmap = var_equal(bmap, i);
4925 if (bmap)
4926 bmap = var_less(bmap, pos);
4927 return isl_basic_map_finalize(bmap);
4930 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
4932 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4933 __isl_take isl_space *space, unsigned pos)
4935 int i;
4936 isl_basic_map *bmap;
4938 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4939 for (i = 0; i < pos; ++i)
4940 bmap = var_equal(bmap, i);
4941 bmap = var_less_or_equal(bmap, pos);
4942 return isl_basic_map_finalize(bmap);
4945 /* Return a relation on "space" expressing i_pos > o_pos
4947 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
4948 unsigned pos)
4950 int i;
4951 struct isl_basic_map *bmap;
4952 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4953 if (!bmap)
4954 return NULL;
4955 for (i = 0; i < pos && bmap; ++i)
4956 bmap = var_equal(bmap, i);
4957 if (bmap)
4958 bmap = var_more(bmap, pos);
4959 return isl_basic_map_finalize(bmap);
4962 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
4964 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4965 __isl_take isl_space *space, unsigned pos)
4967 int i;
4968 isl_basic_map *bmap;
4970 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
4971 for (i = 0; i < pos; ++i)
4972 bmap = var_equal(bmap, i);
4973 bmap = var_more_or_equal(bmap, pos);
4974 return isl_basic_map_finalize(bmap);
4977 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
4978 unsigned n, int equal)
4980 struct isl_map *map;
4981 int i;
4983 if (n == 0 && equal)
4984 return isl_map_universe(space);
4986 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
4988 for (i = 0; i + 1 < n; ++i)
4989 map = isl_map_add_basic_map(map,
4990 isl_basic_map_less_at(isl_space_copy(space), i));
4991 if (n > 0) {
4992 if (equal)
4993 map = isl_map_add_basic_map(map,
4994 isl_basic_map_less_or_equal_at(space, n - 1));
4995 else
4996 map = isl_map_add_basic_map(map,
4997 isl_basic_map_less_at(space, n - 1));
4998 } else
4999 isl_space_free(space);
5001 return map;
5004 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
5006 if (!space)
5007 return NULL;
5008 return map_lex_lte_first(space, space->n_out, equal);
5011 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
5013 return map_lex_lte_first(dim, n, 0);
5016 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
5018 return map_lex_lte_first(dim, n, 1);
5021 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
5023 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
5026 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
5028 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
5031 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5032 unsigned n, int equal)
5034 struct isl_map *map;
5035 int i;
5037 if (n == 0 && equal)
5038 return isl_map_universe(space);
5040 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5042 for (i = 0; i + 1 < n; ++i)
5043 map = isl_map_add_basic_map(map,
5044 isl_basic_map_more_at(isl_space_copy(space), i));
5045 if (n > 0) {
5046 if (equal)
5047 map = isl_map_add_basic_map(map,
5048 isl_basic_map_more_or_equal_at(space, n - 1));
5049 else
5050 map = isl_map_add_basic_map(map,
5051 isl_basic_map_more_at(space, n - 1));
5052 } else
5053 isl_space_free(space);
5055 return map;
5058 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5060 if (!space)
5061 return NULL;
5062 return map_lex_gte_first(space, space->n_out, equal);
5065 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
5067 return map_lex_gte_first(dim, n, 0);
5070 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
5072 return map_lex_gte_first(dim, n, 1);
5075 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
5077 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
5080 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
5082 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
5085 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5086 __isl_take isl_set *set2)
5088 isl_map *map;
5089 map = isl_map_lex_le(isl_set_get_space(set1));
5090 map = isl_map_intersect_domain(map, set1);
5091 map = isl_map_intersect_range(map, set2);
5092 return map;
5095 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5096 __isl_take isl_set *set2)
5098 isl_map *map;
5099 map = isl_map_lex_lt(isl_set_get_space(set1));
5100 map = isl_map_intersect_domain(map, set1);
5101 map = isl_map_intersect_range(map, set2);
5102 return map;
5105 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5106 __isl_take isl_set *set2)
5108 isl_map *map;
5109 map = isl_map_lex_ge(isl_set_get_space(set1));
5110 map = isl_map_intersect_domain(map, set1);
5111 map = isl_map_intersect_range(map, set2);
5112 return map;
5115 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5116 __isl_take isl_set *set2)
5118 isl_map *map;
5119 map = isl_map_lex_gt(isl_set_get_space(set1));
5120 map = isl_map_intersect_domain(map, set1);
5121 map = isl_map_intersect_range(map, set2);
5122 return map;
5125 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5126 __isl_take isl_map *map2)
5128 isl_map *map;
5129 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5130 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5131 map = isl_map_apply_range(map, isl_map_reverse(map2));
5132 return map;
5135 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5136 __isl_take isl_map *map2)
5138 isl_map *map;
5139 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5140 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5141 map = isl_map_apply_range(map, isl_map_reverse(map2));
5142 return map;
5145 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5146 __isl_take isl_map *map2)
5148 isl_map *map;
5149 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5150 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5151 map = isl_map_apply_range(map, isl_map_reverse(map2));
5152 return map;
5155 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5156 __isl_take isl_map *map2)
5158 isl_map *map;
5159 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5160 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5161 map = isl_map_apply_range(map, isl_map_reverse(map2));
5162 return map;
5165 /* For a div d = floor(f/m), add the constraint
5167 * f - m d >= 0
5169 static isl_stat add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
5170 unsigned pos, isl_int *div)
5172 int i;
5173 unsigned total = isl_basic_map_total_dim(bmap);
5175 i = isl_basic_map_alloc_inequality(bmap);
5176 if (i < 0)
5177 return isl_stat_error;
5178 isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
5179 isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
5181 return isl_stat_ok;
5184 /* For a div d = floor(f/m), add the constraint
5186 * -(f-(m-1)) + m d >= 0
5188 static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
5189 unsigned pos, isl_int *div)
5191 int i;
5192 unsigned total = isl_basic_map_total_dim(bmap);
5194 i = isl_basic_map_alloc_inequality(bmap);
5195 if (i < 0)
5196 return isl_stat_error;
5197 isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
5198 isl_int_set(bmap->ineq[i][1 + pos], div[0]);
5199 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5200 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5202 return isl_stat_ok;
5205 /* For a div d = floor(f/m), add the constraints
5207 * f - m d >= 0
5208 * -(f-(m-1)) + m d >= 0
5210 * Note that the second constraint is the negation of
5212 * f - m d >= m
5214 int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
5215 unsigned pos, isl_int *div)
5217 if (add_upper_div_constraint(bmap, pos, div) < 0)
5218 return -1;
5219 if (add_lower_div_constraint(bmap, pos, div) < 0)
5220 return -1;
5221 return 0;
5224 int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
5225 unsigned pos, isl_int *div)
5227 return isl_basic_map_add_div_constraints_var(bset_to_bmap(bset),
5228 pos, div);
5231 int isl_basic_map_add_div_constraints(__isl_keep isl_basic_map *bmap,
5232 unsigned div)
5234 unsigned total = isl_basic_map_total_dim(bmap);
5235 unsigned div_pos = total - bmap->n_div + div;
5237 return isl_basic_map_add_div_constraints_var(bmap, div_pos,
5238 bmap->div[div]);
5241 /* For each known div d = floor(f/m), add the constraints
5243 * f - m d >= 0
5244 * -(f-(m-1)) + m d >= 0
5246 * Remove duplicate constraints in case of some these div constraints
5247 * already appear in "bmap".
5249 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5250 __isl_take isl_basic_map *bmap)
5252 unsigned n_div;
5254 if (!bmap)
5255 return NULL;
5256 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5257 if (n_div == 0)
5258 return bmap;
5260 bmap = add_known_div_constraints(bmap);
5261 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5262 bmap = isl_basic_map_finalize(bmap);
5263 return bmap;
5266 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5268 * In particular, if this div is of the form d = floor(f/m),
5269 * then add the constraint
5271 * f - m d >= 0
5273 * if sign < 0 or the constraint
5275 * -(f-(m-1)) + m d >= 0
5277 * if sign > 0.
5279 int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
5280 unsigned div, int sign)
5282 unsigned total;
5283 unsigned div_pos;
5285 if (!bmap)
5286 return -1;
5288 total = isl_basic_map_total_dim(bmap);
5289 div_pos = total - bmap->n_div + div;
5291 if (sign < 0)
5292 return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
5293 else
5294 return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
5297 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5298 __isl_take isl_basic_map *bmap)
5300 if (!bmap)
5301 goto error;
5302 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5303 bmap->n_div == 0 &&
5304 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5305 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5306 return bset_from_bmap(bmap);
5307 bmap = isl_basic_map_cow(bmap);
5308 if (!bmap)
5309 goto error;
5310 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
5311 if (!bmap->dim)
5312 goto error;
5313 bmap->extra -= bmap->n_div;
5314 bmap->n_div = 0;
5315 bmap = isl_basic_map_finalize(bmap);
5316 return bset_from_bmap(bmap);
5317 error:
5318 isl_basic_map_free(bmap);
5319 return NULL;
5322 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5323 __isl_take isl_basic_set *bset)
5325 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5328 /* Replace each element in "list" by the result of applying
5329 * isl_basic_map_underlying_set to the element.
5331 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5332 __isl_take isl_basic_map_list *list)
5334 int i, n;
5336 if (!list)
5337 return NULL;
5339 n = isl_basic_map_list_n_basic_map(list);
5340 for (i = 0; i < n; ++i) {
5341 isl_basic_map *bmap;
5342 isl_basic_set *bset;
5344 bmap = isl_basic_map_list_get_basic_map(list, i);
5345 bset = isl_basic_set_underlying_set(bmap);
5346 list = isl_basic_set_list_set_basic_set(list, i, bset);
5349 return list;
5352 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5353 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5355 struct isl_basic_map *bmap;
5356 struct isl_ctx *ctx;
5357 unsigned total;
5358 int i;
5360 if (!bset || !like)
5361 goto error;
5362 ctx = bset->ctx;
5363 isl_assert(ctx, bset->n_div == 0, goto error);
5364 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
5365 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
5366 goto error);
5367 if (like->n_div == 0) {
5368 isl_space *space = isl_basic_map_get_space(like);
5369 isl_basic_map_free(like);
5370 return isl_basic_map_reset_space(bset, space);
5372 bset = isl_basic_set_cow(bset);
5373 if (!bset)
5374 goto error;
5375 total = bset->dim->n_out + bset->extra;
5376 bmap = bset_to_bmap(bset);
5377 isl_space_free(bmap->dim);
5378 bmap->dim = isl_space_copy(like->dim);
5379 if (!bmap->dim)
5380 goto error;
5381 bmap->n_div = like->n_div;
5382 bmap->extra += like->n_div;
5383 if (bmap->extra) {
5384 unsigned ltotal;
5385 isl_int **div;
5386 ltotal = total - bmap->extra + like->extra;
5387 if (ltotal > total)
5388 ltotal = total;
5389 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5390 bmap->extra * (1 + 1 + total));
5391 if (isl_blk_is_error(bmap->block2))
5392 goto error;
5393 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5394 if (!div)
5395 goto error;
5396 bmap->div = div;
5397 for (i = 0; i < bmap->extra; ++i)
5398 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5399 for (i = 0; i < like->n_div; ++i) {
5400 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5401 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5403 bmap = isl_basic_map_add_known_div_constraints(bmap);
5405 isl_basic_map_free(like);
5406 bmap = isl_basic_map_simplify(bmap);
5407 bmap = isl_basic_map_finalize(bmap);
5408 return bmap;
5409 error:
5410 isl_basic_map_free(like);
5411 isl_basic_set_free(bset);
5412 return NULL;
5415 struct isl_basic_set *isl_basic_set_from_underlying_set(
5416 struct isl_basic_set *bset, struct isl_basic_set *like)
5418 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5419 bset_to_bmap(like)));
5422 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5424 int i;
5426 map = isl_map_cow(map);
5427 if (!map)
5428 return NULL;
5429 map->dim = isl_space_cow(map->dim);
5430 if (!map->dim)
5431 goto error;
5433 for (i = 1; i < map->n; ++i)
5434 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5435 goto error);
5436 for (i = 0; i < map->n; ++i) {
5437 map->p[i] = bset_to_bmap(
5438 isl_basic_map_underlying_set(map->p[i]));
5439 if (!map->p[i])
5440 goto error;
5442 if (map->n == 0)
5443 map->dim = isl_space_underlying(map->dim, 0);
5444 else {
5445 isl_space_free(map->dim);
5446 map->dim = isl_space_copy(map->p[0]->dim);
5448 if (!map->dim)
5449 goto error;
5450 return set_from_map(map);
5451 error:
5452 isl_map_free(map);
5453 return NULL;
5456 /* Replace the space of "bmap" by "space".
5458 * If the space of "bmap" is identical to "space" (including the identifiers
5459 * of the input and output dimensions), then simply return the original input.
5461 __isl_give isl_basic_map *isl_basic_map_reset_space(
5462 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5464 isl_bool equal;
5465 isl_space *bmap_space;
5467 bmap_space = isl_basic_map_peek_space(bmap);
5468 equal = isl_space_is_equal(bmap_space, space);
5469 if (equal >= 0 && equal)
5470 equal = isl_space_has_equal_ids(bmap_space, space);
5471 if (equal < 0)
5472 goto error;
5473 if (equal) {
5474 isl_space_free(space);
5475 return bmap;
5477 bmap = isl_basic_map_cow(bmap);
5478 if (!bmap || !space)
5479 goto error;
5481 isl_space_free(bmap->dim);
5482 bmap->dim = space;
5484 bmap = isl_basic_map_finalize(bmap);
5486 return bmap;
5487 error:
5488 isl_basic_map_free(bmap);
5489 isl_space_free(space);
5490 return NULL;
5493 __isl_give isl_basic_set *isl_basic_set_reset_space(
5494 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5496 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5497 dim));
5500 /* Check that the total dimensions of "map" and "space" are the same.
5502 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5503 __isl_keep isl_space *space)
5505 unsigned dim1, dim2;
5507 if (!map || !space)
5508 return isl_stat_error;
5509 dim1 = isl_map_dim(map, isl_dim_all);
5510 dim2 = isl_space_dim(space, isl_dim_all);
5511 if (dim1 == dim2)
5512 return isl_stat_ok;
5513 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5514 "total dimensions do not match", return isl_stat_error);
5517 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5518 __isl_take isl_space *space)
5520 int i;
5522 map = isl_map_cow(map);
5523 if (!map || !space)
5524 goto error;
5526 for (i = 0; i < map->n; ++i) {
5527 map->p[i] = isl_basic_map_reset_space(map->p[i],
5528 isl_space_copy(space));
5529 if (!map->p[i])
5530 goto error;
5532 isl_space_free(map->dim);
5533 map->dim = space;
5535 return map;
5536 error:
5537 isl_map_free(map);
5538 isl_space_free(space);
5539 return NULL;
5542 /* Replace the space of "map" by "space", without modifying
5543 * the dimension of "map".
5545 * If the space of "map" is identical to "space" (including the identifiers
5546 * of the input and output dimensions), then simply return the original input.
5548 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5549 __isl_take isl_space *space)
5551 isl_bool equal;
5552 isl_space *map_space;
5554 map_space = isl_map_peek_space(map);
5555 equal = isl_space_is_equal(map_space, space);
5556 if (equal >= 0 && equal)
5557 equal = isl_space_has_equal_ids(map_space, space);
5558 if (equal < 0)
5559 goto error;
5560 if (equal) {
5561 isl_space_free(space);
5562 return map;
5564 if (check_map_space_equal_total_dim(map, space) < 0)
5565 goto error;
5566 return isl_map_reset_space(map, space);
5567 error:
5568 isl_map_free(map);
5569 isl_space_free(space);
5570 return NULL;
5573 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5574 __isl_take isl_space *dim)
5576 return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5579 /* Compute the parameter domain of the given basic set.
5581 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5583 isl_bool is_params;
5584 isl_space *space;
5585 unsigned n;
5587 is_params = isl_basic_set_is_params(bset);
5588 if (is_params < 0)
5589 return isl_basic_set_free(bset);
5590 if (is_params)
5591 return bset;
5593 n = isl_basic_set_dim(bset, isl_dim_set);
5594 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5595 space = isl_basic_set_get_space(bset);
5596 space = isl_space_params(space);
5597 bset = isl_basic_set_reset_space(bset, space);
5598 return bset;
5601 /* Construct a zero-dimensional basic set with the given parameter domain.
5603 __isl_give isl_basic_set *isl_basic_set_from_params(
5604 __isl_take isl_basic_set *bset)
5606 isl_space *space;
5607 space = isl_basic_set_get_space(bset);
5608 space = isl_space_set_from_params(space);
5609 bset = isl_basic_set_reset_space(bset, space);
5610 return bset;
5613 /* Compute the parameter domain of the given set.
5615 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5617 isl_space *space;
5618 unsigned n;
5620 if (isl_set_is_params(set))
5621 return set;
5623 n = isl_set_dim(set, isl_dim_set);
5624 set = isl_set_project_out(set, isl_dim_set, 0, n);
5625 space = isl_set_get_space(set);
5626 space = isl_space_params(space);
5627 set = isl_set_reset_space(set, space);
5628 return set;
5631 /* Construct a zero-dimensional set with the given parameter domain.
5633 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5635 isl_space *space;
5636 space = isl_set_get_space(set);
5637 space = isl_space_set_from_params(space);
5638 set = isl_set_reset_space(set, space);
5639 return set;
5642 /* Compute the parameter domain of the given map.
5644 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5646 isl_space *space;
5647 unsigned n;
5649 n = isl_map_dim(map, isl_dim_in);
5650 map = isl_map_project_out(map, isl_dim_in, 0, n);
5651 n = isl_map_dim(map, isl_dim_out);
5652 map = isl_map_project_out(map, isl_dim_out, 0, n);
5653 space = isl_map_get_space(map);
5654 space = isl_space_params(space);
5655 map = isl_map_reset_space(map, space);
5656 return map;
5659 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5661 isl_space *space;
5662 unsigned n_out;
5664 if (!bmap)
5665 return NULL;
5666 space = isl_space_domain(isl_basic_map_get_space(bmap));
5668 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5669 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5671 return isl_basic_map_reset_space(bmap, space);
5674 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5676 if (!bmap)
5677 return isl_bool_error;
5678 return isl_space_may_be_set(bmap->dim);
5681 /* Is this basic map actually a set?
5682 * Users should never call this function. Outside of isl,
5683 * the type should indicate whether something is a set or a map.
5685 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5687 if (!bmap)
5688 return isl_bool_error;
5689 return isl_space_is_set(bmap->dim);
5692 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5694 isl_bool is_set;
5696 is_set = isl_basic_map_is_set(bmap);
5697 if (is_set < 0)
5698 goto error;
5699 if (is_set)
5700 return bmap;
5701 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5702 error:
5703 isl_basic_map_free(bmap);
5704 return NULL;
5707 __isl_give isl_basic_map *isl_basic_map_domain_map(
5708 __isl_take isl_basic_map *bmap)
5710 int i;
5711 isl_space *space;
5712 isl_basic_map *domain;
5713 int nparam, n_in, n_out;
5715 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5716 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5717 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5719 space = isl_basic_map_get_space(bmap);
5720 space = isl_space_from_range(isl_space_domain(space));
5721 domain = isl_basic_map_universe(space);
5723 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5724 bmap = isl_basic_map_apply_range(bmap, domain);
5725 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5727 for (i = 0; i < n_in; ++i)
5728 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5729 isl_dim_out, i);
5731 bmap = isl_basic_map_gauss(bmap, NULL);
5732 return isl_basic_map_finalize(bmap);
5735 __isl_give isl_basic_map *isl_basic_map_range_map(
5736 __isl_take isl_basic_map *bmap)
5738 int i;
5739 isl_space *space;
5740 isl_basic_map *range;
5741 int nparam, n_in, n_out;
5743 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5744 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5745 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5747 space = isl_basic_map_get_space(bmap);
5748 space = isl_space_from_range(isl_space_range(space));
5749 range = isl_basic_map_universe(space);
5751 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5752 bmap = isl_basic_map_apply_range(bmap, range);
5753 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5755 for (i = 0; i < n_out; ++i)
5756 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5757 isl_dim_out, i);
5759 bmap = isl_basic_map_gauss(bmap, NULL);
5760 return isl_basic_map_finalize(bmap);
5763 int isl_map_may_be_set(__isl_keep isl_map *map)
5765 if (!map)
5766 return -1;
5767 return isl_space_may_be_set(map->dim);
5770 /* Is this map actually a set?
5771 * Users should never call this function. Outside of isl,
5772 * the type should indicate whether something is a set or a map.
5774 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5776 if (!map)
5777 return isl_bool_error;
5778 return isl_space_is_set(map->dim);
5781 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
5783 int i;
5784 isl_bool is_set;
5785 struct isl_set *set;
5787 is_set = isl_map_is_set(map);
5788 if (is_set < 0)
5789 goto error;
5790 if (is_set)
5791 return set_from_map(map);
5793 map = isl_map_cow(map);
5794 if (!map)
5795 goto error;
5797 set = set_from_map(map);
5798 set->dim = isl_space_range(set->dim);
5799 if (!set->dim)
5800 goto error;
5801 for (i = 0; i < map->n; ++i) {
5802 set->p[i] = isl_basic_map_range(map->p[i]);
5803 if (!set->p[i])
5804 goto error;
5806 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5807 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5808 return set;
5809 error:
5810 isl_map_free(map);
5811 return NULL;
5814 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5816 int i;
5818 map = isl_map_cow(map);
5819 if (!map)
5820 return NULL;
5822 map->dim = isl_space_domain_map(map->dim);
5823 if (!map->dim)
5824 goto error;
5825 for (i = 0; i < map->n; ++i) {
5826 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5827 if (!map->p[i])
5828 goto error;
5830 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5831 map = isl_map_unmark_normalized(map);
5832 return map;
5833 error:
5834 isl_map_free(map);
5835 return NULL;
5838 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5840 int i;
5841 isl_space *range_dim;
5843 map = isl_map_cow(map);
5844 if (!map)
5845 return NULL;
5847 range_dim = isl_space_range(isl_map_get_space(map));
5848 range_dim = isl_space_from_range(range_dim);
5849 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5850 map->dim = isl_space_join(map->dim, range_dim);
5851 if (!map->dim)
5852 goto error;
5853 for (i = 0; i < map->n; ++i) {
5854 map->p[i] = isl_basic_map_range_map(map->p[i]);
5855 if (!map->p[i])
5856 goto error;
5858 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5859 map = isl_map_unmark_normalized(map);
5860 return map;
5861 error:
5862 isl_map_free(map);
5863 return NULL;
5866 /* Given a wrapped map of the form A[B -> C],
5867 * return the map A[B -> C] -> B.
5869 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5871 isl_id *id;
5872 isl_map *map;
5874 if (!set)
5875 return NULL;
5876 if (!isl_set_has_tuple_id(set))
5877 return isl_map_domain_map(isl_set_unwrap(set));
5879 id = isl_set_get_tuple_id(set);
5880 map = isl_map_domain_map(isl_set_unwrap(set));
5881 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5883 return map;
5886 __isl_give isl_basic_map *isl_basic_map_from_domain(
5887 __isl_take isl_basic_set *bset)
5889 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5892 __isl_give isl_basic_map *isl_basic_map_from_range(
5893 __isl_take isl_basic_set *bset)
5895 isl_space *space;
5896 space = isl_basic_set_get_space(bset);
5897 space = isl_space_from_range(space);
5898 bset = isl_basic_set_reset_space(bset, space);
5899 return bset_to_bmap(bset);
5902 /* Create a relation with the given set as range.
5903 * The domain of the created relation is a zero-dimensional
5904 * flat anonymous space.
5906 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5908 isl_space *space;
5909 space = isl_set_get_space(set);
5910 space = isl_space_from_range(space);
5911 set = isl_set_reset_space(set, space);
5912 return set_to_map(set);
5915 /* Create a relation with the given set as domain.
5916 * The range of the created relation is a zero-dimensional
5917 * flat anonymous space.
5919 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5921 return isl_map_reverse(isl_map_from_range(set));
5924 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5925 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5927 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5930 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5931 __isl_take isl_set *range)
5933 return isl_map_apply_range(isl_map_reverse(domain), range);
5936 /* Return a newly allocated isl_map with given space and flags and
5937 * room for "n" basic maps.
5938 * Make sure that all cached information is cleared.
5940 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5941 unsigned flags)
5943 struct isl_map *map;
5945 if (!space)
5946 return NULL;
5947 if (n < 0)
5948 isl_die(space->ctx, isl_error_internal,
5949 "negative number of basic maps", goto error);
5950 map = isl_calloc(space->ctx, struct isl_map,
5951 sizeof(struct isl_map) +
5952 (n - 1) * sizeof(struct isl_basic_map *));
5953 if (!map)
5954 goto error;
5956 map->ctx = space->ctx;
5957 isl_ctx_ref(map->ctx);
5958 map->ref = 1;
5959 map->size = n;
5960 map->n = 0;
5961 map->dim = space;
5962 map->flags = flags;
5963 return map;
5964 error:
5965 isl_space_free(space);
5966 return NULL;
5969 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
5971 struct isl_basic_map *bmap;
5972 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
5973 bmap = isl_basic_map_set_to_empty(bmap);
5974 return bmap;
5977 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
5979 struct isl_basic_set *bset;
5980 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
5981 bset = isl_basic_set_set_to_empty(bset);
5982 return bset;
5985 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
5987 struct isl_basic_map *bmap;
5988 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
5989 bmap = isl_basic_map_finalize(bmap);
5990 return bmap;
5993 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
5995 struct isl_basic_set *bset;
5996 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
5997 bset = isl_basic_set_finalize(bset);
5998 return bset;
6001 __isl_give isl_basic_map *isl_basic_map_nat_universe(
6002 __isl_take isl_space *space)
6004 int i;
6005 unsigned total = isl_space_dim(space, isl_dim_all);
6006 isl_basic_map *bmap;
6008 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
6009 for (i = 0; i < total; ++i) {
6010 int k = isl_basic_map_alloc_inequality(bmap);
6011 if (k < 0)
6012 goto error;
6013 isl_seq_clr(bmap->ineq[k], 1 + total);
6014 isl_int_set_si(bmap->ineq[k][1 + i], 1);
6016 return bmap;
6017 error:
6018 isl_basic_map_free(bmap);
6019 return NULL;
6022 __isl_give isl_basic_set *isl_basic_set_nat_universe(
6023 __isl_take isl_space *space)
6025 return isl_basic_map_nat_universe(space);
6028 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
6030 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
6033 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
6035 return isl_map_nat_universe(dim);
6038 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6040 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6043 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6045 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6048 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6050 struct isl_map *map;
6051 if (!space)
6052 return NULL;
6053 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6054 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6055 return map;
6058 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6060 struct isl_set *set;
6061 if (!space)
6062 return NULL;
6063 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6064 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6065 return set;
6068 struct isl_map *isl_map_dup(struct isl_map *map)
6070 int i;
6071 struct isl_map *dup;
6073 if (!map)
6074 return NULL;
6075 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6076 for (i = 0; i < map->n; ++i)
6077 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6078 return dup;
6081 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6082 __isl_take isl_basic_map *bmap)
6084 if (!bmap || !map)
6085 goto error;
6086 if (isl_basic_map_plain_is_empty(bmap)) {
6087 isl_basic_map_free(bmap);
6088 return map;
6090 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
6091 isl_assert(map->ctx, map->n < map->size, goto error);
6092 map->p[map->n] = bmap;
6093 map->n++;
6094 map = isl_map_unmark_normalized(map);
6095 return map;
6096 error:
6097 if (map)
6098 isl_map_free(map);
6099 if (bmap)
6100 isl_basic_map_free(bmap);
6101 return NULL;
6104 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6106 int i;
6108 if (!map)
6109 return NULL;
6111 if (--map->ref > 0)
6112 return NULL;
6114 clear_caches(map);
6115 isl_ctx_deref(map->ctx);
6116 for (i = 0; i < map->n; ++i)
6117 isl_basic_map_free(map->p[i]);
6118 isl_space_free(map->dim);
6119 free(map);
6121 return NULL;
6124 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6125 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6127 int j;
6129 bmap = isl_basic_map_cow(bmap);
6130 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6131 j = isl_basic_map_alloc_equality(bmap);
6132 if (j < 0)
6133 goto error;
6134 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6135 isl_int_set_si(bmap->eq[j][pos], -1);
6136 isl_int_set_si(bmap->eq[j][0], value);
6137 bmap = isl_basic_map_simplify(bmap);
6138 return isl_basic_map_finalize(bmap);
6139 error:
6140 isl_basic_map_free(bmap);
6141 return NULL;
6144 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6145 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6147 int j;
6149 bmap = isl_basic_map_cow(bmap);
6150 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6151 j = isl_basic_map_alloc_equality(bmap);
6152 if (j < 0)
6153 goto error;
6154 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6155 isl_int_set_si(bmap->eq[j][pos], -1);
6156 isl_int_set(bmap->eq[j][0], value);
6157 bmap = isl_basic_map_simplify(bmap);
6158 return isl_basic_map_finalize(bmap);
6159 error:
6160 isl_basic_map_free(bmap);
6161 return NULL;
6164 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6165 enum isl_dim_type type, unsigned pos, int value)
6167 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6168 return isl_basic_map_free(bmap);
6169 return isl_basic_map_fix_pos_si(bmap,
6170 isl_basic_map_offset(bmap, type) + pos, value);
6173 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6174 enum isl_dim_type type, unsigned pos, isl_int value)
6176 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6177 return isl_basic_map_free(bmap);
6178 return isl_basic_map_fix_pos(bmap,
6179 isl_basic_map_offset(bmap, type) + pos, value);
6182 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6183 * to be equal to "v".
6185 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6186 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6188 if (!bmap || !v)
6189 goto error;
6190 if (!isl_val_is_int(v))
6191 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6192 "expecting integer value", goto error);
6193 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6194 goto error;
6195 pos += isl_basic_map_offset(bmap, type);
6196 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6197 isl_val_free(v);
6198 return bmap;
6199 error:
6200 isl_basic_map_free(bmap);
6201 isl_val_free(v);
6202 return NULL;
6205 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6206 * to be equal to "v".
6208 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6209 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6211 return isl_basic_map_fix_val(bset, type, pos, v);
6214 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
6215 enum isl_dim_type type, unsigned pos, int value)
6217 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6218 type, pos, value));
6221 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6222 enum isl_dim_type type, unsigned pos, isl_int value)
6224 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6225 type, pos, value));
6228 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
6229 unsigned input, int value)
6231 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
6234 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
6235 unsigned dim, int value)
6237 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6238 isl_dim_set, dim, value));
6241 /* Remove the basic map at position "i" from "map" if this basic map
6242 * is (obviously) empty.
6244 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6246 isl_bool empty;
6248 if (!map)
6249 return NULL;
6251 empty = isl_basic_map_plain_is_empty(map->p[i]);
6252 if (empty < 0)
6253 return isl_map_free(map);
6254 if (!empty)
6255 return map;
6257 isl_basic_map_free(map->p[i]);
6258 map->n--;
6259 if (i != map->n) {
6260 map->p[i] = map->p[map->n];
6261 map = isl_map_unmark_normalized(map);
6265 return map;
6268 /* Perform "fn" on each basic map of "map", where we may not be holding
6269 * the only reference to "map".
6270 * In particular, "fn" should be a semantics preserving operation
6271 * that we want to apply to all copies of "map". We therefore need
6272 * to be careful not to modify "map" in a way that breaks "map"
6273 * in case anything goes wrong.
6275 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6276 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6278 struct isl_basic_map *bmap;
6279 int i;
6281 if (!map)
6282 return NULL;
6284 for (i = map->n - 1; i >= 0; --i) {
6285 bmap = isl_basic_map_copy(map->p[i]);
6286 bmap = fn(bmap);
6287 if (!bmap)
6288 goto error;
6289 isl_basic_map_free(map->p[i]);
6290 map->p[i] = bmap;
6291 map = remove_if_empty(map, i);
6292 if (!map)
6293 return NULL;
6296 return map;
6297 error:
6298 isl_map_free(map);
6299 return NULL;
6302 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6303 enum isl_dim_type type, unsigned pos, int value)
6305 int i;
6307 map = isl_map_cow(map);
6308 if (!map)
6309 return NULL;
6311 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6312 for (i = map->n - 1; i >= 0; --i) {
6313 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6314 map = remove_if_empty(map, i);
6315 if (!map)
6316 return NULL;
6318 map = isl_map_unmark_normalized(map);
6319 return map;
6320 error:
6321 isl_map_free(map);
6322 return NULL;
6325 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6326 enum isl_dim_type type, unsigned pos, int value)
6328 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6331 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6332 enum isl_dim_type type, unsigned pos, isl_int value)
6334 int i;
6336 map = isl_map_cow(map);
6337 if (!map)
6338 return NULL;
6340 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6341 for (i = 0; i < map->n; ++i) {
6342 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6343 if (!map->p[i])
6344 goto error;
6346 map = isl_map_unmark_normalized(map);
6347 return map;
6348 error:
6349 isl_map_free(map);
6350 return NULL;
6353 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6354 enum isl_dim_type type, unsigned pos, isl_int value)
6356 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6359 /* Fix the value of the variable at position "pos" of type "type" of "map"
6360 * to be equal to "v".
6362 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6363 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6365 int i;
6367 map = isl_map_cow(map);
6368 if (!map || !v)
6369 goto error;
6371 if (!isl_val_is_int(v))
6372 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6373 "expecting integer value", goto error);
6374 if (pos >= isl_map_dim(map, type))
6375 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6376 "index out of bounds", goto error);
6377 for (i = map->n - 1; i >= 0; --i) {
6378 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6379 isl_val_copy(v));
6380 map = remove_if_empty(map, i);
6381 if (!map)
6382 goto error;
6384 map = isl_map_unmark_normalized(map);
6385 isl_val_free(v);
6386 return map;
6387 error:
6388 isl_map_free(map);
6389 isl_val_free(v);
6390 return NULL;
6393 /* Fix the value of the variable at position "pos" of type "type" of "set"
6394 * to be equal to "v".
6396 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6397 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6399 return isl_map_fix_val(set, type, pos, v);
6402 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
6403 unsigned input, int value)
6405 return isl_map_fix_si(map, isl_dim_in, input, value);
6408 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
6410 return set_from_map(isl_map_fix_si(set_to_map(set),
6411 isl_dim_set, dim, value));
6414 static __isl_give isl_basic_map *basic_map_bound_si(
6415 __isl_take isl_basic_map *bmap,
6416 enum isl_dim_type type, unsigned pos, int value, int upper)
6418 int j;
6420 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6421 return isl_basic_map_free(bmap);
6422 pos += isl_basic_map_offset(bmap, type);
6423 bmap = isl_basic_map_cow(bmap);
6424 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6425 j = isl_basic_map_alloc_inequality(bmap);
6426 if (j < 0)
6427 goto error;
6428 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6429 if (upper) {
6430 isl_int_set_si(bmap->ineq[j][pos], -1);
6431 isl_int_set_si(bmap->ineq[j][0], value);
6432 } else {
6433 isl_int_set_si(bmap->ineq[j][pos], 1);
6434 isl_int_set_si(bmap->ineq[j][0], -value);
6436 bmap = isl_basic_map_simplify(bmap);
6437 return isl_basic_map_finalize(bmap);
6438 error:
6439 isl_basic_map_free(bmap);
6440 return NULL;
6443 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6444 __isl_take isl_basic_map *bmap,
6445 enum isl_dim_type type, unsigned pos, int value)
6447 return basic_map_bound_si(bmap, type, pos, value, 0);
6450 /* Constrain the values of the given dimension to be no greater than "value".
6452 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6453 __isl_take isl_basic_map *bmap,
6454 enum isl_dim_type type, unsigned pos, int value)
6456 return basic_map_bound_si(bmap, type, pos, value, 1);
6459 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6460 enum isl_dim_type type, unsigned pos, int value, int upper)
6462 int i;
6464 map = isl_map_cow(map);
6465 if (!map)
6466 return NULL;
6468 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6469 for (i = 0; i < map->n; ++i) {
6470 map->p[i] = basic_map_bound_si(map->p[i],
6471 type, pos, value, upper);
6472 if (!map->p[i])
6473 goto error;
6475 map = isl_map_unmark_normalized(map);
6476 return map;
6477 error:
6478 isl_map_free(map);
6479 return NULL;
6482 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6483 enum isl_dim_type type, unsigned pos, int value)
6485 return map_bound_si(map, type, pos, value, 0);
6488 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6489 enum isl_dim_type type, unsigned pos, int value)
6491 return map_bound_si(map, type, pos, value, 1);
6494 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6495 enum isl_dim_type type, unsigned pos, int value)
6497 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6498 type, pos, value));
6501 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6502 enum isl_dim_type type, unsigned pos, int value)
6504 return isl_map_upper_bound_si(set, type, pos, value);
6507 /* Bound the given variable of "bmap" from below (or above is "upper"
6508 * is set) to "value".
6510 static __isl_give isl_basic_map *basic_map_bound(
6511 __isl_take isl_basic_map *bmap,
6512 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6514 int j;
6516 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6517 return isl_basic_map_free(bmap);
6518 pos += isl_basic_map_offset(bmap, type);
6519 bmap = isl_basic_map_cow(bmap);
6520 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6521 j = isl_basic_map_alloc_inequality(bmap);
6522 if (j < 0)
6523 goto error;
6524 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6525 if (upper) {
6526 isl_int_set_si(bmap->ineq[j][pos], -1);
6527 isl_int_set(bmap->ineq[j][0], value);
6528 } else {
6529 isl_int_set_si(bmap->ineq[j][pos], 1);
6530 isl_int_neg(bmap->ineq[j][0], value);
6532 bmap = isl_basic_map_simplify(bmap);
6533 return isl_basic_map_finalize(bmap);
6534 error:
6535 isl_basic_map_free(bmap);
6536 return NULL;
6539 /* Bound the given variable of "map" from below (or above is "upper"
6540 * is set) to "value".
6542 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6543 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6545 int i;
6547 map = isl_map_cow(map);
6548 if (!map)
6549 return NULL;
6551 if (pos >= isl_map_dim(map, type))
6552 isl_die(map->ctx, isl_error_invalid,
6553 "index out of bounds", goto error);
6554 for (i = map->n - 1; i >= 0; --i) {
6555 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6556 map = remove_if_empty(map, i);
6557 if (!map)
6558 return NULL;
6560 map = isl_map_unmark_normalized(map);
6561 return map;
6562 error:
6563 isl_map_free(map);
6564 return NULL;
6567 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6568 enum isl_dim_type type, unsigned pos, isl_int value)
6570 return map_bound(map, type, pos, value, 0);
6573 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6574 enum isl_dim_type type, unsigned pos, isl_int value)
6576 return map_bound(map, type, pos, value, 1);
6579 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6580 enum isl_dim_type type, unsigned pos, isl_int value)
6582 return isl_map_lower_bound(set, type, pos, value);
6585 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6586 enum isl_dim_type type, unsigned pos, isl_int value)
6588 return isl_map_upper_bound(set, type, pos, value);
6591 /* Force the values of the variable at position "pos" of type "type" of "set"
6592 * to be no smaller than "value".
6594 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6595 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6597 if (!value)
6598 goto error;
6599 if (!isl_val_is_int(value))
6600 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6601 "expecting integer value", goto error);
6602 set = isl_set_lower_bound(set, type, pos, value->n);
6603 isl_val_free(value);
6604 return set;
6605 error:
6606 isl_val_free(value);
6607 isl_set_free(set);
6608 return NULL;
6611 /* Force the values of the variable at position "pos" of type "type" of "set"
6612 * to be no greater than "value".
6614 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6615 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6617 if (!value)
6618 goto error;
6619 if (!isl_val_is_int(value))
6620 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6621 "expecting integer value", goto error);
6622 set = isl_set_upper_bound(set, type, pos, value->n);
6623 isl_val_free(value);
6624 return set;
6625 error:
6626 isl_val_free(value);
6627 isl_set_free(set);
6628 return NULL;
6631 /* Bound the given variable of "bset" from below (or above is "upper"
6632 * is set) to "value".
6634 static __isl_give isl_basic_set *isl_basic_set_bound(
6635 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6636 isl_int value, int upper)
6638 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
6639 type, pos, value, upper));
6642 /* Bound the given variable of "bset" from below (or above is "upper"
6643 * is set) to "value".
6645 static __isl_give isl_basic_set *isl_basic_set_bound_val(
6646 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6647 __isl_take isl_val *value, int upper)
6649 if (!value)
6650 goto error;
6651 if (!isl_val_is_int(value))
6652 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
6653 "expecting integer value", goto error);
6654 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
6655 isl_val_free(value);
6656 return bset;
6657 error:
6658 isl_val_free(value);
6659 isl_basic_set_free(bset);
6660 return NULL;
6663 /* Bound the given variable of "bset" from below to "value".
6665 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
6666 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6667 __isl_take isl_val *value)
6669 return isl_basic_set_bound_val(bset, type, pos, value, 0);
6672 /* Bound the given variable of "bset" from above to "value".
6674 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
6675 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6676 __isl_take isl_val *value)
6678 return isl_basic_set_bound_val(bset, type, pos, value, 1);
6681 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
6683 int i;
6685 map = isl_map_cow(map);
6686 if (!map)
6687 return NULL;
6689 map->dim = isl_space_reverse(map->dim);
6690 if (!map->dim)
6691 goto error;
6692 for (i = 0; i < map->n; ++i) {
6693 map->p[i] = isl_basic_map_reverse(map->p[i]);
6694 if (!map->p[i])
6695 goto error;
6697 map = isl_map_unmark_normalized(map);
6698 return map;
6699 error:
6700 isl_map_free(map);
6701 return NULL;
6704 #undef TYPE
6705 #define TYPE isl_pw_multi_aff
6706 #undef SUFFIX
6707 #define SUFFIX _pw_multi_aff
6708 #undef EMPTY
6709 #define EMPTY isl_pw_multi_aff_empty
6710 #undef ADD
6711 #define ADD isl_pw_multi_aff_union_add
6712 #include "isl_map_lexopt_templ.c"
6714 /* Given a map "map", compute the lexicographically minimal
6715 * (or maximal) image element for each domain element in dom,
6716 * in the form of an isl_pw_multi_aff.
6717 * If "empty" is not NULL, then set *empty to those elements in dom that
6718 * do not have an image element.
6719 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6720 * should be computed over the domain of "map". "empty" is also NULL
6721 * in this case.
6723 * We first compute the lexicographically minimal or maximal element
6724 * in the first basic map. This results in a partial solution "res"
6725 * and a subset "todo" of dom that still need to be handled.
6726 * We then consider each of the remaining maps in "map" and successively
6727 * update both "res" and "todo".
6728 * If "empty" is NULL, then the todo sets are not needed and therefore
6729 * also not computed.
6731 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6732 __isl_take isl_map *map, __isl_take isl_set *dom,
6733 __isl_give isl_set **empty, unsigned flags)
6735 int i;
6736 int full;
6737 isl_pw_multi_aff *res;
6738 isl_set *todo;
6740 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6741 if (!map || (!full && !dom))
6742 goto error;
6744 if (isl_map_plain_is_empty(map)) {
6745 if (empty)
6746 *empty = dom;
6747 else
6748 isl_set_free(dom);
6749 return isl_pw_multi_aff_from_map(map);
6752 res = basic_map_partial_lexopt_pw_multi_aff(
6753 isl_basic_map_copy(map->p[0]),
6754 isl_set_copy(dom), empty, flags);
6756 if (empty)
6757 todo = *empty;
6758 for (i = 1; i < map->n; ++i) {
6759 isl_pw_multi_aff *res_i;
6761 res_i = basic_map_partial_lexopt_pw_multi_aff(
6762 isl_basic_map_copy(map->p[i]),
6763 isl_set_copy(dom), empty, flags);
6765 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6766 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6767 else
6768 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6770 if (empty)
6771 todo = isl_set_intersect(todo, *empty);
6774 isl_set_free(dom);
6775 isl_map_free(map);
6777 if (empty)
6778 *empty = todo;
6780 return res;
6781 error:
6782 if (empty)
6783 *empty = NULL;
6784 isl_set_free(dom);
6785 isl_map_free(map);
6786 return NULL;
6789 #undef TYPE
6790 #define TYPE isl_map
6791 #undef SUFFIX
6792 #define SUFFIX
6793 #undef EMPTY
6794 #define EMPTY isl_map_empty
6795 #undef ADD
6796 #define ADD isl_map_union_disjoint
6797 #include "isl_map_lexopt_templ.c"
6799 /* Given a map "map", compute the lexicographically minimal
6800 * (or maximal) image element for each domain element in "dom",
6801 * in the form of an isl_map.
6802 * If "empty" is not NULL, then set *empty to those elements in "dom" that
6803 * do not have an image element.
6804 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6805 * should be computed over the domain of "map". "empty" is also NULL
6806 * in this case.
6808 * If the input consists of more than one disjunct, then first
6809 * compute the desired result in the form of an isl_pw_multi_aff and
6810 * then convert that into an isl_map.
6812 * This function used to have an explicit implementation in terms
6813 * of isl_maps, but it would continually intersect the domains of
6814 * partial results with the complement of the domain of the next
6815 * partial solution, potentially leading to an explosion in the number
6816 * of disjuncts if there are several disjuncts in the input.
6817 * An even earlier implementation of this function would look for
6818 * better results in the domain of the partial result and for extra
6819 * results in the complement of this domain, which would lead to
6820 * even more splintering.
6822 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6823 __isl_take isl_map *map, __isl_take isl_set *dom,
6824 __isl_give isl_set **empty, unsigned flags)
6826 int full;
6827 struct isl_map *res;
6828 isl_pw_multi_aff *pma;
6830 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6831 if (!map || (!full && !dom))
6832 goto error;
6834 if (isl_map_plain_is_empty(map)) {
6835 if (empty)
6836 *empty = dom;
6837 else
6838 isl_set_free(dom);
6839 return map;
6842 if (map->n == 1) {
6843 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6844 dom, empty, flags);
6845 isl_map_free(map);
6846 return res;
6849 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6850 flags);
6851 return isl_map_from_pw_multi_aff(pma);
6852 error:
6853 if (empty)
6854 *empty = NULL;
6855 isl_set_free(dom);
6856 isl_map_free(map);
6857 return NULL;
6860 __isl_give isl_map *isl_map_partial_lexmax(
6861 __isl_take isl_map *map, __isl_take isl_set *dom,
6862 __isl_give isl_set **empty)
6864 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6867 __isl_give isl_map *isl_map_partial_lexmin(
6868 __isl_take isl_map *map, __isl_take isl_set *dom,
6869 __isl_give isl_set **empty)
6871 return isl_map_partial_lexopt(map, dom, empty, 0);
6874 __isl_give isl_set *isl_set_partial_lexmin(
6875 __isl_take isl_set *set, __isl_take isl_set *dom,
6876 __isl_give isl_set **empty)
6878 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6879 dom, empty));
6882 __isl_give isl_set *isl_set_partial_lexmax(
6883 __isl_take isl_set *set, __isl_take isl_set *dom,
6884 __isl_give isl_set **empty)
6886 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6887 dom, empty));
6890 /* Compute the lexicographic minimum (or maximum if "flags" includes
6891 * ISL_OPT_MAX) of "bset" over its parametric domain.
6893 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6894 unsigned flags)
6896 return isl_basic_map_lexopt(bset, flags);
6899 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6901 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6904 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6906 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6909 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6911 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6914 /* Compute the lexicographic minimum of "bset" over its parametric domain
6915 * for the purpose of quantifier elimination.
6916 * That is, find an explicit representation for all the existentially
6917 * quantified variables in "bset" by computing their lexicographic
6918 * minimum.
6920 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6921 __isl_take isl_basic_set *bset)
6923 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6926 /* Given a basic map with one output dimension, compute the minimum or
6927 * maximum of that dimension as an isl_pw_aff.
6929 * Compute the optimum as a lexicographic optimum over the single
6930 * output dimension and extract the single isl_pw_aff from the result.
6932 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6933 int max)
6935 isl_pw_multi_aff *pma;
6936 isl_pw_aff *pwaff;
6938 bmap = isl_basic_map_copy(bmap);
6939 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
6940 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
6941 isl_pw_multi_aff_free(pma);
6943 return pwaff;
6946 /* Compute the minimum or maximum of the given output dimension
6947 * as a function of the parameters and the input dimensions,
6948 * but independently of the other output dimensions.
6950 * We first project out the other output dimension and then compute
6951 * the "lexicographic" maximum in each basic map, combining the results
6952 * using isl_pw_aff_union_max.
6954 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6955 int max)
6957 int i;
6958 isl_pw_aff *pwaff;
6959 unsigned n_out;
6961 n_out = isl_map_dim(map, isl_dim_out);
6962 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6963 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6964 if (!map)
6965 return NULL;
6967 if (map->n == 0) {
6968 isl_space *space = isl_map_get_space(map);
6969 isl_map_free(map);
6970 return isl_pw_aff_empty(space);
6973 pwaff = basic_map_dim_opt(map->p[0], max);
6974 for (i = 1; i < map->n; ++i) {
6975 isl_pw_aff *pwaff_i;
6977 pwaff_i = basic_map_dim_opt(map->p[i], max);
6978 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6981 isl_map_free(map);
6983 return pwaff;
6986 /* Compute the minimum of the given output dimension as a function of the
6987 * parameters and input dimensions, but independently of
6988 * the other output dimensions.
6990 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
6992 return map_dim_opt(map, pos, 0);
6995 /* Compute the maximum of the given output dimension as a function of the
6996 * parameters and input dimensions, but independently of
6997 * the other output dimensions.
6999 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7001 return map_dim_opt(map, pos, 1);
7004 /* Compute the minimum or maximum of the given set dimension
7005 * as a function of the parameters,
7006 * but independently of the other set dimensions.
7008 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7009 int max)
7011 return map_dim_opt(set, pos, max);
7014 /* Compute the maximum of the given set dimension as a function of the
7015 * parameters, but independently of the other set dimensions.
7017 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7019 return set_dim_opt(set, pos, 1);
7022 /* Compute the minimum of the given set dimension as a function of the
7023 * parameters, but independently of the other set dimensions.
7025 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7027 return set_dim_opt(set, pos, 0);
7030 /* Apply a preimage specified by "mat" on the parameters of "bset".
7031 * bset is assumed to have only parameters and divs.
7033 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7034 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7036 unsigned nparam;
7038 if (!bset || !mat)
7039 goto error;
7041 bset->dim = isl_space_cow(bset->dim);
7042 if (!bset->dim)
7043 goto error;
7045 nparam = isl_basic_set_dim(bset, isl_dim_param);
7047 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7049 bset->dim->nparam = 0;
7050 bset->dim->n_out = nparam;
7051 bset = isl_basic_set_preimage(bset, mat);
7052 if (bset) {
7053 bset->dim->nparam = bset->dim->n_out;
7054 bset->dim->n_out = 0;
7056 return bset;
7057 error:
7058 isl_mat_free(mat);
7059 isl_basic_set_free(bset);
7060 return NULL;
7063 /* Apply a preimage specified by "mat" on the parameters of "set".
7064 * set is assumed to have only parameters and divs.
7066 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7067 __isl_take isl_mat *mat)
7069 isl_space *space;
7070 unsigned nparam;
7072 if (!set || !mat)
7073 goto error;
7075 nparam = isl_set_dim(set, isl_dim_param);
7077 if (mat->n_row != 1 + nparam)
7078 isl_die(isl_set_get_ctx(set), isl_error_internal,
7079 "unexpected number of rows", goto error);
7081 space = isl_set_get_space(set);
7082 space = isl_space_move_dims(space, isl_dim_set, 0,
7083 isl_dim_param, 0, nparam);
7084 set = isl_set_reset_space(set, space);
7085 set = isl_set_preimage(set, mat);
7086 nparam = isl_set_dim(set, isl_dim_out);
7087 space = isl_set_get_space(set);
7088 space = isl_space_move_dims(space, isl_dim_param, 0,
7089 isl_dim_out, 0, nparam);
7090 set = isl_set_reset_space(set, space);
7091 return set;
7092 error:
7093 isl_mat_free(mat);
7094 isl_set_free(set);
7095 return NULL;
7098 /* Intersect the basic set "bset" with the affine space specified by the
7099 * equalities in "eq".
7101 static __isl_give isl_basic_set *basic_set_append_equalities(
7102 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7104 int i, k;
7105 unsigned len;
7107 if (!bset || !eq)
7108 goto error;
7110 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
7111 eq->n_row, 0);
7112 if (!bset)
7113 goto error;
7115 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
7116 for (i = 0; i < eq->n_row; ++i) {
7117 k = isl_basic_set_alloc_equality(bset);
7118 if (k < 0)
7119 goto error;
7120 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7121 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7123 isl_mat_free(eq);
7125 bset = isl_basic_set_gauss(bset, NULL);
7126 bset = isl_basic_set_finalize(bset);
7128 return bset;
7129 error:
7130 isl_mat_free(eq);
7131 isl_basic_set_free(bset);
7132 return NULL;
7135 /* Intersect the set "set" with the affine space specified by the
7136 * equalities in "eq".
7138 static struct isl_set *set_append_equalities(struct isl_set *set,
7139 struct isl_mat *eq)
7141 int i;
7143 if (!set || !eq)
7144 goto error;
7146 for (i = 0; i < set->n; ++i) {
7147 set->p[i] = basic_set_append_equalities(set->p[i],
7148 isl_mat_copy(eq));
7149 if (!set->p[i])
7150 goto error;
7152 isl_mat_free(eq);
7153 return set;
7154 error:
7155 isl_mat_free(eq);
7156 isl_set_free(set);
7157 return NULL;
7160 /* Given a basic set "bset" that only involves parameters and existentially
7161 * quantified variables, return the index of the first equality
7162 * that only involves parameters. If there is no such equality then
7163 * return bset->n_eq.
7165 * This function assumes that isl_basic_set_gauss has been called on "bset".
7167 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7169 int i, j;
7170 unsigned nparam, n_div;
7172 if (!bset)
7173 return -1;
7175 nparam = isl_basic_set_dim(bset, isl_dim_param);
7176 n_div = isl_basic_set_dim(bset, isl_dim_div);
7178 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7179 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7180 ++i;
7183 return i;
7186 /* Compute an explicit representation for the existentially quantified
7187 * variables in "bset" by computing the "minimal value" of the set
7188 * variables. Since there are no set variables, the computation of
7189 * the minimal value essentially computes an explicit representation
7190 * of the non-empty part(s) of "bset".
7192 * The input only involves parameters and existentially quantified variables.
7193 * All equalities among parameters have been removed.
7195 * Since the existentially quantified variables in the result are in general
7196 * going to be different from those in the input, we first replace
7197 * them by the minimal number of variables based on their equalities.
7198 * This should simplify the parametric integer programming.
7200 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7202 isl_morph *morph1, *morph2;
7203 isl_set *set;
7204 unsigned n;
7206 if (!bset)
7207 return NULL;
7208 if (bset->n_eq == 0)
7209 return isl_basic_set_lexmin_compute_divs(bset);
7211 morph1 = isl_basic_set_parameter_compression(bset);
7212 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7213 bset = isl_basic_set_lift(bset);
7214 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7215 bset = isl_morph_basic_set(morph2, bset);
7216 n = isl_basic_set_dim(bset, isl_dim_set);
7217 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7219 set = isl_basic_set_lexmin_compute_divs(bset);
7221 set = isl_morph_set(isl_morph_inverse(morph1), set);
7223 return set;
7226 /* Project the given basic set onto its parameter domain, possibly introducing
7227 * new, explicit, existential variables in the constraints.
7228 * The input has parameters and (possibly implicit) existential variables.
7229 * The output has the same parameters, but only
7230 * explicit existentially quantified variables.
7232 * The actual projection is performed by pip, but pip doesn't seem
7233 * to like equalities very much, so we first remove the equalities
7234 * among the parameters by performing a variable compression on
7235 * the parameters. Afterward, an inverse transformation is performed
7236 * and the equalities among the parameters are inserted back in.
7238 * The variable compression on the parameters may uncover additional
7239 * equalities that were only implicit before. We therefore check
7240 * if there are any new parameter equalities in the result and
7241 * if so recurse. The removal of parameter equalities is required
7242 * for the parameter compression performed by base_compute_divs.
7244 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
7246 int i;
7247 struct isl_mat *eq;
7248 struct isl_mat *T, *T2;
7249 struct isl_set *set;
7250 unsigned nparam;
7252 bset = isl_basic_set_cow(bset);
7253 if (!bset)
7254 return NULL;
7256 if (bset->n_eq == 0)
7257 return base_compute_divs(bset);
7259 bset = isl_basic_set_gauss(bset, NULL);
7260 if (!bset)
7261 return NULL;
7262 if (isl_basic_set_plain_is_empty(bset))
7263 return isl_set_from_basic_set(bset);
7265 i = first_parameter_equality(bset);
7266 if (i == bset->n_eq)
7267 return base_compute_divs(bset);
7269 nparam = isl_basic_set_dim(bset, isl_dim_param);
7270 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7271 0, 1 + nparam);
7272 eq = isl_mat_cow(eq);
7273 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7274 if (T && T->n_col == 0) {
7275 isl_mat_free(T);
7276 isl_mat_free(T2);
7277 isl_mat_free(eq);
7278 bset = isl_basic_set_set_to_empty(bset);
7279 return isl_set_from_basic_set(bset);
7281 bset = basic_set_parameter_preimage(bset, T);
7283 i = first_parameter_equality(bset);
7284 if (!bset)
7285 set = NULL;
7286 else if (i == bset->n_eq)
7287 set = base_compute_divs(bset);
7288 else
7289 set = parameter_compute_divs(bset);
7290 set = set_parameter_preimage(set, T2);
7291 set = set_append_equalities(set, eq);
7292 return set;
7295 /* Insert the divs from "ls" before those of "bmap".
7297 * The number of columns is not changed, which means that the last
7298 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7299 * The caller is responsible for removing the same number of dimensions
7300 * from the space of "bmap".
7302 static __isl_give isl_basic_map *insert_divs_from_local_space(
7303 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7305 int i;
7306 int n_div;
7307 int old_n_div;
7309 n_div = isl_local_space_dim(ls, isl_dim_div);
7310 if (n_div == 0)
7311 return bmap;
7313 old_n_div = bmap->n_div;
7314 bmap = insert_div_rows(bmap, n_div);
7315 if (!bmap)
7316 return NULL;
7318 for (i = 0; i < n_div; ++i) {
7319 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7320 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7323 return bmap;
7326 /* Replace the space of "bmap" by the space and divs of "ls".
7328 * If "ls" has any divs, then we simplify the result since we may
7329 * have discovered some additional equalities that could simplify
7330 * the div expressions.
7332 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7333 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7335 int n_div;
7337 bmap = isl_basic_map_cow(bmap);
7338 if (!bmap || !ls)
7339 goto error;
7341 n_div = isl_local_space_dim(ls, isl_dim_div);
7342 bmap = insert_divs_from_local_space(bmap, ls);
7343 if (!bmap)
7344 goto error;
7346 isl_space_free(bmap->dim);
7347 bmap->dim = isl_local_space_get_space(ls);
7348 if (!bmap->dim)
7349 goto error;
7351 isl_local_space_free(ls);
7352 if (n_div > 0)
7353 bmap = isl_basic_map_simplify(bmap);
7354 bmap = isl_basic_map_finalize(bmap);
7355 return bmap;
7356 error:
7357 isl_basic_map_free(bmap);
7358 isl_local_space_free(ls);
7359 return NULL;
7362 /* Replace the space of "map" by the space and divs of "ls".
7364 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7365 __isl_take isl_local_space *ls)
7367 int i;
7369 map = isl_map_cow(map);
7370 if (!map || !ls)
7371 goto error;
7373 for (i = 0; i < map->n; ++i) {
7374 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7375 isl_local_space_copy(ls));
7376 if (!map->p[i])
7377 goto error;
7379 isl_space_free(map->dim);
7380 map->dim = isl_local_space_get_space(ls);
7381 if (!map->dim)
7382 goto error;
7384 isl_local_space_free(ls);
7385 return map;
7386 error:
7387 isl_local_space_free(ls);
7388 isl_map_free(map);
7389 return NULL;
7392 /* Compute an explicit representation for the existentially
7393 * quantified variables for which do not know any explicit representation yet.
7395 * We first sort the existentially quantified variables so that the
7396 * existentially quantified variables for which we already have an explicit
7397 * representation are placed before those for which we do not.
7398 * The input dimensions, the output dimensions and the existentially
7399 * quantified variables for which we already have an explicit
7400 * representation are then turned into parameters.
7401 * compute_divs returns a map with the same parameters and
7402 * no input or output dimensions and the dimension specification
7403 * is reset to that of the input, including the existentially quantified
7404 * variables for which we already had an explicit representation.
7406 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7408 struct isl_basic_set *bset;
7409 struct isl_set *set;
7410 struct isl_map *map;
7411 isl_space *space;
7412 isl_local_space *ls;
7413 unsigned nparam;
7414 unsigned n_in;
7415 unsigned n_out;
7416 int n_known;
7417 int i;
7419 bmap = isl_basic_map_sort_divs(bmap);
7420 bmap = isl_basic_map_cow(bmap);
7421 if (!bmap)
7422 return NULL;
7424 n_known = isl_basic_map_first_unknown_div(bmap);
7425 if (n_known < 0)
7426 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7428 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7429 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7430 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7431 space = isl_space_set_alloc(bmap->ctx,
7432 nparam + n_in + n_out + n_known, 0);
7433 if (!space)
7434 goto error;
7436 ls = isl_basic_map_get_local_space(bmap);
7437 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7438 n_known, bmap->n_div - n_known);
7439 if (n_known > 0) {
7440 for (i = n_known; i < bmap->n_div; ++i)
7441 swap_div(bmap, i - n_known, i);
7442 bmap->n_div -= n_known;
7443 bmap->extra -= n_known;
7445 bmap = isl_basic_map_reset_space(bmap, space);
7446 bset = bset_from_bmap(bmap);
7448 set = parameter_compute_divs(bset);
7449 map = set_to_map(set);
7450 map = replace_space_by_local_space(map, ls);
7452 return map;
7453 error:
7454 isl_basic_map_free(bmap);
7455 return NULL;
7458 /* Remove the explicit representation of local variable "div",
7459 * if there is any.
7461 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7462 __isl_take isl_basic_map *bmap, int div)
7464 isl_bool unknown;
7466 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7467 if (unknown < 0)
7468 return isl_basic_map_free(bmap);
7469 if (unknown)
7470 return bmap;
7472 bmap = isl_basic_map_cow(bmap);
7473 if (!bmap)
7474 return NULL;
7475 isl_int_set_si(bmap->div[div][0], 0);
7476 return bmap;
7479 /* Is local variable "div" of "bmap" marked as not having an explicit
7480 * representation?
7481 * Note that even if "div" is not marked in this way and therefore
7482 * has an explicit representation, this representation may still
7483 * depend (indirectly) on other local variables that do not
7484 * have an explicit representation.
7486 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7487 int div)
7489 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7490 return isl_bool_error;
7491 return isl_int_is_zero(bmap->div[div][0]);
7494 /* Return the position of the first local variable that does not
7495 * have an explicit representation.
7496 * Return the total number of local variables if they all have
7497 * an explicit representation.
7498 * Return -1 on error.
7500 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7502 int i;
7504 if (!bmap)
7505 return -1;
7507 for (i = 0; i < bmap->n_div; ++i) {
7508 if (!isl_basic_map_div_is_known(bmap, i))
7509 return i;
7511 return bmap->n_div;
7514 /* Return the position of the first local variable that does not
7515 * have an explicit representation.
7516 * Return the total number of local variables if they all have
7517 * an explicit representation.
7518 * Return -1 on error.
7520 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7522 return isl_basic_map_first_unknown_div(bset);
7525 /* Does "bmap" have an explicit representation for all local variables?
7527 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7529 int first, n;
7531 n = isl_basic_map_dim(bmap, isl_dim_div);
7532 first = isl_basic_map_first_unknown_div(bmap);
7533 if (first < 0)
7534 return isl_bool_error;
7535 return first == n;
7538 /* Do all basic maps in "map" have an explicit representation
7539 * for all local variables?
7541 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7543 int i;
7545 if (!map)
7546 return isl_bool_error;
7548 for (i = 0; i < map->n; ++i) {
7549 int known = isl_basic_map_divs_known(map->p[i]);
7550 if (known <= 0)
7551 return known;
7554 return isl_bool_true;
7557 /* If bmap contains any unknown divs, then compute explicit
7558 * expressions for them. However, this computation may be
7559 * quite expensive, so first try to remove divs that aren't
7560 * strictly needed.
7562 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7564 int known;
7565 struct isl_map *map;
7567 known = isl_basic_map_divs_known(bmap);
7568 if (known < 0)
7569 goto error;
7570 if (known)
7571 return isl_map_from_basic_map(bmap);
7573 bmap = isl_basic_map_drop_redundant_divs(bmap);
7575 known = isl_basic_map_divs_known(bmap);
7576 if (known < 0)
7577 goto error;
7578 if (known)
7579 return isl_map_from_basic_map(bmap);
7581 map = compute_divs(bmap);
7582 return map;
7583 error:
7584 isl_basic_map_free(bmap);
7585 return NULL;
7588 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7590 int i;
7591 int known;
7592 struct isl_map *res;
7594 if (!map)
7595 return NULL;
7596 if (map->n == 0)
7597 return map;
7599 known = isl_map_divs_known(map);
7600 if (known < 0) {
7601 isl_map_free(map);
7602 return NULL;
7604 if (known)
7605 return map;
7607 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7608 for (i = 1 ; i < map->n; ++i) {
7609 struct isl_map *r2;
7610 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7611 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7612 res = isl_map_union_disjoint(res, r2);
7613 else
7614 res = isl_map_union(res, r2);
7616 isl_map_free(map);
7618 return res;
7621 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
7623 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7626 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7628 return set_from_map(isl_map_compute_divs(set_to_map(set)));
7631 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
7633 int i;
7634 struct isl_set *set;
7636 if (!map)
7637 goto error;
7639 map = isl_map_cow(map);
7640 if (!map)
7641 return NULL;
7643 set = set_from_map(map);
7644 set->dim = isl_space_domain(set->dim);
7645 if (!set->dim)
7646 goto error;
7647 for (i = 0; i < map->n; ++i) {
7648 set->p[i] = isl_basic_map_domain(map->p[i]);
7649 if (!set->p[i])
7650 goto error;
7652 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7653 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7654 return set;
7655 error:
7656 isl_map_free(map);
7657 return NULL;
7660 /* Return the union of "map1" and "map2", where we assume for now that
7661 * "map1" and "map2" are disjoint. Note that the basic maps inside
7662 * "map1" or "map2" may not be disjoint from each other.
7663 * Also note that this function is also called from isl_map_union,
7664 * which takes care of handling the situation where "map1" and "map2"
7665 * may not be disjoint.
7667 * If one of the inputs is empty, we can simply return the other input.
7668 * Similarly, if one of the inputs is universal, then it is equal to the union.
7670 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7671 __isl_take isl_map *map2)
7673 int i;
7674 unsigned flags = 0;
7675 struct isl_map *map = NULL;
7676 int is_universe;
7678 if (!map1 || !map2)
7679 goto error;
7681 if (!isl_space_is_equal(map1->dim, map2->dim))
7682 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7683 "spaces don't match", goto error);
7685 if (map1->n == 0) {
7686 isl_map_free(map1);
7687 return map2;
7689 if (map2->n == 0) {
7690 isl_map_free(map2);
7691 return map1;
7694 is_universe = isl_map_plain_is_universe(map1);
7695 if (is_universe < 0)
7696 goto error;
7697 if (is_universe) {
7698 isl_map_free(map2);
7699 return map1;
7702 is_universe = isl_map_plain_is_universe(map2);
7703 if (is_universe < 0)
7704 goto error;
7705 if (is_universe) {
7706 isl_map_free(map1);
7707 return map2;
7710 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7711 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7712 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7714 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7715 map1->n + map2->n, flags);
7716 if (!map)
7717 goto error;
7718 for (i = 0; i < map1->n; ++i) {
7719 map = isl_map_add_basic_map(map,
7720 isl_basic_map_copy(map1->p[i]));
7721 if (!map)
7722 goto error;
7724 for (i = 0; i < map2->n; ++i) {
7725 map = isl_map_add_basic_map(map,
7726 isl_basic_map_copy(map2->p[i]));
7727 if (!map)
7728 goto error;
7730 isl_map_free(map1);
7731 isl_map_free(map2);
7732 return map;
7733 error:
7734 isl_map_free(map);
7735 isl_map_free(map1);
7736 isl_map_free(map2);
7737 return NULL;
7740 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7741 * guaranteed to be disjoint by the caller.
7743 * Note that this functions is called from within isl_map_make_disjoint,
7744 * so we have to be careful not to touch the constraints of the inputs
7745 * in any way.
7747 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7748 __isl_take isl_map *map2)
7750 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7753 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7754 * not be disjoint. The parameters are assumed to have been aligned.
7756 * We currently simply call map_union_disjoint, the internal operation
7757 * of which does not really depend on the inputs being disjoint.
7758 * If the result contains more than one basic map, then we clear
7759 * the disjoint flag since the result may contain basic maps from
7760 * both inputs and these are not guaranteed to be disjoint.
7762 * As a special case, if "map1" and "map2" are obviously equal,
7763 * then we simply return "map1".
7765 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7766 __isl_take isl_map *map2)
7768 int equal;
7770 if (!map1 || !map2)
7771 goto error;
7773 equal = isl_map_plain_is_equal(map1, map2);
7774 if (equal < 0)
7775 goto error;
7776 if (equal) {
7777 isl_map_free(map2);
7778 return map1;
7781 map1 = map_union_disjoint(map1, map2);
7782 if (!map1)
7783 return NULL;
7784 if (map1->n > 1)
7785 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7786 return map1;
7787 error:
7788 isl_map_free(map1);
7789 isl_map_free(map2);
7790 return NULL;
7793 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7794 * not be disjoint.
7796 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7797 __isl_take isl_map *map2)
7799 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7802 __isl_give isl_set *isl_set_union_disjoint(
7803 __isl_take isl_set *set1, __isl_take isl_set *set2)
7805 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7806 set_to_map(set2)));
7809 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7811 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7814 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7815 * the results.
7817 * "map" and "set" are assumed to be compatible and non-NULL.
7819 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7820 __isl_take isl_set *set,
7821 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7822 __isl_take isl_basic_set *bset))
7824 unsigned flags = 0;
7825 struct isl_map *result;
7826 int i, j;
7828 if (isl_set_plain_is_universe(set)) {
7829 isl_set_free(set);
7830 return map;
7833 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7834 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7835 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7837 result = isl_map_alloc_space(isl_space_copy(map->dim),
7838 map->n * set->n, flags);
7839 for (i = 0; result && i < map->n; ++i)
7840 for (j = 0; j < set->n; ++j) {
7841 result = isl_map_add_basic_map(result,
7842 fn(isl_basic_map_copy(map->p[i]),
7843 isl_basic_set_copy(set->p[j])));
7844 if (!result)
7845 break;
7848 isl_map_free(map);
7849 isl_set_free(set);
7850 return result;
7853 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7854 __isl_take isl_set *set)
7856 isl_bool ok;
7858 ok = isl_map_compatible_range(map, set);
7859 if (ok < 0)
7860 goto error;
7861 if (!ok)
7862 isl_die(set->ctx, isl_error_invalid,
7863 "incompatible spaces", goto error);
7865 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7866 error:
7867 isl_map_free(map);
7868 isl_set_free(set);
7869 return NULL;
7872 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7873 __isl_take isl_set *set)
7875 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7878 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7879 __isl_take isl_set *set)
7881 isl_bool ok;
7883 ok = isl_map_compatible_domain(map, set);
7884 if (ok < 0)
7885 goto error;
7886 if (!ok)
7887 isl_die(set->ctx, isl_error_invalid,
7888 "incompatible spaces", goto error);
7890 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7891 error:
7892 isl_map_free(map);
7893 isl_set_free(set);
7894 return NULL;
7897 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7898 __isl_take isl_set *set)
7900 return isl_map_align_params_map_map_and(map, set,
7901 &map_intersect_domain);
7904 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7905 * in the space B -> C, return the intersection.
7906 * The parameters are assumed to have been aligned.
7908 * The map "factor" is first extended to a map living in the space
7909 * [A -> B] -> C and then a regular intersection is computed.
7911 static __isl_give isl_map *map_intersect_domain_factor_range(
7912 __isl_take isl_map *map, __isl_take isl_map *factor)
7914 isl_space *space;
7915 isl_map *ext_factor;
7917 space = isl_space_domain_factor_domain(isl_map_get_space(map));
7918 ext_factor = isl_map_universe(space);
7919 ext_factor = isl_map_domain_product(ext_factor, factor);
7920 return map_intersect(map, ext_factor);
7923 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7924 * in the space B -> C, return the intersection.
7926 __isl_give isl_map *isl_map_intersect_domain_factor_range(
7927 __isl_take isl_map *map, __isl_take isl_map *factor)
7929 return isl_map_align_params_map_map_and(map, factor,
7930 &map_intersect_domain_factor_range);
7933 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7934 * in the space A -> C, return the intersection.
7936 * The map "factor" is first extended to a map living in the space
7937 * A -> [B -> C] and then a regular intersection is computed.
7939 static __isl_give isl_map *map_intersect_range_factor_range(
7940 __isl_take isl_map *map, __isl_take isl_map *factor)
7942 isl_space *space;
7943 isl_map *ext_factor;
7945 space = isl_space_range_factor_domain(isl_map_get_space(map));
7946 ext_factor = isl_map_universe(space);
7947 ext_factor = isl_map_range_product(ext_factor, factor);
7948 return isl_map_intersect(map, ext_factor);
7951 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7952 * in the space A -> C, return the intersection.
7954 __isl_give isl_map *isl_map_intersect_range_factor_range(
7955 __isl_take isl_map *map, __isl_take isl_map *factor)
7957 return isl_map_align_params_map_map_and(map, factor,
7958 &map_intersect_range_factor_range);
7961 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7962 __isl_take isl_map *map2)
7964 if (!map1 || !map2)
7965 goto error;
7966 map1 = isl_map_reverse(map1);
7967 map1 = isl_map_apply_range(map1, map2);
7968 return isl_map_reverse(map1);
7969 error:
7970 isl_map_free(map1);
7971 isl_map_free(map2);
7972 return NULL;
7975 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7976 __isl_take isl_map *map2)
7978 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7981 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7982 __isl_take isl_map *map2)
7984 isl_space *space;
7985 struct isl_map *result;
7986 int i, j;
7988 if (!map1 || !map2)
7989 goto error;
7991 space = isl_space_join(isl_space_copy(map1->dim),
7992 isl_space_copy(map2->dim));
7994 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
7995 if (!result)
7996 goto error;
7997 for (i = 0; i < map1->n; ++i)
7998 for (j = 0; j < map2->n; ++j) {
7999 result = isl_map_add_basic_map(result,
8000 isl_basic_map_apply_range(
8001 isl_basic_map_copy(map1->p[i]),
8002 isl_basic_map_copy(map2->p[j])));
8003 if (!result)
8004 goto error;
8006 isl_map_free(map1);
8007 isl_map_free(map2);
8008 if (result && result->n <= 1)
8009 ISL_F_SET(result, ISL_MAP_DISJOINT);
8010 return result;
8011 error:
8012 isl_map_free(map1);
8013 isl_map_free(map2);
8014 return NULL;
8017 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8018 __isl_take isl_map *map2)
8020 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
8024 * returns range - domain
8026 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8028 isl_space *target_space;
8029 struct isl_basic_set *bset;
8030 unsigned dim;
8031 unsigned nparam;
8032 int i;
8034 if (!bmap)
8035 goto error;
8036 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8037 bmap->dim, isl_dim_out),
8038 goto error);
8039 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8040 dim = isl_basic_map_dim(bmap, isl_dim_in);
8041 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8042 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8043 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8044 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8045 for (i = 0; i < dim; ++i) {
8046 int j = isl_basic_map_alloc_equality(bmap);
8047 if (j < 0) {
8048 bmap = isl_basic_map_free(bmap);
8049 break;
8051 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
8052 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8053 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8054 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8056 bset = isl_basic_map_domain(bmap);
8057 bset = isl_basic_set_reset_space(bset, target_space);
8058 return bset;
8059 error:
8060 isl_basic_map_free(bmap);
8061 return NULL;
8065 * returns range - domain
8067 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8069 int i;
8070 isl_space *dim;
8071 struct isl_set *result;
8073 if (!map)
8074 return NULL;
8076 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
8077 map->dim, isl_dim_out),
8078 goto error);
8079 dim = isl_map_get_space(map);
8080 dim = isl_space_domain(dim);
8081 result = isl_set_alloc_space(dim, map->n, 0);
8082 if (!result)
8083 goto error;
8084 for (i = 0; i < map->n; ++i)
8085 result = isl_set_add_basic_set(result,
8086 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8087 isl_map_free(map);
8088 return result;
8089 error:
8090 isl_map_free(map);
8091 return NULL;
8095 * returns [domain -> range] -> range - domain
8097 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8098 __isl_take isl_basic_map *bmap)
8100 int i, k;
8101 isl_space *space;
8102 isl_basic_map *domain;
8103 int nparam, n;
8104 unsigned total;
8106 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8107 bmap->dim, isl_dim_out))
8108 isl_die(bmap->ctx, isl_error_invalid,
8109 "domain and range don't match", goto error);
8111 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8112 n = isl_basic_map_dim(bmap, isl_dim_in);
8114 space = isl_basic_map_get_space(bmap);
8115 space = isl_space_from_range(isl_space_domain(space));
8116 domain = isl_basic_map_universe(space);
8118 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8119 bmap = isl_basic_map_apply_range(bmap, domain);
8120 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8122 total = isl_basic_map_total_dim(bmap);
8124 for (i = 0; i < n; ++i) {
8125 k = isl_basic_map_alloc_equality(bmap);
8126 if (k < 0)
8127 goto error;
8128 isl_seq_clr(bmap->eq[k], 1 + total);
8129 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8130 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8131 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8134 bmap = isl_basic_map_gauss(bmap, NULL);
8135 return isl_basic_map_finalize(bmap);
8136 error:
8137 isl_basic_map_free(bmap);
8138 return NULL;
8142 * returns [domain -> range] -> range - domain
8144 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8146 int i;
8147 isl_space *domain_space;
8149 if (!map)
8150 return NULL;
8152 if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
8153 map->dim, isl_dim_out))
8154 isl_die(map->ctx, isl_error_invalid,
8155 "domain and range don't match", goto error);
8157 map = isl_map_cow(map);
8158 if (!map)
8159 return NULL;
8161 domain_space = isl_space_domain(isl_map_get_space(map));
8162 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
8163 map->dim = isl_space_join(map->dim, isl_space_from_range(domain_space));
8164 if (!map->dim)
8165 goto error;
8166 for (i = 0; i < map->n; ++i) {
8167 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
8168 if (!map->p[i])
8169 goto error;
8171 map = isl_map_unmark_normalized(map);
8172 return map;
8173 error:
8174 isl_map_free(map);
8175 return NULL;
8178 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8180 unsigned n_in, n_out;
8182 if (!space)
8183 return NULL;
8184 n_in = isl_space_dim(space, isl_dim_in);
8185 n_out = isl_space_dim(space, isl_dim_out);
8186 if (n_in != n_out)
8187 isl_die(space->ctx, isl_error_invalid,
8188 "number of input and output dimensions needs to be "
8189 "the same", goto error);
8190 return isl_basic_map_equal(space, n_in);
8191 error:
8192 isl_space_free(space);
8193 return NULL;
8196 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
8198 return isl_map_from_basic_map(isl_basic_map_identity(dim));
8201 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8203 isl_space *dim = isl_set_get_space(set);
8204 isl_map *id;
8205 id = isl_map_identity(isl_space_map_from_set(dim));
8206 return isl_map_intersect_range(id, set);
8209 /* Construct a basic set with all set dimensions having only non-negative
8210 * values.
8212 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8213 __isl_take isl_space *space)
8215 int i;
8216 unsigned nparam;
8217 unsigned dim;
8218 struct isl_basic_set *bset;
8220 if (!space)
8221 return NULL;
8222 nparam = space->nparam;
8223 dim = space->n_out;
8224 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8225 if (!bset)
8226 return NULL;
8227 for (i = 0; i < dim; ++i) {
8228 int k = isl_basic_set_alloc_inequality(bset);
8229 if (k < 0)
8230 goto error;
8231 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
8232 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8234 return bset;
8235 error:
8236 isl_basic_set_free(bset);
8237 return NULL;
8240 /* Construct the half-space x_pos >= 0.
8242 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8243 int pos)
8245 int k;
8246 isl_basic_set *nonneg;
8248 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8249 k = isl_basic_set_alloc_inequality(nonneg);
8250 if (k < 0)
8251 goto error;
8252 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
8253 isl_int_set_si(nonneg->ineq[k][pos], 1);
8255 return isl_basic_set_finalize(nonneg);
8256 error:
8257 isl_basic_set_free(nonneg);
8258 return NULL;
8261 /* Construct the half-space x_pos <= -1.
8263 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8264 int pos)
8266 int k;
8267 isl_basic_set *neg;
8269 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8270 k = isl_basic_set_alloc_inequality(neg);
8271 if (k < 0)
8272 goto error;
8273 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
8274 isl_int_set_si(neg->ineq[k][0], -1);
8275 isl_int_set_si(neg->ineq[k][pos], -1);
8277 return isl_basic_set_finalize(neg);
8278 error:
8279 isl_basic_set_free(neg);
8280 return NULL;
8283 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8284 enum isl_dim_type type, unsigned first, unsigned n)
8286 int i;
8287 unsigned offset;
8288 isl_basic_set *nonneg;
8289 isl_basic_set *neg;
8291 if (!set)
8292 return NULL;
8293 if (n == 0)
8294 return set;
8296 isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
8298 offset = pos(set->dim, type);
8299 for (i = 0; i < n; ++i) {
8300 nonneg = nonneg_halfspace(isl_set_get_space(set),
8301 offset + first + i);
8302 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8304 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8307 return set;
8308 error:
8309 isl_set_free(set);
8310 return NULL;
8313 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8314 int len,
8315 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8316 void *user)
8318 isl_set *half;
8320 if (!set)
8321 return isl_stat_error;
8322 if (isl_set_plain_is_empty(set)) {
8323 isl_set_free(set);
8324 return isl_stat_ok;
8326 if (first == len)
8327 return fn(set, signs, user);
8329 signs[first] = 1;
8330 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8331 1 + first));
8332 half = isl_set_intersect(half, isl_set_copy(set));
8333 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8334 goto error;
8336 signs[first] = -1;
8337 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8338 1 + first));
8339 half = isl_set_intersect(half, set);
8340 return foreach_orthant(half, signs, first + 1, len, fn, user);
8341 error:
8342 isl_set_free(set);
8343 return isl_stat_error;
8346 /* Call "fn" on the intersections of "set" with each of the orthants
8347 * (except for obviously empty intersections). The orthant is identified
8348 * by the signs array, with each entry having value 1 or -1 according
8349 * to the sign of the corresponding variable.
8351 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8352 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8353 void *user)
8355 unsigned nparam;
8356 unsigned nvar;
8357 int *signs;
8358 isl_stat r;
8360 if (!set)
8361 return isl_stat_error;
8362 if (isl_set_plain_is_empty(set))
8363 return isl_stat_ok;
8365 nparam = isl_set_dim(set, isl_dim_param);
8366 nvar = isl_set_dim(set, isl_dim_set);
8368 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8370 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8371 fn, user);
8373 free(signs);
8375 return r;
8378 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8380 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8383 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8384 __isl_keep isl_basic_map *bmap2)
8386 isl_bool is_subset;
8387 struct isl_map *map1;
8388 struct isl_map *map2;
8390 if (!bmap1 || !bmap2)
8391 return isl_bool_error;
8393 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8394 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8396 is_subset = isl_map_is_subset(map1, map2);
8398 isl_map_free(map1);
8399 isl_map_free(map2);
8401 return is_subset;
8404 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8405 __isl_keep isl_basic_set *bset2)
8407 return isl_basic_map_is_subset(bset1, bset2);
8410 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8411 __isl_keep isl_basic_map *bmap2)
8413 isl_bool is_subset;
8415 if (!bmap1 || !bmap2)
8416 return isl_bool_error;
8417 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8418 if (is_subset != isl_bool_true)
8419 return is_subset;
8420 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8421 return is_subset;
8424 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8425 __isl_keep isl_basic_set *bset2)
8427 return isl_basic_map_is_equal(
8428 bset_to_bmap(bset1), bset_to_bmap(bset2));
8431 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8433 int i;
8434 int is_empty;
8436 if (!map)
8437 return isl_bool_error;
8438 for (i = 0; i < map->n; ++i) {
8439 is_empty = isl_basic_map_is_empty(map->p[i]);
8440 if (is_empty < 0)
8441 return isl_bool_error;
8442 if (!is_empty)
8443 return isl_bool_false;
8445 return isl_bool_true;
8448 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8450 return map ? map->n == 0 : isl_bool_error;
8453 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8455 return set ? set->n == 0 : isl_bool_error;
8458 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8460 return isl_map_is_empty(set_to_map(set));
8463 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
8464 __isl_keep isl_map *map2)
8466 if (!map1 || !map2)
8467 return isl_bool_error;
8469 return isl_space_is_equal(map1->dim, map2->dim);
8472 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
8473 __isl_keep isl_set *set2)
8475 if (!set1 || !set2)
8476 return isl_bool_error;
8478 return isl_space_is_equal(set1->dim, set2->dim);
8481 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8483 isl_bool is_subset;
8485 if (!map1 || !map2)
8486 return isl_bool_error;
8487 is_subset = isl_map_is_subset(map1, map2);
8488 if (is_subset != isl_bool_true)
8489 return is_subset;
8490 is_subset = isl_map_is_subset(map2, map1);
8491 return is_subset;
8494 /* Is "map1" equal to "map2"?
8496 * First check if they are obviously equal.
8497 * If not, then perform a more detailed analysis.
8499 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8501 isl_bool equal;
8503 equal = isl_map_plain_is_equal(map1, map2);
8504 if (equal < 0 || equal)
8505 return equal;
8506 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8509 isl_bool isl_basic_map_is_strict_subset(
8510 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8512 isl_bool is_subset;
8514 if (!bmap1 || !bmap2)
8515 return isl_bool_error;
8516 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8517 if (is_subset != isl_bool_true)
8518 return is_subset;
8519 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8520 return isl_bool_not(is_subset);
8523 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8524 __isl_keep isl_map *map2)
8526 isl_bool is_subset;
8528 if (!map1 || !map2)
8529 return isl_bool_error;
8530 is_subset = isl_map_is_subset(map1, map2);
8531 if (is_subset != isl_bool_true)
8532 return is_subset;
8533 is_subset = isl_map_is_subset(map2, map1);
8534 return isl_bool_not(is_subset);
8537 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8538 __isl_keep isl_set *set2)
8540 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8543 /* Is "bmap" obviously equal to the universe with the same space?
8545 * That is, does it not have any constraints?
8547 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8549 if (!bmap)
8550 return isl_bool_error;
8551 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8554 /* Is "bset" obviously equal to the universe with the same space?
8556 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8558 return isl_basic_map_plain_is_universe(bset);
8561 /* If "c" does not involve any existentially quantified variables,
8562 * then set *univ to false and abort
8564 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8566 isl_bool *univ = user;
8567 unsigned n;
8569 n = isl_constraint_dim(c, isl_dim_div);
8570 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8571 isl_constraint_free(c);
8572 if (*univ < 0 || !*univ)
8573 return isl_stat_error;
8574 return isl_stat_ok;
8577 /* Is "bmap" equal to the universe with the same space?
8579 * First check if it is obviously equal to the universe.
8580 * If not and if there are any constraints not involving
8581 * existentially quantified variables, then it is certainly
8582 * not equal to the universe.
8583 * Otherwise, check if the universe is a subset of "bmap".
8585 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8587 isl_bool univ;
8588 isl_basic_map *test;
8590 univ = isl_basic_map_plain_is_universe(bmap);
8591 if (univ < 0 || univ)
8592 return univ;
8593 if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8594 return isl_bool_false;
8595 univ = isl_bool_true;
8596 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8597 univ)
8598 return isl_bool_error;
8599 if (univ < 0 || !univ)
8600 return univ;
8601 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8602 univ = isl_basic_map_is_subset(test, bmap);
8603 isl_basic_map_free(test);
8604 return univ;
8607 /* Is "bset" equal to the universe with the same space?
8609 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8611 return isl_basic_map_is_universe(bset);
8614 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8616 int i;
8618 if (!map)
8619 return isl_bool_error;
8621 for (i = 0; i < map->n; ++i) {
8622 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8623 if (r < 0 || r)
8624 return r;
8627 return isl_bool_false;
8630 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8632 return isl_map_plain_is_universe(set_to_map(set));
8635 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8637 struct isl_basic_set *bset = NULL;
8638 struct isl_vec *sample = NULL;
8639 isl_bool empty, non_empty;
8641 if (!bmap)
8642 return isl_bool_error;
8644 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8645 return isl_bool_true;
8647 if (isl_basic_map_plain_is_universe(bmap))
8648 return isl_bool_false;
8650 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8651 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8652 copy = isl_basic_map_remove_redundancies(copy);
8653 empty = isl_basic_map_plain_is_empty(copy);
8654 isl_basic_map_free(copy);
8655 return empty;
8658 non_empty = isl_basic_map_plain_is_non_empty(bmap);
8659 if (non_empty < 0)
8660 return isl_bool_error;
8661 if (non_empty)
8662 return isl_bool_false;
8663 isl_vec_free(bmap->sample);
8664 bmap->sample = NULL;
8665 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8666 if (!bset)
8667 return isl_bool_error;
8668 sample = isl_basic_set_sample_vec(bset);
8669 if (!sample)
8670 return isl_bool_error;
8671 empty = sample->size == 0;
8672 isl_vec_free(bmap->sample);
8673 bmap->sample = sample;
8674 if (empty)
8675 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8677 return empty;
8680 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8682 if (!bmap)
8683 return isl_bool_error;
8684 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8687 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8689 if (!bset)
8690 return isl_bool_error;
8691 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8694 /* Is "bmap" known to be non-empty?
8696 * That is, is the cached sample still valid?
8698 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8700 unsigned total;
8702 if (!bmap)
8703 return isl_bool_error;
8704 if (!bmap->sample)
8705 return isl_bool_false;
8706 total = 1 + isl_basic_map_total_dim(bmap);
8707 if (bmap->sample->size != total)
8708 return isl_bool_false;
8709 return isl_basic_map_contains(bmap, bmap->sample);
8712 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8714 return isl_basic_map_is_empty(bset_to_bmap(bset));
8717 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
8718 __isl_take isl_basic_map *bmap2)
8720 struct isl_map *map;
8721 if (!bmap1 || !bmap2)
8722 goto error;
8724 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8726 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8727 if (!map)
8728 goto error;
8729 map = isl_map_add_basic_map(map, bmap1);
8730 map = isl_map_add_basic_map(map, bmap2);
8731 return map;
8732 error:
8733 isl_basic_map_free(bmap1);
8734 isl_basic_map_free(bmap2);
8735 return NULL;
8738 struct isl_set *isl_basic_set_union(
8739 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8741 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8742 bset_to_bmap(bset2)));
8745 /* Order divs such that any div only depends on previous divs */
8746 __isl_give isl_basic_map *isl_basic_map_order_divs(
8747 __isl_take isl_basic_map *bmap)
8749 int i;
8750 unsigned off;
8752 if (!bmap)
8753 return NULL;
8755 off = isl_space_dim(bmap->dim, isl_dim_all);
8757 for (i = 0; i < bmap->n_div; ++i) {
8758 int pos;
8759 if (isl_int_is_zero(bmap->div[i][0]))
8760 continue;
8761 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8762 bmap->n_div-i);
8763 if (pos == -1)
8764 continue;
8765 if (pos == 0)
8766 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8767 "integer division depends on itself",
8768 return isl_basic_map_free(bmap));
8769 isl_basic_map_swap_div(bmap, i, i + pos);
8770 --i;
8772 return bmap;
8775 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8777 return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8780 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8782 int i;
8784 if (!map)
8785 return 0;
8787 for (i = 0; i < map->n; ++i) {
8788 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8789 if (!map->p[i])
8790 goto error;
8793 return map;
8794 error:
8795 isl_map_free(map);
8796 return NULL;
8799 /* Sort the local variables of "bset".
8801 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8802 __isl_take isl_basic_set *bset)
8804 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8807 /* Apply the expansion computed by isl_merge_divs.
8808 * The expansion itself is given by "exp" while the resulting
8809 * list of divs is given by "div".
8811 * Move the integer divisions of "bmap" into the right position
8812 * according to "exp" and then introduce the additional integer
8813 * divisions, adding div constraints.
8814 * The moving should be done first to avoid moving coefficients
8815 * in the definitions of the extra integer divisions.
8817 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8818 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8820 int i, j;
8821 int n_div;
8823 bmap = isl_basic_map_cow(bmap);
8824 if (!bmap || !div)
8825 goto error;
8827 if (div->n_row < bmap->n_div)
8828 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8829 "not an expansion", goto error);
8831 n_div = bmap->n_div;
8832 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8833 div->n_row - n_div, 0,
8834 2 * (div->n_row - n_div));
8836 for (i = n_div; i < div->n_row; ++i)
8837 if (isl_basic_map_alloc_div(bmap) < 0)
8838 goto error;
8840 for (j = n_div - 1; j >= 0; --j) {
8841 if (exp[j] == j)
8842 break;
8843 isl_basic_map_swap_div(bmap, j, exp[j]);
8845 j = 0;
8846 for (i = 0; i < div->n_row; ++i) {
8847 if (j < n_div && exp[j] == i) {
8848 j++;
8849 } else {
8850 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8851 if (isl_basic_map_div_is_marked_unknown(bmap, i))
8852 continue;
8853 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
8854 goto error;
8858 isl_mat_free(div);
8859 return bmap;
8860 error:
8861 isl_basic_map_free(bmap);
8862 isl_mat_free(div);
8863 return NULL;
8866 /* Apply the expansion computed by isl_merge_divs.
8867 * The expansion itself is given by "exp" while the resulting
8868 * list of divs is given by "div".
8870 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8871 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8873 return isl_basic_map_expand_divs(bset, div, exp);
8876 /* Look for a div in dst that corresponds to the div "div" in src.
8877 * The divs before "div" in src and dst are assumed to be the same.
8879 * Returns -1 if no corresponding div was found and the position
8880 * of the corresponding div in dst otherwise.
8882 static int find_div(__isl_keep isl_basic_map *dst,
8883 __isl_keep isl_basic_map *src, unsigned div)
8885 int i;
8887 unsigned total = isl_space_dim(src->dim, isl_dim_all);
8889 isl_assert(dst->ctx, div <= dst->n_div, return -1);
8890 for (i = div; i < dst->n_div; ++i)
8891 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8892 isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8893 dst->n_div - div) == -1)
8894 return i;
8895 return -1;
8898 /* Align the divs of "dst" to those of "src", adding divs from "src"
8899 * if needed. That is, make sure that the first src->n_div divs
8900 * of the result are equal to those of src.
8902 * The result is not finalized as by design it will have redundant
8903 * divs if any divs from "src" were copied.
8905 __isl_give isl_basic_map *isl_basic_map_align_divs(
8906 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8908 int i;
8909 isl_bool known;
8910 int extended;
8911 unsigned total;
8913 if (!dst || !src)
8914 return isl_basic_map_free(dst);
8916 if (src->n_div == 0)
8917 return dst;
8919 known = isl_basic_map_divs_known(src);
8920 if (known < 0)
8921 return isl_basic_map_free(dst);
8922 if (!known)
8923 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8924 "some src divs are unknown",
8925 return isl_basic_map_free(dst));
8927 src = isl_basic_map_order_divs(isl_basic_map_copy(src));
8928 if (!src)
8929 return isl_basic_map_free(dst);
8931 extended = 0;
8932 total = isl_space_dim(src->dim, isl_dim_all);
8933 for (i = 0; i < src->n_div; ++i) {
8934 int j = find_div(dst, src, i);
8935 if (j < 0) {
8936 if (!extended) {
8937 int extra = src->n_div - i;
8938 dst = isl_basic_map_cow(dst);
8939 if (!dst)
8940 goto error;
8941 dst = isl_basic_map_extend_space(dst,
8942 isl_space_copy(dst->dim),
8943 extra, 0, 2 * extra);
8944 extended = 1;
8946 j = isl_basic_map_alloc_div(dst);
8947 if (j < 0)
8948 goto error;
8949 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8950 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8951 if (isl_basic_map_add_div_constraints(dst, j) < 0)
8952 goto error;
8954 if (j != i)
8955 isl_basic_map_swap_div(dst, i, j);
8957 isl_basic_map_free(src);
8958 return dst;
8959 error:
8960 isl_basic_map_free(src);
8961 isl_basic_map_free(dst);
8962 return NULL;
8965 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
8967 int i;
8969 if (!map)
8970 return NULL;
8971 if (map->n == 0)
8972 return map;
8973 map = isl_map_compute_divs(map);
8974 map = isl_map_cow(map);
8975 if (!map)
8976 return NULL;
8978 for (i = 1; i < map->n; ++i)
8979 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8980 for (i = 1; i < map->n; ++i) {
8981 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8982 if (!map->p[i])
8983 return isl_map_free(map);
8986 map = isl_map_unmark_normalized(map);
8987 return map;
8990 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
8992 return isl_map_align_divs_internal(map);
8995 struct isl_set *isl_set_align_divs(struct isl_set *set)
8997 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9000 /* Align the divs of the basic maps in "map" to those
9001 * of the basic maps in "list", as well as to the other basic maps in "map".
9002 * The elements in "list" are assumed to have known divs.
9004 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9005 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9007 int i, n;
9009 map = isl_map_compute_divs(map);
9010 map = isl_map_cow(map);
9011 if (!map || !list)
9012 return isl_map_free(map);
9013 if (map->n == 0)
9014 return map;
9016 n = isl_basic_map_list_n_basic_map(list);
9017 for (i = 0; i < n; ++i) {
9018 isl_basic_map *bmap;
9020 bmap = isl_basic_map_list_get_basic_map(list, i);
9021 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9022 isl_basic_map_free(bmap);
9024 if (!map->p[0])
9025 return isl_map_free(map);
9027 return isl_map_align_divs_internal(map);
9030 /* Align the divs of each element of "list" to those of "bmap".
9031 * Both "bmap" and the elements of "list" are assumed to have known divs.
9033 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9034 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9036 int i, n;
9038 if (!list || !bmap)
9039 return isl_basic_map_list_free(list);
9041 n = isl_basic_map_list_n_basic_map(list);
9042 for (i = 0; i < n; ++i) {
9043 isl_basic_map *bmap_i;
9045 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9046 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9047 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9050 return list;
9053 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
9054 __isl_take isl_map *map)
9056 isl_bool ok;
9058 ok = isl_map_compatible_domain(map, set);
9059 if (ok < 0)
9060 goto error;
9061 if (!ok)
9062 isl_die(isl_set_get_ctx(set), isl_error_invalid,
9063 "incompatible spaces", goto error);
9064 map = isl_map_intersect_domain(map, set);
9065 set = isl_map_range(map);
9066 return set;
9067 error:
9068 isl_set_free(set);
9069 isl_map_free(map);
9070 return NULL;
9073 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9074 __isl_take isl_map *map)
9076 return isl_map_align_params_map_map_and(set, map, &set_apply);
9079 /* There is no need to cow as removing empty parts doesn't change
9080 * the meaning of the set.
9082 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9084 int i;
9086 if (!map)
9087 return NULL;
9089 for (i = map->n - 1; i >= 0; --i)
9090 map = remove_if_empty(map, i);
9092 return map;
9095 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
9097 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9100 /* Create a binary relation that maps the shared initial "pos" dimensions
9101 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9103 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9104 __isl_keep isl_basic_set *bset2, int pos)
9106 isl_basic_map *bmap1;
9107 isl_basic_map *bmap2;
9109 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9110 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9111 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9112 isl_dim_out, 0, pos);
9113 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9114 isl_dim_out, 0, pos);
9115 return isl_basic_map_range_product(bmap1, bmap2);
9118 /* Given two basic sets bset1 and bset2, compute the maximal difference
9119 * between the values of dimension pos in bset1 and those in bset2
9120 * for any common value of the parameters and dimensions preceding pos.
9122 static enum isl_lp_result basic_set_maximal_difference_at(
9123 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9124 int pos, isl_int *opt)
9126 isl_basic_map *bmap1;
9127 struct isl_ctx *ctx;
9128 struct isl_vec *obj;
9129 unsigned total;
9130 unsigned nparam;
9131 unsigned dim1;
9132 enum isl_lp_result res;
9134 if (!bset1 || !bset2)
9135 return isl_lp_error;
9137 nparam = isl_basic_set_n_param(bset1);
9138 dim1 = isl_basic_set_n_dim(bset1);
9140 bmap1 = join_initial(bset1, bset2, pos);
9141 if (!bmap1)
9142 return isl_lp_error;
9144 total = isl_basic_map_total_dim(bmap1);
9145 ctx = bmap1->ctx;
9146 obj = isl_vec_alloc(ctx, 1 + total);
9147 if (!obj)
9148 goto error;
9149 isl_seq_clr(obj->block.data, 1 + total);
9150 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9151 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9152 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9153 opt, NULL, NULL);
9154 isl_basic_map_free(bmap1);
9155 isl_vec_free(obj);
9156 return res;
9157 error:
9158 isl_basic_map_free(bmap1);
9159 return isl_lp_error;
9162 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9163 * for any common value of the parameters and dimensions preceding pos
9164 * in both basic sets, the values of dimension pos in bset1 are
9165 * smaller or larger than those in bset2.
9167 * Returns
9168 * 1 if bset1 follows bset2
9169 * -1 if bset1 precedes bset2
9170 * 0 if bset1 and bset2 are incomparable
9171 * -2 if some error occurred.
9173 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9174 __isl_keep isl_basic_set *bset2, int pos)
9176 isl_int opt;
9177 enum isl_lp_result res;
9178 int cmp;
9180 isl_int_init(opt);
9182 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9184 if (res == isl_lp_empty)
9185 cmp = 0;
9186 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9187 res == isl_lp_unbounded)
9188 cmp = 1;
9189 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9190 cmp = -1;
9191 else
9192 cmp = -2;
9194 isl_int_clear(opt);
9195 return cmp;
9198 /* Given two basic sets bset1 and bset2, check whether
9199 * for any common value of the parameters and dimensions preceding pos
9200 * there is a value of dimension pos in bset1 that is larger
9201 * than a value of the same dimension in bset2.
9203 * Return
9204 * 1 if there exists such a pair
9205 * 0 if there is no such pair, but there is a pair of equal values
9206 * -1 otherwise
9207 * -2 if some error occurred.
9209 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9210 __isl_keep isl_basic_set *bset2, int pos)
9212 isl_bool empty;
9213 isl_basic_map *bmap;
9214 unsigned dim1;
9216 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9217 bmap = join_initial(bset1, bset2, pos);
9218 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9219 isl_dim_out, dim1 - pos);
9220 empty = isl_basic_map_is_empty(bmap);
9221 if (empty < 0)
9222 goto error;
9223 if (empty) {
9224 isl_basic_map_free(bmap);
9225 return -1;
9227 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9228 isl_dim_out, dim1 - pos);
9229 empty = isl_basic_map_is_empty(bmap);
9230 if (empty < 0)
9231 goto error;
9232 isl_basic_map_free(bmap);
9233 if (empty)
9234 return 0;
9235 return 1;
9236 error:
9237 isl_basic_map_free(bmap);
9238 return -2;
9241 /* Given two sets set1 and set2, check whether
9242 * for any common value of the parameters and dimensions preceding pos
9243 * there is a value of dimension pos in set1 that is larger
9244 * than a value of the same dimension in set2.
9246 * Return
9247 * 1 if there exists such a pair
9248 * 0 if there is no such pair, but there is a pair of equal values
9249 * -1 otherwise
9250 * -2 if some error occurred.
9252 int isl_set_follows_at(__isl_keep isl_set *set1,
9253 __isl_keep isl_set *set2, int pos)
9255 int i, j;
9256 int follows = -1;
9258 if (!set1 || !set2)
9259 return -2;
9261 for (i = 0; i < set1->n; ++i)
9262 for (j = 0; j < set2->n; ++j) {
9263 int f;
9264 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9265 if (f == 1 || f == -2)
9266 return f;
9267 if (f > follows)
9268 follows = f;
9271 return follows;
9274 static isl_bool isl_basic_map_plain_has_fixed_var(
9275 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9277 int i;
9278 int d;
9279 unsigned total;
9281 if (!bmap)
9282 return isl_bool_error;
9283 total = isl_basic_map_total_dim(bmap);
9284 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9285 for (; d+1 > pos; --d)
9286 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9287 break;
9288 if (d != pos)
9289 continue;
9290 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9291 return isl_bool_false;
9292 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9293 return isl_bool_false;
9294 if (!isl_int_is_one(bmap->eq[i][1+d]))
9295 return isl_bool_false;
9296 if (val)
9297 isl_int_neg(*val, bmap->eq[i][0]);
9298 return isl_bool_true;
9300 return isl_bool_false;
9303 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9304 unsigned pos, isl_int *val)
9306 int i;
9307 isl_int v;
9308 isl_int tmp;
9309 isl_bool fixed;
9311 if (!map)
9312 return isl_bool_error;
9313 if (map->n == 0)
9314 return isl_bool_false;
9315 if (map->n == 1)
9316 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9317 isl_int_init(v);
9318 isl_int_init(tmp);
9319 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9320 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9321 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9322 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9323 fixed = isl_bool_false;
9325 if (val)
9326 isl_int_set(*val, v);
9327 isl_int_clear(tmp);
9328 isl_int_clear(v);
9329 return fixed;
9332 static isl_bool isl_basic_set_plain_has_fixed_var(
9333 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9335 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9336 pos, val);
9339 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9340 enum isl_dim_type type, unsigned pos, isl_int *val)
9342 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9343 return isl_bool_error;
9344 return isl_basic_map_plain_has_fixed_var(bmap,
9345 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9348 /* If "bmap" obviously lies on a hyperplane where the given dimension
9349 * has a fixed value, then return that value.
9350 * Otherwise return NaN.
9352 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9353 __isl_keep isl_basic_map *bmap,
9354 enum isl_dim_type type, unsigned pos)
9356 isl_ctx *ctx;
9357 isl_val *v;
9358 isl_bool fixed;
9360 if (!bmap)
9361 return NULL;
9362 ctx = isl_basic_map_get_ctx(bmap);
9363 v = isl_val_alloc(ctx);
9364 if (!v)
9365 return NULL;
9366 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9367 if (fixed < 0)
9368 return isl_val_free(v);
9369 if (fixed) {
9370 isl_int_set_si(v->d, 1);
9371 return v;
9373 isl_val_free(v);
9374 return isl_val_nan(ctx);
9377 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9378 enum isl_dim_type type, unsigned pos, isl_int *val)
9380 if (pos >= isl_map_dim(map, type))
9381 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9382 "position out of bounds", return isl_bool_error);
9383 return isl_map_plain_has_fixed_var(map,
9384 map_offset(map, type) - 1 + pos, val);
9387 /* If "map" obviously lies on a hyperplane where the given dimension
9388 * has a fixed value, then return that value.
9389 * Otherwise return NaN.
9391 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9392 enum isl_dim_type type, unsigned pos)
9394 isl_ctx *ctx;
9395 isl_val *v;
9396 isl_bool fixed;
9398 if (!map)
9399 return NULL;
9400 ctx = isl_map_get_ctx(map);
9401 v = isl_val_alloc(ctx);
9402 if (!v)
9403 return NULL;
9404 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9405 if (fixed < 0)
9406 return isl_val_free(v);
9407 if (fixed) {
9408 isl_int_set_si(v->d, 1);
9409 return v;
9411 isl_val_free(v);
9412 return isl_val_nan(ctx);
9415 /* If "set" obviously lies on a hyperplane where the given dimension
9416 * has a fixed value, then return that value.
9417 * Otherwise return NaN.
9419 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
9420 enum isl_dim_type type, unsigned pos)
9422 return isl_map_plain_get_val_if_fixed(set, type, pos);
9425 /* Check if dimension dim has fixed value and if so and if val is not NULL,
9426 * then return this fixed value in *val.
9428 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
9429 unsigned dim, isl_int *val)
9431 return isl_basic_set_plain_has_fixed_var(bset,
9432 isl_basic_set_n_param(bset) + dim, val);
9435 /* Return -1 if the constraint "c1" should be sorted before "c2"
9436 * and 1 if it should be sorted after "c2".
9437 * Return 0 if the two constraints are the same (up to the constant term).
9439 * In particular, if a constraint involves later variables than another
9440 * then it is sorted after this other constraint.
9441 * uset_gist depends on constraints without existentially quantified
9442 * variables sorting first.
9444 * For constraints that have the same latest variable, those
9445 * with the same coefficient for this latest variable (first in absolute value
9446 * and then in actual value) are grouped together.
9447 * This is useful for detecting pairs of constraints that can
9448 * be chained in their printed representation.
9450 * Finally, within a group, constraints are sorted according to
9451 * their coefficients (excluding the constant term).
9453 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9455 isl_int **c1 = (isl_int **) p1;
9456 isl_int **c2 = (isl_int **) p2;
9457 int l1, l2;
9458 unsigned size = *(unsigned *) arg;
9459 int cmp;
9461 l1 = isl_seq_last_non_zero(*c1 + 1, size);
9462 l2 = isl_seq_last_non_zero(*c2 + 1, size);
9464 if (l1 != l2)
9465 return l1 - l2;
9467 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9468 if (cmp != 0)
9469 return cmp;
9470 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9471 if (cmp != 0)
9472 return -cmp;
9474 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9477 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
9478 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
9479 * and 0 if the two constraints are the same (up to the constant term).
9481 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
9482 isl_int *c1, isl_int *c2)
9484 unsigned total;
9486 if (!bmap)
9487 return -2;
9488 total = isl_basic_map_total_dim(bmap);
9489 return sort_constraint_cmp(&c1, &c2, &total);
9492 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9493 __isl_take isl_basic_map *bmap)
9495 unsigned total;
9497 if (!bmap)
9498 return NULL;
9499 if (bmap->n_ineq == 0)
9500 return bmap;
9501 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
9502 return bmap;
9503 total = isl_basic_map_total_dim(bmap);
9504 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9505 &sort_constraint_cmp, &total) < 0)
9506 return isl_basic_map_free(bmap);
9507 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
9508 return bmap;
9511 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9512 __isl_take isl_basic_set *bset)
9514 isl_basic_map *bmap = bset_to_bmap(bset);
9515 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9518 __isl_give isl_basic_map *isl_basic_map_normalize(
9519 __isl_take isl_basic_map *bmap)
9521 bmap = isl_basic_map_remove_redundancies(bmap);
9522 bmap = isl_basic_map_sort_constraints(bmap);
9523 return bmap;
9525 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9526 __isl_keep isl_basic_map *bmap2)
9528 int i, cmp;
9529 unsigned total;
9530 isl_space *space1, *space2;
9532 if (!bmap1 || !bmap2)
9533 return -1;
9535 if (bmap1 == bmap2)
9536 return 0;
9537 space1 = isl_basic_map_peek_space(bmap1);
9538 space2 = isl_basic_map_peek_space(bmap2);
9539 cmp = isl_space_cmp(space1, space2);
9540 if (cmp)
9541 return cmp;
9542 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9543 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9544 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9545 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9546 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9547 return 0;
9548 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9549 return 1;
9550 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9551 return -1;
9552 if (bmap1->n_eq != bmap2->n_eq)
9553 return bmap1->n_eq - bmap2->n_eq;
9554 if (bmap1->n_ineq != bmap2->n_ineq)
9555 return bmap1->n_ineq - bmap2->n_ineq;
9556 if (bmap1->n_div != bmap2->n_div)
9557 return bmap1->n_div - bmap2->n_div;
9558 total = isl_basic_map_total_dim(bmap1);
9559 for (i = 0; i < bmap1->n_eq; ++i) {
9560 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9561 if (cmp)
9562 return cmp;
9564 for (i = 0; i < bmap1->n_ineq; ++i) {
9565 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9566 if (cmp)
9567 return cmp;
9569 for (i = 0; i < bmap1->n_div; ++i) {
9570 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9571 if (cmp)
9572 return cmp;
9574 return 0;
9577 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9578 __isl_keep isl_basic_set *bset2)
9580 return isl_basic_map_plain_cmp(bset1, bset2);
9583 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9585 int i, cmp;
9587 if (set1 == set2)
9588 return 0;
9589 if (set1->n != set2->n)
9590 return set1->n - set2->n;
9592 for (i = 0; i < set1->n; ++i) {
9593 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9594 if (cmp)
9595 return cmp;
9598 return 0;
9601 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9602 __isl_keep isl_basic_map *bmap2)
9604 if (!bmap1 || !bmap2)
9605 return isl_bool_error;
9606 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9609 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9610 __isl_keep isl_basic_set *bset2)
9612 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9613 bset_to_bmap(bset2));
9616 static int qsort_bmap_cmp(const void *p1, const void *p2)
9618 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9619 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9621 return isl_basic_map_plain_cmp(bmap1, bmap2);
9624 /* Sort the basic maps of "map" and remove duplicate basic maps.
9626 * While removing basic maps, we make sure that the basic maps remain
9627 * sorted because isl_map_normalize expects the basic maps of the result
9628 * to be sorted.
9630 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9632 int i, j;
9634 map = isl_map_remove_empty_parts(map);
9635 if (!map)
9636 return NULL;
9637 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9638 for (i = map->n - 1; i >= 1; --i) {
9639 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9640 continue;
9641 isl_basic_map_free(map->p[i-1]);
9642 for (j = i; j < map->n; ++j)
9643 map->p[j - 1] = map->p[j];
9644 map->n--;
9647 return map;
9650 /* Remove obvious duplicates among the basic maps of "map".
9652 * Unlike isl_map_normalize, this function does not remove redundant
9653 * constraints and only removes duplicates that have exactly the same
9654 * constraints in the input. It does sort the constraints and
9655 * the basic maps to ease the detection of duplicates.
9657 * If "map" has already been normalized or if the basic maps are
9658 * disjoint, then there can be no duplicates.
9660 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9662 int i;
9663 isl_basic_map *bmap;
9665 if (!map)
9666 return NULL;
9667 if (map->n <= 1)
9668 return map;
9669 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9670 return map;
9671 for (i = 0; i < map->n; ++i) {
9672 bmap = isl_basic_map_copy(map->p[i]);
9673 bmap = isl_basic_map_sort_constraints(bmap);
9674 if (!bmap)
9675 return isl_map_free(map);
9676 isl_basic_map_free(map->p[i]);
9677 map->p[i] = bmap;
9680 map = sort_and_remove_duplicates(map);
9681 return map;
9684 /* We normalize in place, but if anything goes wrong we need
9685 * to return NULL, so we need to make sure we don't change the
9686 * meaning of any possible other copies of map.
9688 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9690 int i;
9691 struct isl_basic_map *bmap;
9693 if (!map)
9694 return NULL;
9695 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9696 return map;
9697 for (i = 0; i < map->n; ++i) {
9698 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9699 if (!bmap)
9700 goto error;
9701 isl_basic_map_free(map->p[i]);
9702 map->p[i] = bmap;
9705 map = sort_and_remove_duplicates(map);
9706 if (map)
9707 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9708 return map;
9709 error:
9710 isl_map_free(map);
9711 return NULL;
9714 struct isl_set *isl_set_normalize(struct isl_set *set)
9716 return set_from_map(isl_map_normalize(set_to_map(set)));
9719 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9720 __isl_keep isl_map *map2)
9722 int i;
9723 isl_bool equal;
9725 if (!map1 || !map2)
9726 return isl_bool_error;
9728 if (map1 == map2)
9729 return isl_bool_true;
9730 if (!isl_space_is_equal(map1->dim, map2->dim))
9731 return isl_bool_false;
9733 map1 = isl_map_copy(map1);
9734 map2 = isl_map_copy(map2);
9735 map1 = isl_map_normalize(map1);
9736 map2 = isl_map_normalize(map2);
9737 if (!map1 || !map2)
9738 goto error;
9739 equal = map1->n == map2->n;
9740 for (i = 0; equal && i < map1->n; ++i) {
9741 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9742 if (equal < 0)
9743 goto error;
9745 isl_map_free(map1);
9746 isl_map_free(map2);
9747 return equal;
9748 error:
9749 isl_map_free(map1);
9750 isl_map_free(map2);
9751 return isl_bool_error;
9754 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9755 __isl_keep isl_set *set2)
9757 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9760 /* Return the basic maps in "map" as a list.
9762 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9763 __isl_keep isl_map *map)
9765 int i;
9766 isl_ctx *ctx;
9767 isl_basic_map_list *list;
9769 if (!map)
9770 return NULL;
9771 ctx = isl_map_get_ctx(map);
9772 list = isl_basic_map_list_alloc(ctx, map->n);
9774 for (i = 0; i < map->n; ++i) {
9775 isl_basic_map *bmap;
9777 bmap = isl_basic_map_copy(map->p[i]);
9778 list = isl_basic_map_list_add(list, bmap);
9781 return list;
9784 /* Return the intersection of the elements in the non-empty list "list".
9785 * All elements are assumed to live in the same space.
9787 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9788 __isl_take isl_basic_map_list *list)
9790 int i, n;
9791 isl_basic_map *bmap;
9793 if (!list)
9794 return NULL;
9795 n = isl_basic_map_list_n_basic_map(list);
9796 if (n < 1)
9797 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9798 "expecting non-empty list", goto error);
9800 bmap = isl_basic_map_list_get_basic_map(list, 0);
9801 for (i = 1; i < n; ++i) {
9802 isl_basic_map *bmap_i;
9804 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9805 bmap = isl_basic_map_intersect(bmap, bmap_i);
9808 isl_basic_map_list_free(list);
9809 return bmap;
9810 error:
9811 isl_basic_map_list_free(list);
9812 return NULL;
9815 /* Return the intersection of the elements in the non-empty list "list".
9816 * All elements are assumed to live in the same space.
9818 __isl_give isl_basic_set *isl_basic_set_list_intersect(
9819 __isl_take isl_basic_set_list *list)
9821 return isl_basic_map_list_intersect(list);
9824 /* Return the union of the elements of "list".
9825 * The list is required to have at least one element.
9827 __isl_give isl_set *isl_basic_set_list_union(
9828 __isl_take isl_basic_set_list *list)
9830 int i, n;
9831 isl_space *space;
9832 isl_basic_set *bset;
9833 isl_set *set;
9835 if (!list)
9836 return NULL;
9837 n = isl_basic_set_list_n_basic_set(list);
9838 if (n < 1)
9839 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9840 "expecting non-empty list", goto error);
9842 bset = isl_basic_set_list_get_basic_set(list, 0);
9843 space = isl_basic_set_get_space(bset);
9844 isl_basic_set_free(bset);
9846 set = isl_set_alloc_space(space, n, 0);
9847 for (i = 0; i < n; ++i) {
9848 bset = isl_basic_set_list_get_basic_set(list, i);
9849 set = isl_set_add_basic_set(set, bset);
9852 isl_basic_set_list_free(list);
9853 return set;
9854 error:
9855 isl_basic_set_list_free(list);
9856 return NULL;
9859 /* Return the union of the elements in the non-empty list "list".
9860 * All elements are assumed to live in the same space.
9862 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9864 int i, n;
9865 isl_set *set;
9867 if (!list)
9868 return NULL;
9869 n = isl_set_list_n_set(list);
9870 if (n < 1)
9871 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9872 "expecting non-empty list", goto error);
9874 set = isl_set_list_get_set(list, 0);
9875 for (i = 1; i < n; ++i) {
9876 isl_set *set_i;
9878 set_i = isl_set_list_get_set(list, i);
9879 set = isl_set_union(set, set_i);
9882 isl_set_list_free(list);
9883 return set;
9884 error:
9885 isl_set_list_free(list);
9886 return NULL;
9889 __isl_give isl_basic_map *isl_basic_map_product(
9890 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9892 isl_space *space_result = NULL;
9893 struct isl_basic_map *bmap;
9894 unsigned in1, in2, out1, out2, nparam, total, pos;
9895 struct isl_dim_map *dim_map1, *dim_map2;
9897 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9898 goto error;
9899 space_result = isl_space_product(isl_space_copy(bmap1->dim),
9900 isl_space_copy(bmap2->dim));
9902 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9903 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9904 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9905 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9906 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9908 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9909 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9910 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9911 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9912 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9913 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9914 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9915 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9916 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9917 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9918 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9920 bmap = isl_basic_map_alloc_space(space_result,
9921 bmap1->n_div + bmap2->n_div,
9922 bmap1->n_eq + bmap2->n_eq,
9923 bmap1->n_ineq + bmap2->n_ineq);
9924 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9925 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9926 bmap = isl_basic_map_simplify(bmap);
9927 return isl_basic_map_finalize(bmap);
9928 error:
9929 isl_basic_map_free(bmap1);
9930 isl_basic_map_free(bmap2);
9931 return NULL;
9934 __isl_give isl_basic_map *isl_basic_map_flat_product(
9935 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9937 isl_basic_map *prod;
9939 prod = isl_basic_map_product(bmap1, bmap2);
9940 prod = isl_basic_map_flatten(prod);
9941 return prod;
9944 __isl_give isl_basic_set *isl_basic_set_flat_product(
9945 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9947 return isl_basic_map_flat_range_product(bset1, bset2);
9950 __isl_give isl_basic_map *isl_basic_map_domain_product(
9951 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9953 isl_space *space_result = NULL;
9954 isl_basic_map *bmap;
9955 unsigned in1, in2, out, nparam, total, pos;
9956 struct isl_dim_map *dim_map1, *dim_map2;
9958 if (!bmap1 || !bmap2)
9959 goto error;
9961 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9962 isl_space_copy(bmap2->dim));
9964 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9965 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9966 out = isl_basic_map_dim(bmap1, isl_dim_out);
9967 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9969 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9970 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9971 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9972 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9973 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9974 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9975 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9976 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9977 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9978 isl_dim_map_div(dim_map1, bmap1, pos += out);
9979 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9981 bmap = isl_basic_map_alloc_space(space_result,
9982 bmap1->n_div + bmap2->n_div,
9983 bmap1->n_eq + bmap2->n_eq,
9984 bmap1->n_ineq + bmap2->n_ineq);
9985 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9986 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9987 bmap = isl_basic_map_simplify(bmap);
9988 return isl_basic_map_finalize(bmap);
9989 error:
9990 isl_basic_map_free(bmap1);
9991 isl_basic_map_free(bmap2);
9992 return NULL;
9995 __isl_give isl_basic_map *isl_basic_map_range_product(
9996 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9998 isl_bool rational;
9999 isl_space *space_result = NULL;
10000 isl_basic_map *bmap;
10001 unsigned in, out1, out2, nparam, total, pos;
10002 struct isl_dim_map *dim_map1, *dim_map2;
10004 rational = isl_basic_map_is_rational(bmap1);
10005 if (rational >= 0 && rational)
10006 rational = isl_basic_map_is_rational(bmap2);
10007 if (!bmap1 || !bmap2 || rational < 0)
10008 goto error;
10010 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10011 goto error;
10013 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10014 isl_space_copy(bmap2->dim));
10016 in = isl_basic_map_dim(bmap1, isl_dim_in);
10017 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10018 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10019 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10021 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10022 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10023 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10024 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10025 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10026 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10027 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10028 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10029 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10030 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10031 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10033 bmap = isl_basic_map_alloc_space(space_result,
10034 bmap1->n_div + bmap2->n_div,
10035 bmap1->n_eq + bmap2->n_eq,
10036 bmap1->n_ineq + bmap2->n_ineq);
10037 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10038 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10039 if (rational)
10040 bmap = isl_basic_map_set_rational(bmap);
10041 bmap = isl_basic_map_simplify(bmap);
10042 return isl_basic_map_finalize(bmap);
10043 error:
10044 isl_basic_map_free(bmap1);
10045 isl_basic_map_free(bmap2);
10046 return NULL;
10049 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10050 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10052 isl_basic_map *prod;
10054 prod = isl_basic_map_range_product(bmap1, bmap2);
10055 prod = isl_basic_map_flatten_range(prod);
10056 return prod;
10059 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10060 * and collect the results.
10061 * The result live in the space obtained by calling "space_product"
10062 * on the spaces of "map1" and "map2".
10063 * If "remove_duplicates" is set then the result may contain duplicates
10064 * (even if the inputs do not) and so we try and remove the obvious
10065 * duplicates.
10067 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10068 __isl_take isl_map *map2,
10069 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10070 __isl_take isl_space *right),
10071 __isl_give isl_basic_map *(*basic_map_product)(
10072 __isl_take isl_basic_map *left,
10073 __isl_take isl_basic_map *right),
10074 int remove_duplicates)
10076 unsigned flags = 0;
10077 struct isl_map *result;
10078 int i, j;
10079 isl_bool m;
10081 m = isl_map_has_equal_params(map1, map2);
10082 if (m < 0)
10083 goto error;
10084 if (!m)
10085 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10086 "parameters don't match", goto error);
10088 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10089 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10090 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10092 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10093 isl_space_copy(map2->dim)),
10094 map1->n * map2->n, flags);
10095 if (!result)
10096 goto error;
10097 for (i = 0; i < map1->n; ++i)
10098 for (j = 0; j < map2->n; ++j) {
10099 struct isl_basic_map *part;
10100 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10101 isl_basic_map_copy(map2->p[j]));
10102 if (isl_basic_map_is_empty(part))
10103 isl_basic_map_free(part);
10104 else
10105 result = isl_map_add_basic_map(result, part);
10106 if (!result)
10107 goto error;
10109 if (remove_duplicates)
10110 result = isl_map_remove_obvious_duplicates(result);
10111 isl_map_free(map1);
10112 isl_map_free(map2);
10113 return result;
10114 error:
10115 isl_map_free(map1);
10116 isl_map_free(map2);
10117 return NULL;
10120 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10122 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
10123 __isl_take isl_map *map2)
10125 return map_product(map1, map2, &isl_space_product,
10126 &isl_basic_map_product, 0);
10129 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10130 __isl_take isl_map *map2)
10132 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
10135 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10137 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10138 __isl_take isl_map *map2)
10140 isl_map *prod;
10142 prod = isl_map_product(map1, map2);
10143 prod = isl_map_flatten(prod);
10144 return prod;
10147 /* Given two set A and B, construct its Cartesian product A x B.
10149 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
10151 return isl_map_range_product(set1, set2);
10154 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10155 __isl_take isl_set *set2)
10157 return isl_map_flat_range_product(set1, set2);
10160 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10162 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
10163 __isl_take isl_map *map2)
10165 return map_product(map1, map2, &isl_space_domain_product,
10166 &isl_basic_map_domain_product, 1);
10169 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10171 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
10172 __isl_take isl_map *map2)
10174 return map_product(map1, map2, &isl_space_range_product,
10175 &isl_basic_map_range_product, 1);
10178 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10179 __isl_take isl_map *map2)
10181 return isl_map_align_params_map_map_and(map1, map2,
10182 &map_domain_product_aligned);
10185 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10186 __isl_take isl_map *map2)
10188 return isl_map_align_params_map_map_and(map1, map2,
10189 &map_range_product_aligned);
10192 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10194 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10196 isl_space *space;
10197 int total1, keep1, total2, keep2;
10199 if (!map)
10200 return NULL;
10201 if (!isl_space_domain_is_wrapping(map->dim) ||
10202 !isl_space_range_is_wrapping(map->dim))
10203 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10204 "not a product", return isl_map_free(map));
10206 space = isl_map_get_space(map);
10207 total1 = isl_space_dim(space, isl_dim_in);
10208 total2 = isl_space_dim(space, isl_dim_out);
10209 space = isl_space_factor_domain(space);
10210 keep1 = isl_space_dim(space, isl_dim_in);
10211 keep2 = isl_space_dim(space, isl_dim_out);
10212 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10213 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10214 map = isl_map_reset_space(map, space);
10216 return map;
10219 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10221 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10223 isl_space *space;
10224 int total1, keep1, total2, keep2;
10226 if (!map)
10227 return NULL;
10228 if (!isl_space_domain_is_wrapping(map->dim) ||
10229 !isl_space_range_is_wrapping(map->dim))
10230 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10231 "not a product", return isl_map_free(map));
10233 space = isl_map_get_space(map);
10234 total1 = isl_space_dim(space, isl_dim_in);
10235 total2 = isl_space_dim(space, isl_dim_out);
10236 space = isl_space_factor_range(space);
10237 keep1 = isl_space_dim(space, isl_dim_in);
10238 keep2 = isl_space_dim(space, isl_dim_out);
10239 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10240 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10241 map = isl_map_reset_space(map, space);
10243 return map;
10246 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10248 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10250 isl_space *space;
10251 int total, keep;
10253 if (!map)
10254 return NULL;
10255 if (!isl_space_domain_is_wrapping(map->dim))
10256 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10257 "domain is not a product", return isl_map_free(map));
10259 space = isl_map_get_space(map);
10260 total = isl_space_dim(space, isl_dim_in);
10261 space = isl_space_domain_factor_domain(space);
10262 keep = isl_space_dim(space, isl_dim_in);
10263 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10264 map = isl_map_reset_space(map, space);
10266 return map;
10269 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10271 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10273 isl_space *space;
10274 int total, keep;
10276 if (!map)
10277 return NULL;
10278 if (!isl_space_domain_is_wrapping(map->dim))
10279 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10280 "domain is not a product", return isl_map_free(map));
10282 space = isl_map_get_space(map);
10283 total = isl_space_dim(space, isl_dim_in);
10284 space = isl_space_domain_factor_range(space);
10285 keep = isl_space_dim(space, isl_dim_in);
10286 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10287 map = isl_map_reset_space(map, space);
10289 return map;
10292 /* Given a map A -> [B -> C], extract the map A -> B.
10294 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10296 isl_space *space;
10297 int total, keep;
10299 if (!map)
10300 return NULL;
10301 if (!isl_space_range_is_wrapping(map->dim))
10302 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10303 "range is not a product", return isl_map_free(map));
10305 space = isl_map_get_space(map);
10306 total = isl_space_dim(space, isl_dim_out);
10307 space = isl_space_range_factor_domain(space);
10308 keep = isl_space_dim(space, isl_dim_out);
10309 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10310 map = isl_map_reset_space(map, space);
10312 return map;
10315 /* Given a map A -> [B -> C], extract the map A -> C.
10317 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10319 isl_space *space;
10320 int total, keep;
10322 if (!map)
10323 return NULL;
10324 if (!isl_space_range_is_wrapping(map->dim))
10325 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10326 "range is not a product", return isl_map_free(map));
10328 space = isl_map_get_space(map);
10329 total = isl_space_dim(space, isl_dim_out);
10330 space = isl_space_range_factor_range(space);
10331 keep = isl_space_dim(space, isl_dim_out);
10332 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10333 map = isl_map_reset_space(map, space);
10335 return map;
10338 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10340 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10341 __isl_take isl_map *map2)
10343 isl_map *prod;
10345 prod = isl_map_domain_product(map1, map2);
10346 prod = isl_map_flatten_domain(prod);
10347 return prod;
10350 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10352 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10353 __isl_take isl_map *map2)
10355 isl_map *prod;
10357 prod = isl_map_range_product(map1, map2);
10358 prod = isl_map_flatten_range(prod);
10359 return prod;
10362 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10364 int i;
10365 uint32_t hash = isl_hash_init();
10366 unsigned total;
10368 if (!bmap)
10369 return 0;
10370 bmap = isl_basic_map_copy(bmap);
10371 bmap = isl_basic_map_normalize(bmap);
10372 if (!bmap)
10373 return 0;
10374 total = isl_basic_map_total_dim(bmap);
10375 isl_hash_byte(hash, bmap->n_eq & 0xFF);
10376 for (i = 0; i < bmap->n_eq; ++i) {
10377 uint32_t c_hash;
10378 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
10379 isl_hash_hash(hash, c_hash);
10381 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
10382 for (i = 0; i < bmap->n_ineq; ++i) {
10383 uint32_t c_hash;
10384 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
10385 isl_hash_hash(hash, c_hash);
10387 isl_hash_byte(hash, bmap->n_div & 0xFF);
10388 for (i = 0; i < bmap->n_div; ++i) {
10389 uint32_t c_hash;
10390 if (isl_int_is_zero(bmap->div[i][0]))
10391 continue;
10392 isl_hash_byte(hash, i & 0xFF);
10393 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
10394 isl_hash_hash(hash, c_hash);
10396 isl_basic_map_free(bmap);
10397 return hash;
10400 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
10402 return isl_basic_map_get_hash(bset_to_bmap(bset));
10405 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
10407 int i;
10408 uint32_t hash;
10410 if (!map)
10411 return 0;
10412 map = isl_map_copy(map);
10413 map = isl_map_normalize(map);
10414 if (!map)
10415 return 0;
10417 hash = isl_hash_init();
10418 for (i = 0; i < map->n; ++i) {
10419 uint32_t bmap_hash;
10420 bmap_hash = isl_basic_map_get_hash(map->p[i]);
10421 isl_hash_hash(hash, bmap_hash);
10424 isl_map_free(map);
10426 return hash;
10429 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
10431 return isl_map_get_hash(set_to_map(set));
10434 /* Return the number of basic maps in the (current) representation of "map".
10436 int isl_map_n_basic_map(__isl_keep isl_map *map)
10438 return map ? map->n : 0;
10441 int isl_set_n_basic_set(__isl_keep isl_set *set)
10443 return set ? set->n : 0;
10446 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
10447 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10449 int i;
10451 if (!map)
10452 return isl_stat_error;
10454 for (i = 0; i < map->n; ++i)
10455 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10456 return isl_stat_error;
10458 return isl_stat_ok;
10461 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10462 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10464 int i;
10466 if (!set)
10467 return isl_stat_error;
10469 for (i = 0; i < set->n; ++i)
10470 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10471 return isl_stat_error;
10473 return isl_stat_ok;
10476 /* Return a list of basic sets, the union of which is equal to "set".
10478 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10479 __isl_keep isl_set *set)
10481 int i;
10482 isl_basic_set_list *list;
10484 if (!set)
10485 return NULL;
10487 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10488 for (i = 0; i < set->n; ++i) {
10489 isl_basic_set *bset;
10491 bset = isl_basic_set_copy(set->p[i]);
10492 list = isl_basic_set_list_add(list, bset);
10495 return list;
10498 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10500 isl_space *space;
10502 if (!bset)
10503 return NULL;
10505 bset = isl_basic_set_cow(bset);
10506 if (!bset)
10507 return NULL;
10509 space = isl_basic_set_get_space(bset);
10510 space = isl_space_lift(space, bset->n_div);
10511 if (!space)
10512 goto error;
10513 isl_space_free(bset->dim);
10514 bset->dim = space;
10515 bset->extra -= bset->n_div;
10516 bset->n_div = 0;
10518 bset = isl_basic_set_finalize(bset);
10520 return bset;
10521 error:
10522 isl_basic_set_free(bset);
10523 return NULL;
10526 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10528 int i;
10529 isl_space *space;
10530 unsigned n_div;
10532 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10534 if (!set)
10535 return NULL;
10537 set = isl_set_cow(set);
10538 if (!set)
10539 return NULL;
10541 n_div = set->p[0]->n_div;
10542 space = isl_set_get_space(set);
10543 space = isl_space_lift(space, n_div);
10544 if (!space)
10545 goto error;
10546 isl_space_free(set->dim);
10547 set->dim = space;
10549 for (i = 0; i < set->n; ++i) {
10550 set->p[i] = isl_basic_set_lift(set->p[i]);
10551 if (!set->p[i])
10552 goto error;
10555 return set;
10556 error:
10557 isl_set_free(set);
10558 return NULL;
10561 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10563 unsigned dim;
10564 int size = 0;
10566 if (!bset)
10567 return -1;
10569 dim = isl_basic_set_total_dim(bset);
10570 size += bset->n_eq * (1 + dim);
10571 size += bset->n_ineq * (1 + dim);
10572 size += bset->n_div * (2 + dim);
10574 return size;
10577 int isl_set_size(__isl_keep isl_set *set)
10579 int i;
10580 int size = 0;
10582 if (!set)
10583 return -1;
10585 for (i = 0; i < set->n; ++i)
10586 size += isl_basic_set_size(set->p[i]);
10588 return size;
10591 /* Check if there is any lower bound (if lower == 0) and/or upper
10592 * bound (if upper == 0) on the specified dim.
10594 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10595 enum isl_dim_type type, unsigned pos, int lower, int upper)
10597 int i;
10599 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10600 return isl_bool_error;
10602 pos += isl_basic_map_offset(bmap, type);
10604 for (i = 0; i < bmap->n_div; ++i) {
10605 if (isl_int_is_zero(bmap->div[i][0]))
10606 continue;
10607 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10608 return isl_bool_true;
10611 for (i = 0; i < bmap->n_eq; ++i)
10612 if (!isl_int_is_zero(bmap->eq[i][pos]))
10613 return isl_bool_true;
10615 for (i = 0; i < bmap->n_ineq; ++i) {
10616 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10617 if (sgn > 0)
10618 lower = 1;
10619 if (sgn < 0)
10620 upper = 1;
10623 return lower && upper;
10626 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10627 enum isl_dim_type type, unsigned pos)
10629 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10632 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10633 enum isl_dim_type type, unsigned pos)
10635 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10638 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10639 enum isl_dim_type type, unsigned pos)
10641 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10644 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10645 enum isl_dim_type type, unsigned pos)
10647 int i;
10649 if (!map)
10650 return isl_bool_error;
10652 for (i = 0; i < map->n; ++i) {
10653 isl_bool bounded;
10654 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10655 if (bounded < 0 || !bounded)
10656 return bounded;
10659 return isl_bool_true;
10662 /* Return true if the specified dim is involved in both an upper bound
10663 * and a lower bound.
10665 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10666 enum isl_dim_type type, unsigned pos)
10668 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10671 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10673 static isl_bool has_any_bound(__isl_keep isl_map *map,
10674 enum isl_dim_type type, unsigned pos,
10675 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10676 enum isl_dim_type type, unsigned pos))
10678 int i;
10680 if (!map)
10681 return isl_bool_error;
10683 for (i = 0; i < map->n; ++i) {
10684 isl_bool bounded;
10685 bounded = fn(map->p[i], type, pos);
10686 if (bounded < 0 || bounded)
10687 return bounded;
10690 return isl_bool_false;
10693 /* Return 1 if the specified dim is involved in any lower bound.
10695 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10696 enum isl_dim_type type, unsigned pos)
10698 return has_any_bound(set, type, pos,
10699 &isl_basic_map_dim_has_lower_bound);
10702 /* Return 1 if the specified dim is involved in any upper bound.
10704 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10705 enum isl_dim_type type, unsigned pos)
10707 return has_any_bound(set, type, pos,
10708 &isl_basic_map_dim_has_upper_bound);
10711 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10713 static isl_bool has_bound(__isl_keep isl_map *map,
10714 enum isl_dim_type type, unsigned pos,
10715 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10716 enum isl_dim_type type, unsigned pos))
10718 int i;
10720 if (!map)
10721 return isl_bool_error;
10723 for (i = 0; i < map->n; ++i) {
10724 isl_bool bounded;
10725 bounded = fn(map->p[i], type, pos);
10726 if (bounded < 0 || !bounded)
10727 return bounded;
10730 return isl_bool_true;
10733 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10735 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10736 enum isl_dim_type type, unsigned pos)
10738 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10741 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10743 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10744 enum isl_dim_type type, unsigned pos)
10746 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10749 /* For each of the "n" variables starting at "first", determine
10750 * the sign of the variable and put the results in the first "n"
10751 * elements of the array "signs".
10752 * Sign
10753 * 1 means that the variable is non-negative
10754 * -1 means that the variable is non-positive
10755 * 0 means the variable attains both positive and negative values.
10757 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10758 unsigned first, unsigned n, int *signs)
10760 isl_vec *bound = NULL;
10761 struct isl_tab *tab = NULL;
10762 struct isl_tab_undo *snap;
10763 int i;
10765 if (!bset || !signs)
10766 return isl_stat_error;
10768 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10769 tab = isl_tab_from_basic_set(bset, 0);
10770 if (!bound || !tab)
10771 goto error;
10773 isl_seq_clr(bound->el, bound->size);
10774 isl_int_set_si(bound->el[0], -1);
10776 snap = isl_tab_snap(tab);
10777 for (i = 0; i < n; ++i) {
10778 int empty;
10780 isl_int_set_si(bound->el[1 + first + i], -1);
10781 if (isl_tab_add_ineq(tab, bound->el) < 0)
10782 goto error;
10783 empty = tab->empty;
10784 isl_int_set_si(bound->el[1 + first + i], 0);
10785 if (isl_tab_rollback(tab, snap) < 0)
10786 goto error;
10788 if (empty) {
10789 signs[i] = 1;
10790 continue;
10793 isl_int_set_si(bound->el[1 + first + i], 1);
10794 if (isl_tab_add_ineq(tab, bound->el) < 0)
10795 goto error;
10796 empty = tab->empty;
10797 isl_int_set_si(bound->el[1 + first + i], 0);
10798 if (isl_tab_rollback(tab, snap) < 0)
10799 goto error;
10801 signs[i] = empty ? -1 : 0;
10804 isl_tab_free(tab);
10805 isl_vec_free(bound);
10806 return isl_stat_ok;
10807 error:
10808 isl_tab_free(tab);
10809 isl_vec_free(bound);
10810 return isl_stat_error;
10813 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10814 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10816 if (!bset || !signs)
10817 return isl_stat_error;
10818 isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
10819 return isl_stat_error);
10821 first += pos(bset->dim, type) - 1;
10822 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10825 /* Is it possible for the integer division "div" to depend (possibly
10826 * indirectly) on any output dimensions?
10828 * If the div is undefined, then we conservatively assume that it
10829 * may depend on them.
10830 * Otherwise, we check if it actually depends on them or on any integer
10831 * divisions that may depend on them.
10833 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10835 int i;
10836 unsigned n_out, o_out;
10837 unsigned n_div, o_div;
10839 if (isl_int_is_zero(bmap->div[div][0]))
10840 return isl_bool_true;
10842 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10843 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10845 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10846 return isl_bool_true;
10848 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10849 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10851 for (i = 0; i < n_div; ++i) {
10852 isl_bool may_involve;
10854 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10855 continue;
10856 may_involve = div_may_involve_output(bmap, i);
10857 if (may_involve < 0 || may_involve)
10858 return may_involve;
10861 return isl_bool_false;
10864 /* Return the first integer division of "bmap" in the range
10865 * [first, first + n[ that may depend on any output dimensions and
10866 * that has a non-zero coefficient in "c" (where the first coefficient
10867 * in "c" corresponds to integer division "first").
10869 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10870 isl_int *c, int first, int n)
10872 int k;
10874 if (!bmap)
10875 return -1;
10877 for (k = first; k < first + n; ++k) {
10878 isl_bool may_involve;
10880 if (isl_int_is_zero(c[k]))
10881 continue;
10882 may_involve = div_may_involve_output(bmap, k);
10883 if (may_involve < 0)
10884 return -1;
10885 if (may_involve)
10886 return k;
10889 return first + n;
10892 /* Look for a pair of inequality constraints in "bmap" of the form
10894 * -l + i >= 0 or i >= l
10895 * and
10896 * n + l - i >= 0 or i <= l + n
10898 * with n < "m" and i the output dimension at position "pos".
10899 * (Note that n >= 0 as otherwise the two constraints would conflict.)
10900 * Furthermore, "l" is only allowed to involve parameters, input dimensions
10901 * and earlier output dimensions, as well as integer divisions that do
10902 * not involve any of the output dimensions.
10904 * Return the index of the first inequality constraint or bmap->n_ineq
10905 * if no such pair can be found.
10907 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10908 int pos, isl_int m)
10910 int i, j;
10911 isl_ctx *ctx;
10912 unsigned total;
10913 unsigned n_div, o_div;
10914 unsigned n_out, o_out;
10915 int less;
10917 if (!bmap)
10918 return -1;
10920 ctx = isl_basic_map_get_ctx(bmap);
10921 total = isl_basic_map_total_dim(bmap);
10922 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10923 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10924 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10925 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10926 for (i = 0; i < bmap->n_ineq; ++i) {
10927 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
10928 continue;
10929 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
10930 n_out - (pos + 1)) != -1)
10931 continue;
10932 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
10933 0, n_div) < n_div)
10934 continue;
10935 for (j = i + 1; j < bmap->n_ineq; ++j) {
10936 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
10937 ctx->one))
10938 continue;
10939 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
10940 bmap->ineq[j] + 1, total))
10941 continue;
10942 break;
10944 if (j >= bmap->n_ineq)
10945 continue;
10946 isl_int_add(bmap->ineq[i][0],
10947 bmap->ineq[i][0], bmap->ineq[j][0]);
10948 less = isl_int_abs_lt(bmap->ineq[i][0], m);
10949 isl_int_sub(bmap->ineq[i][0],
10950 bmap->ineq[i][0], bmap->ineq[j][0]);
10951 if (!less)
10952 continue;
10953 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
10954 return i;
10955 else
10956 return j;
10959 return bmap->n_ineq;
10962 /* Return the index of the equality of "bmap" that defines
10963 * the output dimension "pos" in terms of earlier dimensions.
10964 * The equality may also involve integer divisions, as long
10965 * as those integer divisions are defined in terms of
10966 * parameters or input dimensions.
10967 * In this case, *div is set to the number of integer divisions and
10968 * *ineq is set to the number of inequality constraints (provided
10969 * div and ineq are not NULL).
10971 * The equality may also involve a single integer division involving
10972 * the output dimensions (typically only output dimension "pos") as
10973 * long as the coefficient of output dimension "pos" is 1 or -1 and
10974 * there is a pair of constraints i >= l and i <= l + n, with i referring
10975 * to output dimension "pos", l an expression involving only earlier
10976 * dimensions and n smaller than the coefficient of the integer division
10977 * in the equality. In this case, the output dimension can be defined
10978 * in terms of a modulo expression that does not involve the integer division.
10979 * *div is then set to this single integer division and
10980 * *ineq is set to the index of constraint i >= l.
10982 * Return bmap->n_eq if there is no such equality.
10983 * Return -1 on error.
10985 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
10986 int pos, int *div, int *ineq)
10988 int j, k, l;
10989 unsigned n_out, o_out;
10990 unsigned n_div, o_div;
10992 if (!bmap)
10993 return -1;
10995 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10996 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10997 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10998 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11000 if (ineq)
11001 *ineq = bmap->n_ineq;
11002 if (div)
11003 *div = n_div;
11004 for (j = 0; j < bmap->n_eq; ++j) {
11005 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11006 continue;
11007 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11008 n_out - (pos + 1)) != -1)
11009 continue;
11010 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11011 0, n_div);
11012 if (k >= n_div)
11013 return j;
11014 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11015 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11016 continue;
11017 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11018 k + 1, n_div - (k+1)) < n_div)
11019 continue;
11020 l = find_modulo_constraint_pair(bmap, pos,
11021 bmap->eq[j][o_div + k]);
11022 if (l < 0)
11023 return -1;
11024 if (l >= bmap->n_ineq)
11025 continue;
11026 if (div)
11027 *div = k;
11028 if (ineq)
11029 *ineq = l;
11030 return j;
11033 return bmap->n_eq;
11036 /* Check if the given basic map is obviously single-valued.
11037 * In particular, for each output dimension, check that there is
11038 * an equality that defines the output dimension in terms of
11039 * earlier dimensions.
11041 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11043 int i;
11044 unsigned n_out;
11046 if (!bmap)
11047 return isl_bool_error;
11049 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11051 for (i = 0; i < n_out; ++i) {
11052 int eq;
11054 eq = isl_basic_map_output_defining_equality(bmap, i,
11055 NULL, NULL);
11056 if (eq < 0)
11057 return isl_bool_error;
11058 if (eq >= bmap->n_eq)
11059 return isl_bool_false;
11062 return isl_bool_true;
11065 /* Check if the given basic map is single-valued.
11066 * We simply compute
11068 * M \circ M^-1
11070 * and check if the result is a subset of the identity mapping.
11072 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11074 isl_space *space;
11075 isl_basic_map *test;
11076 isl_basic_map *id;
11077 isl_bool sv;
11079 sv = isl_basic_map_plain_is_single_valued(bmap);
11080 if (sv < 0 || sv)
11081 return sv;
11083 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11084 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11086 space = isl_basic_map_get_space(bmap);
11087 space = isl_space_map_from_set(isl_space_range(space));
11088 id = isl_basic_map_identity(space);
11090 sv = isl_basic_map_is_subset(test, id);
11092 isl_basic_map_free(test);
11093 isl_basic_map_free(id);
11095 return sv;
11098 /* Check if the given map is obviously single-valued.
11100 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11102 if (!map)
11103 return isl_bool_error;
11104 if (map->n == 0)
11105 return isl_bool_true;
11106 if (map->n >= 2)
11107 return isl_bool_false;
11109 return isl_basic_map_plain_is_single_valued(map->p[0]);
11112 /* Check if the given map is single-valued.
11113 * We simply compute
11115 * M \circ M^-1
11117 * and check if the result is a subset of the identity mapping.
11119 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11121 isl_space *dim;
11122 isl_map *test;
11123 isl_map *id;
11124 isl_bool sv;
11126 sv = isl_map_plain_is_single_valued(map);
11127 if (sv < 0 || sv)
11128 return sv;
11130 test = isl_map_reverse(isl_map_copy(map));
11131 test = isl_map_apply_range(test, isl_map_copy(map));
11133 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11134 id = isl_map_identity(dim);
11136 sv = isl_map_is_subset(test, id);
11138 isl_map_free(test);
11139 isl_map_free(id);
11141 return sv;
11144 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11146 isl_bool in;
11148 map = isl_map_copy(map);
11149 map = isl_map_reverse(map);
11150 in = isl_map_is_single_valued(map);
11151 isl_map_free(map);
11153 return in;
11156 /* Check if the given map is obviously injective.
11158 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11160 isl_bool in;
11162 map = isl_map_copy(map);
11163 map = isl_map_reverse(map);
11164 in = isl_map_plain_is_single_valued(map);
11165 isl_map_free(map);
11167 return in;
11170 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11172 isl_bool sv;
11174 sv = isl_map_is_single_valued(map);
11175 if (sv < 0 || !sv)
11176 return sv;
11178 return isl_map_is_injective(map);
11181 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11183 return isl_map_is_single_valued(set_to_map(set));
11186 /* Does "map" only map elements to themselves?
11188 * If the domain and range spaces are different, then "map"
11189 * is considered not to be an identity relation, even if it is empty.
11190 * Otherwise, construct the maximal identity relation and
11191 * check whether "map" is a subset of this relation.
11193 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11195 isl_space *space;
11196 isl_map *id;
11197 isl_bool equal, is_identity;
11199 space = isl_map_get_space(map);
11200 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
11201 isl_space_free(space);
11202 if (equal < 0 || !equal)
11203 return equal;
11205 id = isl_map_identity(isl_map_get_space(map));
11206 is_identity = isl_map_is_subset(map, id);
11207 isl_map_free(id);
11209 return is_identity;
11212 int isl_map_is_translation(__isl_keep isl_map *map)
11214 int ok;
11215 isl_set *delta;
11217 delta = isl_map_deltas(isl_map_copy(map));
11218 ok = isl_set_is_singleton(delta);
11219 isl_set_free(delta);
11221 return ok;
11224 static int unique(isl_int *p, unsigned pos, unsigned len)
11226 if (isl_seq_first_non_zero(p, pos) != -1)
11227 return 0;
11228 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11229 return 0;
11230 return 1;
11233 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11235 int i, j;
11236 unsigned nvar;
11237 unsigned ovar;
11239 if (!bset)
11240 return isl_bool_error;
11242 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
11243 return isl_bool_false;
11245 nvar = isl_basic_set_dim(bset, isl_dim_set);
11246 ovar = isl_space_offset(bset->dim, isl_dim_set);
11247 for (j = 0; j < nvar; ++j) {
11248 int lower = 0, upper = 0;
11249 for (i = 0; i < bset->n_eq; ++i) {
11250 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11251 continue;
11252 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11253 return isl_bool_false;
11254 break;
11256 if (i < bset->n_eq)
11257 continue;
11258 for (i = 0; i < bset->n_ineq; ++i) {
11259 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11260 continue;
11261 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11262 return isl_bool_false;
11263 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11264 lower = 1;
11265 else
11266 upper = 1;
11268 if (!lower || !upper)
11269 return isl_bool_false;
11272 return isl_bool_true;
11275 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11277 if (!set)
11278 return isl_bool_error;
11279 if (set->n != 1)
11280 return isl_bool_false;
11282 return isl_basic_set_is_box(set->p[0]);
11285 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11287 if (!bset)
11288 return isl_bool_error;
11290 return isl_space_is_wrapping(bset->dim);
11293 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11295 if (!set)
11296 return isl_bool_error;
11298 return isl_space_is_wrapping(set->dim);
11301 /* Modify the space of "map" through a call to "change".
11302 * If "can_change" is set (not NULL), then first call it to check
11303 * if the modification is allowed, printing the error message "cannot_change"
11304 * if it is not.
11306 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11307 isl_bool (*can_change)(__isl_keep isl_map *map),
11308 const char *cannot_change,
11309 __isl_give isl_space *(*change)(__isl_take isl_space *space))
11311 isl_bool ok;
11312 isl_space *space;
11314 if (!map)
11315 return NULL;
11317 ok = can_change ? can_change(map) : isl_bool_true;
11318 if (ok < 0)
11319 return isl_map_free(map);
11320 if (!ok)
11321 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11322 return isl_map_free(map));
11324 space = change(isl_map_get_space(map));
11325 map = isl_map_reset_space(map, space);
11327 return map;
11330 /* Is the domain of "map" a wrapped relation?
11332 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11334 if (!map)
11335 return isl_bool_error;
11337 return isl_space_domain_is_wrapping(map->dim);
11340 /* Does "map" have a wrapped relation in both domain and range?
11342 isl_bool isl_map_is_product(__isl_keep isl_map *map)
11344 return isl_space_is_product(isl_map_peek_space(map));
11347 /* Is the range of "map" a wrapped relation?
11349 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
11351 if (!map)
11352 return isl_bool_error;
11354 return isl_space_range_is_wrapping(map->dim);
11357 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
11359 bmap = isl_basic_map_cow(bmap);
11360 if (!bmap)
11361 return NULL;
11363 bmap->dim = isl_space_wrap(bmap->dim);
11364 if (!bmap->dim)
11365 goto error;
11367 bmap = isl_basic_map_finalize(bmap);
11369 return bset_from_bmap(bmap);
11370 error:
11371 isl_basic_map_free(bmap);
11372 return NULL;
11375 /* Given a map A -> B, return the set (A -> B).
11377 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
11379 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
11382 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
11384 bset = isl_basic_set_cow(bset);
11385 if (!bset)
11386 return NULL;
11388 bset->dim = isl_space_unwrap(bset->dim);
11389 if (!bset->dim)
11390 goto error;
11392 bset = isl_basic_set_finalize(bset);
11394 return bset_to_bmap(bset);
11395 error:
11396 isl_basic_set_free(bset);
11397 return NULL;
11400 /* Given a set (A -> B), return the map A -> B.
11401 * Error out if "set" is not of the form (A -> B).
11403 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
11405 return isl_map_change_space(set, &isl_set_is_wrapping,
11406 "not a wrapping set", &isl_space_unwrap);
11409 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
11410 enum isl_dim_type type)
11412 if (!bmap)
11413 return NULL;
11415 if (!isl_space_is_named_or_nested(bmap->dim, type))
11416 return bmap;
11418 bmap = isl_basic_map_cow(bmap);
11419 if (!bmap)
11420 return NULL;
11422 bmap->dim = isl_space_reset(bmap->dim, type);
11423 if (!bmap->dim)
11424 goto error;
11426 bmap = isl_basic_map_finalize(bmap);
11428 return bmap;
11429 error:
11430 isl_basic_map_free(bmap);
11431 return NULL;
11434 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
11435 enum isl_dim_type type)
11437 int i;
11439 if (!map)
11440 return NULL;
11442 if (!isl_space_is_named_or_nested(map->dim, type))
11443 return map;
11445 map = isl_map_cow(map);
11446 if (!map)
11447 return NULL;
11449 for (i = 0; i < map->n; ++i) {
11450 map->p[i] = isl_basic_map_reset(map->p[i], type);
11451 if (!map->p[i])
11452 goto error;
11454 map->dim = isl_space_reset(map->dim, type);
11455 if (!map->dim)
11456 goto error;
11458 return map;
11459 error:
11460 isl_map_free(map);
11461 return NULL;
11464 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11466 if (!bmap)
11467 return NULL;
11469 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11470 return bmap;
11472 bmap = isl_basic_map_cow(bmap);
11473 if (!bmap)
11474 return NULL;
11476 bmap->dim = isl_space_flatten(bmap->dim);
11477 if (!bmap->dim)
11478 goto error;
11480 bmap = isl_basic_map_finalize(bmap);
11482 return bmap;
11483 error:
11484 isl_basic_map_free(bmap);
11485 return NULL;
11488 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11490 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11493 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11494 __isl_take isl_basic_map *bmap)
11496 if (!bmap)
11497 return NULL;
11499 if (!bmap->dim->nested[0])
11500 return bmap;
11502 bmap = isl_basic_map_cow(bmap);
11503 if (!bmap)
11504 return NULL;
11506 bmap->dim = isl_space_flatten_domain(bmap->dim);
11507 if (!bmap->dim)
11508 goto error;
11510 bmap = isl_basic_map_finalize(bmap);
11512 return bmap;
11513 error:
11514 isl_basic_map_free(bmap);
11515 return NULL;
11518 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11519 __isl_take isl_basic_map *bmap)
11521 if (!bmap)
11522 return NULL;
11524 if (!bmap->dim->nested[1])
11525 return bmap;
11527 bmap = isl_basic_map_cow(bmap);
11528 if (!bmap)
11529 return NULL;
11531 bmap->dim = isl_space_flatten_range(bmap->dim);
11532 if (!bmap->dim)
11533 goto error;
11535 bmap = isl_basic_map_finalize(bmap);
11537 return bmap;
11538 error:
11539 isl_basic_map_free(bmap);
11540 return NULL;
11543 /* Remove any internal structure from the spaces of domain and range of "map".
11545 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11547 if (!map)
11548 return NULL;
11550 if (!map->dim->nested[0] && !map->dim->nested[1])
11551 return map;
11553 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11556 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11558 return set_from_map(isl_map_flatten(set_to_map(set)));
11561 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11563 isl_space *space, *flat_space;
11564 isl_map *map;
11566 space = isl_set_get_space(set);
11567 flat_space = isl_space_flatten(isl_space_copy(space));
11568 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
11569 flat_space));
11570 map = isl_map_intersect_domain(map, set);
11572 return map;
11575 /* Remove any internal structure from the space of the domain of "map".
11577 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11579 if (!map)
11580 return NULL;
11582 if (!map->dim->nested[0])
11583 return map;
11585 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11588 /* Remove any internal structure from the space of the range of "map".
11590 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11592 if (!map)
11593 return NULL;
11595 if (!map->dim->nested[1])
11596 return map;
11598 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11601 /* Reorder the dimensions of "bmap" according to the given dim_map
11602 * and set the dimension specification to "space" and
11603 * perform Gaussian elimination on the result.
11605 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11606 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
11608 isl_basic_map *res;
11609 unsigned flags;
11610 unsigned n_div;
11612 if (!bmap || !space || !dim_map)
11613 goto error;
11615 flags = bmap->flags;
11616 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11617 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
11618 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11619 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11620 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
11621 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11622 if (res)
11623 res->flags = flags;
11624 res = isl_basic_map_gauss(res, NULL);
11625 res = isl_basic_map_finalize(res);
11626 return res;
11627 error:
11628 free(dim_map);
11629 isl_basic_map_free(bmap);
11630 isl_space_free(space);
11631 return NULL;
11634 /* Reorder the dimensions of "map" according to given reordering.
11636 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11637 __isl_take isl_reordering *r)
11639 int i;
11640 struct isl_dim_map *dim_map;
11642 map = isl_map_cow(map);
11643 dim_map = isl_dim_map_from_reordering(r);
11644 if (!map || !r || !dim_map)
11645 goto error;
11647 for (i = 0; i < map->n; ++i) {
11648 struct isl_dim_map *dim_map_i;
11649 isl_space *space;
11651 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11653 space = isl_reordering_get_space(r);
11654 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
11656 if (!map->p[i])
11657 goto error;
11660 map = isl_map_reset_space(map, isl_reordering_get_space(r));
11661 map = isl_map_unmark_normalized(map);
11663 isl_reordering_free(r);
11664 free(dim_map);
11665 return map;
11666 error:
11667 free(dim_map);
11668 isl_map_free(map);
11669 isl_reordering_free(r);
11670 return NULL;
11673 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11674 __isl_take isl_reordering *r)
11676 return set_from_map(isl_map_realign(set_to_map(set), r));
11679 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11680 __isl_take isl_space *model)
11682 isl_ctx *ctx;
11683 isl_bool aligned;
11685 if (!map || !model)
11686 goto error;
11688 ctx = isl_space_get_ctx(model);
11689 if (!isl_space_has_named_params(model))
11690 isl_die(ctx, isl_error_invalid,
11691 "model has unnamed parameters", goto error);
11692 if (isl_map_check_named_params(map) < 0)
11693 goto error;
11694 aligned = isl_map_space_has_equal_params(map, model);
11695 if (aligned < 0)
11696 goto error;
11697 if (!aligned) {
11698 isl_reordering *exp;
11700 exp = isl_parameter_alignment_reordering(map->dim, model);
11701 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11702 map = isl_map_realign(map, exp);
11705 isl_space_free(model);
11706 return map;
11707 error:
11708 isl_space_free(model);
11709 isl_map_free(map);
11710 return NULL;
11713 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11714 __isl_take isl_space *model)
11716 return isl_map_align_params(set, model);
11719 /* Align the parameters of "bmap" to those of "model", introducing
11720 * additional parameters if needed.
11722 __isl_give isl_basic_map *isl_basic_map_align_params(
11723 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11725 isl_ctx *ctx;
11726 isl_bool equal_params;
11728 if (!bmap || !model)
11729 goto error;
11731 ctx = isl_space_get_ctx(model);
11732 if (!isl_space_has_named_params(model))
11733 isl_die(ctx, isl_error_invalid,
11734 "model has unnamed parameters", goto error);
11735 if (isl_basic_map_check_named_params(bmap) < 0)
11736 goto error;
11737 equal_params = isl_space_has_equal_params(bmap->dim, model);
11738 if (equal_params < 0)
11739 goto error;
11740 if (!equal_params) {
11741 isl_reordering *exp;
11742 struct isl_dim_map *dim_map;
11744 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11745 exp = isl_reordering_extend_space(exp,
11746 isl_basic_map_get_space(bmap));
11747 dim_map = isl_dim_map_from_reordering(exp);
11748 bmap = isl_basic_map_realign(bmap,
11749 isl_reordering_get_space(exp),
11750 isl_dim_map_extend(dim_map, bmap));
11751 isl_reordering_free(exp);
11752 free(dim_map);
11755 isl_space_free(model);
11756 return bmap;
11757 error:
11758 isl_space_free(model);
11759 isl_basic_map_free(bmap);
11760 return NULL;
11763 /* Do "bset" and "space" have the same parameters?
11765 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
11766 __isl_keep isl_space *space)
11768 isl_space *bset_space;
11770 bset_space = isl_basic_set_peek_space(bset);
11771 return isl_space_has_equal_params(bset_space, space);
11774 /* Do "map" and "space" have the same parameters?
11776 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
11777 __isl_keep isl_space *space)
11779 isl_space *map_space;
11781 map_space = isl_map_peek_space(map);
11782 return isl_space_has_equal_params(map_space, space);
11785 /* Do "set" and "space" have the same parameters?
11787 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
11788 __isl_keep isl_space *space)
11790 return isl_map_space_has_equal_params(set_to_map(set), space);
11793 /* Align the parameters of "bset" to those of "model", introducing
11794 * additional parameters if needed.
11796 __isl_give isl_basic_set *isl_basic_set_align_params(
11797 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11799 return isl_basic_map_align_params(bset, model);
11802 /* Drop all parameters not referenced by "map".
11804 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
11806 int i;
11808 if (isl_map_check_named_params(map) < 0)
11809 return isl_map_free(map);
11811 for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
11812 isl_bool involves;
11814 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
11815 if (involves < 0)
11816 return isl_map_free(map);
11817 if (!involves)
11818 map = isl_map_project_out(map, isl_dim_param, i, 1);
11821 return map;
11824 /* Drop all parameters not referenced by "set".
11826 __isl_give isl_set *isl_set_drop_unused_params(
11827 __isl_take isl_set *set)
11829 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
11832 /* Drop all parameters not referenced by "bmap".
11834 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
11835 __isl_take isl_basic_map *bmap)
11837 int i;
11839 if (isl_basic_map_check_named_params(bmap) < 0)
11840 return isl_basic_map_free(bmap);
11842 for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
11843 isl_bool involves;
11845 involves = isl_basic_map_involves_dims(bmap,
11846 isl_dim_param, i, 1);
11847 if (involves < 0)
11848 return isl_basic_map_free(bmap);
11849 if (!involves)
11850 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
11853 return bmap;
11856 /* Drop all parameters not referenced by "bset".
11858 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
11859 __isl_take isl_basic_set *bset)
11861 return bset_from_bmap(isl_basic_map_drop_unused_params(
11862 bset_to_bmap(bset)));
11865 __isl_give isl_mat *isl_basic_map_equalities_matrix(
11866 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11867 enum isl_dim_type c2, enum isl_dim_type c3,
11868 enum isl_dim_type c4, enum isl_dim_type c5)
11870 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11871 struct isl_mat *mat;
11872 int i, j, k;
11873 int pos;
11875 if (!bmap)
11876 return NULL;
11877 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11878 isl_basic_map_total_dim(bmap) + 1);
11879 if (!mat)
11880 return NULL;
11881 for (i = 0; i < bmap->n_eq; ++i)
11882 for (j = 0, pos = 0; j < 5; ++j) {
11883 int off = isl_basic_map_offset(bmap, c[j]);
11884 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11885 isl_int_set(mat->row[i][pos],
11886 bmap->eq[i][off + k]);
11887 ++pos;
11891 return mat;
11894 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11895 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11896 enum isl_dim_type c2, enum isl_dim_type c3,
11897 enum isl_dim_type c4, enum isl_dim_type c5)
11899 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11900 struct isl_mat *mat;
11901 int i, j, k;
11902 int pos;
11904 if (!bmap)
11905 return NULL;
11906 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11907 isl_basic_map_total_dim(bmap) + 1);
11908 if (!mat)
11909 return NULL;
11910 for (i = 0; i < bmap->n_ineq; ++i)
11911 for (j = 0, pos = 0; j < 5; ++j) {
11912 int off = isl_basic_map_offset(bmap, c[j]);
11913 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11914 isl_int_set(mat->row[i][pos],
11915 bmap->ineq[i][off + k]);
11916 ++pos;
11920 return mat;
11923 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11924 __isl_take isl_space *space,
11925 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11926 enum isl_dim_type c2, enum isl_dim_type c3,
11927 enum isl_dim_type c4, enum isl_dim_type c5)
11929 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11930 isl_basic_map *bmap = NULL;
11931 unsigned total;
11932 unsigned extra;
11933 int i, j, k, l;
11934 int pos;
11936 if (!space || !eq || !ineq)
11937 goto error;
11939 if (eq->n_col != ineq->n_col)
11940 isl_die(space->ctx, isl_error_invalid,
11941 "equalities and inequalities matrices should have "
11942 "same number of columns", goto error);
11944 total = 1 + isl_space_dim(space, isl_dim_all);
11946 if (eq->n_col < total)
11947 isl_die(space->ctx, isl_error_invalid,
11948 "number of columns too small", goto error);
11950 extra = eq->n_col - total;
11952 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
11953 eq->n_row, ineq->n_row);
11954 if (!bmap)
11955 goto error;
11956 for (i = 0; i < extra; ++i) {
11957 k = isl_basic_map_alloc_div(bmap);
11958 if (k < 0)
11959 goto error;
11960 isl_int_set_si(bmap->div[k][0], 0);
11962 for (i = 0; i < eq->n_row; ++i) {
11963 l = isl_basic_map_alloc_equality(bmap);
11964 if (l < 0)
11965 goto error;
11966 for (j = 0, pos = 0; j < 5; ++j) {
11967 int off = isl_basic_map_offset(bmap, c[j]);
11968 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11969 isl_int_set(bmap->eq[l][off + k],
11970 eq->row[i][pos]);
11971 ++pos;
11975 for (i = 0; i < ineq->n_row; ++i) {
11976 l = isl_basic_map_alloc_inequality(bmap);
11977 if (l < 0)
11978 goto error;
11979 for (j = 0, pos = 0; j < 5; ++j) {
11980 int off = isl_basic_map_offset(bmap, c[j]);
11981 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11982 isl_int_set(bmap->ineq[l][off + k],
11983 ineq->row[i][pos]);
11984 ++pos;
11989 isl_space_free(space);
11990 isl_mat_free(eq);
11991 isl_mat_free(ineq);
11993 bmap = isl_basic_map_simplify(bmap);
11994 return isl_basic_map_finalize(bmap);
11995 error:
11996 isl_space_free(space);
11997 isl_mat_free(eq);
11998 isl_mat_free(ineq);
11999 isl_basic_map_free(bmap);
12000 return NULL;
12003 __isl_give isl_mat *isl_basic_set_equalities_matrix(
12004 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12005 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12007 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12008 c1, c2, c3, c4, isl_dim_in);
12011 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12012 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12013 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12015 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12016 c1, c2, c3, c4, isl_dim_in);
12019 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12020 __isl_take isl_space *dim,
12021 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12022 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12024 isl_basic_map *bmap;
12025 bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
12026 c1, c2, c3, c4, isl_dim_in);
12027 return bset_from_bmap(bmap);
12030 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12032 if (!bmap)
12033 return isl_bool_error;
12035 return isl_space_can_zip(bmap->dim);
12038 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12040 if (!map)
12041 return isl_bool_error;
12043 return isl_space_can_zip(map->dim);
12046 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12047 * (A -> C) -> (B -> D).
12049 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12051 unsigned pos;
12052 unsigned n1;
12053 unsigned n2;
12055 if (!bmap)
12056 return NULL;
12058 if (!isl_basic_map_can_zip(bmap))
12059 isl_die(bmap->ctx, isl_error_invalid,
12060 "basic map cannot be zipped", goto error);
12061 pos = isl_basic_map_offset(bmap, isl_dim_in) +
12062 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12063 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12064 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12065 bmap = isl_basic_map_cow(bmap);
12066 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12067 if (!bmap)
12068 return NULL;
12069 bmap->dim = isl_space_zip(bmap->dim);
12070 if (!bmap->dim)
12071 goto error;
12072 bmap = isl_basic_map_mark_final(bmap);
12073 return bmap;
12074 error:
12075 isl_basic_map_free(bmap);
12076 return NULL;
12079 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12080 * (A -> C) -> (B -> D).
12082 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12084 int i;
12086 if (!map)
12087 return NULL;
12089 if (!isl_map_can_zip(map))
12090 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12091 goto error);
12093 map = isl_map_cow(map);
12094 if (!map)
12095 return NULL;
12097 for (i = 0; i < map->n; ++i) {
12098 map->p[i] = isl_basic_map_zip(map->p[i]);
12099 if (!map->p[i])
12100 goto error;
12103 map->dim = isl_space_zip(map->dim);
12104 if (!map->dim)
12105 goto error;
12107 return map;
12108 error:
12109 isl_map_free(map);
12110 return NULL;
12113 /* Can we apply isl_basic_map_curry to "bmap"?
12114 * That is, does it have a nested relation in its domain?
12116 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12118 if (!bmap)
12119 return isl_bool_error;
12121 return isl_space_can_curry(bmap->dim);
12124 /* Can we apply isl_map_curry to "map"?
12125 * That is, does it have a nested relation in its domain?
12127 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12129 if (!map)
12130 return isl_bool_error;
12132 return isl_space_can_curry(map->dim);
12135 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12136 * A -> (B -> C).
12138 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12141 if (!bmap)
12142 return NULL;
12144 if (!isl_basic_map_can_curry(bmap))
12145 isl_die(bmap->ctx, isl_error_invalid,
12146 "basic map cannot be curried", goto error);
12147 bmap = isl_basic_map_cow(bmap);
12148 if (!bmap)
12149 return NULL;
12150 bmap->dim = isl_space_curry(bmap->dim);
12151 if (!bmap->dim)
12152 goto error;
12153 bmap = isl_basic_map_mark_final(bmap);
12154 return bmap;
12155 error:
12156 isl_basic_map_free(bmap);
12157 return NULL;
12160 /* Given a map (A -> B) -> C, return the corresponding map
12161 * A -> (B -> C).
12163 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
12165 return isl_map_change_space(map, &isl_map_can_curry,
12166 "map cannot be curried", &isl_space_curry);
12169 /* Can isl_map_range_curry be applied to "map"?
12170 * That is, does it have a nested relation in its range,
12171 * the domain of which is itself a nested relation?
12173 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
12175 if (!map)
12176 return isl_bool_error;
12178 return isl_space_can_range_curry(map->dim);
12181 /* Given a map A -> ((B -> C) -> D), return the corresponding map
12182 * A -> (B -> (C -> D)).
12184 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
12186 return isl_map_change_space(map, &isl_map_can_range_curry,
12187 "map range cannot be curried",
12188 &isl_space_range_curry);
12191 /* Can we apply isl_basic_map_uncurry to "bmap"?
12192 * That is, does it have a nested relation in its domain?
12194 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
12196 if (!bmap)
12197 return isl_bool_error;
12199 return isl_space_can_uncurry(bmap->dim);
12202 /* Can we apply isl_map_uncurry to "map"?
12203 * That is, does it have a nested relation in its domain?
12205 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
12207 if (!map)
12208 return isl_bool_error;
12210 return isl_space_can_uncurry(map->dim);
12213 /* Given a basic map A -> (B -> C), return the corresponding basic map
12214 * (A -> B) -> C.
12216 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
12219 if (!bmap)
12220 return NULL;
12222 if (!isl_basic_map_can_uncurry(bmap))
12223 isl_die(bmap->ctx, isl_error_invalid,
12224 "basic map cannot be uncurried",
12225 return isl_basic_map_free(bmap));
12226 bmap = isl_basic_map_cow(bmap);
12227 if (!bmap)
12228 return NULL;
12229 bmap->dim = isl_space_uncurry(bmap->dim);
12230 if (!bmap->dim)
12231 return isl_basic_map_free(bmap);
12232 bmap = isl_basic_map_mark_final(bmap);
12233 return bmap;
12236 /* Given a map A -> (B -> C), return the corresponding map
12237 * (A -> B) -> C.
12239 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
12241 return isl_map_change_space(map, &isl_map_can_uncurry,
12242 "map cannot be uncurried", &isl_space_uncurry);
12245 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
12246 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12248 return isl_map_equate(set, type1, pos1, type2, pos2);
12251 /* Construct a basic map where the given dimensions are equal to each other.
12253 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
12254 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12256 isl_basic_map *bmap = NULL;
12257 int i;
12259 if (!space)
12260 return NULL;
12262 if (pos1 >= isl_space_dim(space, type1))
12263 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12264 "index out of bounds", goto error);
12265 if (pos2 >= isl_space_dim(space, type2))
12266 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12267 "index out of bounds", goto error);
12269 if (type1 == type2 && pos1 == pos2)
12270 return isl_basic_map_universe(space);
12272 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
12273 i = isl_basic_map_alloc_equality(bmap);
12274 if (i < 0)
12275 goto error;
12276 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12277 pos1 += isl_basic_map_offset(bmap, type1);
12278 pos2 += isl_basic_map_offset(bmap, type2);
12279 isl_int_set_si(bmap->eq[i][pos1], -1);
12280 isl_int_set_si(bmap->eq[i][pos2], 1);
12281 bmap = isl_basic_map_finalize(bmap);
12282 isl_space_free(space);
12283 return bmap;
12284 error:
12285 isl_space_free(space);
12286 isl_basic_map_free(bmap);
12287 return NULL;
12290 /* Add a constraint imposing that the given two dimensions are equal.
12292 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
12293 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12295 isl_basic_map *eq;
12297 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12299 bmap = isl_basic_map_intersect(bmap, eq);
12301 return bmap;
12304 /* Add a constraint imposing that the given two dimensions are equal.
12306 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
12307 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12309 isl_basic_map *bmap;
12311 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
12313 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12315 return map;
12318 /* Add a constraint imposing that the given two dimensions have opposite values.
12320 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
12321 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12323 isl_basic_map *bmap = NULL;
12324 int i;
12326 if (!map)
12327 return NULL;
12329 if (pos1 >= isl_map_dim(map, type1))
12330 isl_die(map->ctx, isl_error_invalid,
12331 "index out of bounds", goto error);
12332 if (pos2 >= isl_map_dim(map, type2))
12333 isl_die(map->ctx, isl_error_invalid,
12334 "index out of bounds", goto error);
12336 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
12337 i = isl_basic_map_alloc_equality(bmap);
12338 if (i < 0)
12339 goto error;
12340 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12341 pos1 += isl_basic_map_offset(bmap, type1);
12342 pos2 += isl_basic_map_offset(bmap, type2);
12343 isl_int_set_si(bmap->eq[i][pos1], 1);
12344 isl_int_set_si(bmap->eq[i][pos2], 1);
12345 bmap = isl_basic_map_finalize(bmap);
12347 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12349 return map;
12350 error:
12351 isl_basic_map_free(bmap);
12352 isl_map_free(map);
12353 return NULL;
12356 /* Construct a constraint imposing that the value of the first dimension is
12357 * greater than or equal to that of the second.
12359 static __isl_give isl_constraint *constraint_order_ge(
12360 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
12361 enum isl_dim_type type2, int pos2)
12363 isl_constraint *c;
12365 if (!space)
12366 return NULL;
12368 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
12370 if (pos1 >= isl_constraint_dim(c, type1))
12371 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
12372 "index out of bounds", return isl_constraint_free(c));
12373 if (pos2 >= isl_constraint_dim(c, type2))
12374 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
12375 "index out of bounds", return isl_constraint_free(c));
12377 if (type1 == type2 && pos1 == pos2)
12378 return c;
12380 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
12381 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
12383 return c;
12386 /* Add a constraint imposing that the value of the first dimension is
12387 * greater than or equal to that of the second.
12389 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
12390 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12392 isl_constraint *c;
12393 isl_space *space;
12395 if (type1 == type2 && pos1 == pos2)
12396 return bmap;
12397 space = isl_basic_map_get_space(bmap);
12398 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12399 bmap = isl_basic_map_add_constraint(bmap, c);
12401 return bmap;
12404 /* Add a constraint imposing that the value of the first dimension is
12405 * greater than or equal to that of the second.
12407 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12408 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12410 isl_constraint *c;
12411 isl_space *space;
12413 if (type1 == type2 && pos1 == pos2)
12414 return map;
12415 space = isl_map_get_space(map);
12416 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12417 map = isl_map_add_constraint(map, c);
12419 return map;
12422 /* Add a constraint imposing that the value of the first dimension is
12423 * less than or equal to that of the second.
12425 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12426 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12428 return isl_map_order_ge(map, type2, pos2, type1, pos1);
12431 /* Construct a basic map where the value of the first dimension is
12432 * greater than that of the second.
12434 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12435 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12437 isl_basic_map *bmap = NULL;
12438 int i;
12440 if (!space)
12441 return NULL;
12443 if (pos1 >= isl_space_dim(space, type1))
12444 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12445 "index out of bounds", goto error);
12446 if (pos2 >= isl_space_dim(space, type2))
12447 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12448 "index out of bounds", goto error);
12450 if (type1 == type2 && pos1 == pos2)
12451 return isl_basic_map_empty(space);
12453 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12454 i = isl_basic_map_alloc_inequality(bmap);
12455 if (i < 0)
12456 return isl_basic_map_free(bmap);
12457 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12458 pos1 += isl_basic_map_offset(bmap, type1);
12459 pos2 += isl_basic_map_offset(bmap, type2);
12460 isl_int_set_si(bmap->ineq[i][pos1], 1);
12461 isl_int_set_si(bmap->ineq[i][pos2], -1);
12462 isl_int_set_si(bmap->ineq[i][0], -1);
12463 bmap = isl_basic_map_finalize(bmap);
12465 return bmap;
12466 error:
12467 isl_space_free(space);
12468 isl_basic_map_free(bmap);
12469 return NULL;
12472 /* Add a constraint imposing that the value of the first dimension is
12473 * greater than that of the second.
12475 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12476 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12478 isl_basic_map *gt;
12480 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12482 bmap = isl_basic_map_intersect(bmap, gt);
12484 return bmap;
12487 /* Add a constraint imposing that the value of the first dimension is
12488 * greater than that of the second.
12490 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12491 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12493 isl_basic_map *bmap;
12495 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12497 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12499 return map;
12502 /* Add a constraint imposing that the value of the first dimension is
12503 * smaller than that of the second.
12505 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12506 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12508 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12511 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12512 int pos)
12514 isl_aff *div;
12515 isl_local_space *ls;
12517 if (!bmap)
12518 return NULL;
12520 if (!isl_basic_map_divs_known(bmap))
12521 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12522 "some divs are unknown", return NULL);
12524 ls = isl_basic_map_get_local_space(bmap);
12525 div = isl_local_space_get_div(ls, pos);
12526 isl_local_space_free(ls);
12528 return div;
12531 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12532 int pos)
12534 return isl_basic_map_get_div(bset, pos);
12537 /* Plug in "subs" for dimension "type", "pos" of "bset".
12539 * Let i be the dimension to replace and let "subs" be of the form
12541 * f/d
12543 * Any integer division with a non-zero coefficient for i,
12545 * floor((a i + g)/m)
12547 * is replaced by
12549 * floor((a f + d g)/(m d))
12551 * Constraints of the form
12553 * a i + g
12555 * are replaced by
12557 * a f + d g
12559 * We currently require that "subs" is an integral expression.
12560 * Handling rational expressions may require us to add stride constraints
12561 * as we do in isl_basic_set_preimage_multi_aff.
12563 __isl_give isl_basic_set *isl_basic_set_substitute(
12564 __isl_take isl_basic_set *bset,
12565 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12567 int i;
12568 isl_int v;
12569 isl_ctx *ctx;
12571 if (bset && isl_basic_set_plain_is_empty(bset))
12572 return bset;
12574 bset = isl_basic_set_cow(bset);
12575 if (!bset || !subs)
12576 goto error;
12578 ctx = isl_basic_set_get_ctx(bset);
12579 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12580 isl_die(ctx, isl_error_invalid,
12581 "spaces don't match", goto error);
12582 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12583 isl_die(ctx, isl_error_unsupported,
12584 "cannot handle divs yet", goto error);
12585 if (!isl_int_is_one(subs->v->el[0]))
12586 isl_die(ctx, isl_error_invalid,
12587 "can only substitute integer expressions", goto error);
12589 pos += isl_basic_set_offset(bset, type);
12591 isl_int_init(v);
12593 for (i = 0; i < bset->n_eq; ++i) {
12594 if (isl_int_is_zero(bset->eq[i][pos]))
12595 continue;
12596 isl_int_set(v, bset->eq[i][pos]);
12597 isl_int_set_si(bset->eq[i][pos], 0);
12598 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12599 v, subs->v->el + 1, subs->v->size - 1);
12602 for (i = 0; i < bset->n_ineq; ++i) {
12603 if (isl_int_is_zero(bset->ineq[i][pos]))
12604 continue;
12605 isl_int_set(v, bset->ineq[i][pos]);
12606 isl_int_set_si(bset->ineq[i][pos], 0);
12607 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12608 v, subs->v->el + 1, subs->v->size - 1);
12611 for (i = 0; i < bset->n_div; ++i) {
12612 if (isl_int_is_zero(bset->div[i][1 + pos]))
12613 continue;
12614 isl_int_set(v, bset->div[i][1 + pos]);
12615 isl_int_set_si(bset->div[i][1 + pos], 0);
12616 isl_seq_combine(bset->div[i] + 1,
12617 subs->v->el[0], bset->div[i] + 1,
12618 v, subs->v->el + 1, subs->v->size - 1);
12619 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12622 isl_int_clear(v);
12624 bset = isl_basic_set_simplify(bset);
12625 return isl_basic_set_finalize(bset);
12626 error:
12627 isl_basic_set_free(bset);
12628 return NULL;
12631 /* Plug in "subs" for dimension "type", "pos" of "set".
12633 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12634 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12636 int i;
12638 if (set && isl_set_plain_is_empty(set))
12639 return set;
12641 set = isl_set_cow(set);
12642 if (!set || !subs)
12643 goto error;
12645 for (i = set->n - 1; i >= 0; --i) {
12646 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12647 set = set_from_map(remove_if_empty(set_to_map(set), i));
12648 if (!set)
12649 return NULL;
12652 return set;
12653 error:
12654 isl_set_free(set);
12655 return NULL;
12658 /* Check if the range of "ma" is compatible with the domain or range
12659 * (depending on "type") of "bmap".
12661 static isl_stat check_basic_map_compatible_range_multi_aff(
12662 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12663 __isl_keep isl_multi_aff *ma)
12665 isl_bool m;
12666 isl_space *ma_space;
12668 ma_space = isl_multi_aff_get_space(ma);
12670 m = isl_space_has_equal_params(bmap->dim, ma_space);
12671 if (m < 0)
12672 goto error;
12673 if (!m)
12674 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12675 "parameters don't match", goto error);
12676 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12677 if (m < 0)
12678 goto error;
12679 if (!m)
12680 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12681 "spaces don't match", goto error);
12683 isl_space_free(ma_space);
12684 return isl_stat_ok;
12685 error:
12686 isl_space_free(ma_space);
12687 return isl_stat_error;
12690 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12691 * coefficients before the transformed range of dimensions,
12692 * the "n_after" coefficients after the transformed range of dimensions
12693 * and the coefficients of the other divs in "bmap".
12695 static int set_ma_divs(__isl_keep isl_basic_map *bmap,
12696 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12698 int i;
12699 int n_param;
12700 int n_set;
12701 isl_local_space *ls;
12703 if (n_div == 0)
12704 return 0;
12706 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
12707 if (!ls)
12708 return -1;
12710 n_param = isl_local_space_dim(ls, isl_dim_param);
12711 n_set = isl_local_space_dim(ls, isl_dim_set);
12712 for (i = 0; i < n_div; ++i) {
12713 int o_bmap = 0, o_ls = 0;
12715 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12716 o_bmap += 1 + 1 + n_param;
12717 o_ls += 1 + 1 + n_param;
12718 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12719 o_bmap += n_before;
12720 isl_seq_cpy(bmap->div[i] + o_bmap,
12721 ls->div->row[i] + o_ls, n_set);
12722 o_bmap += n_set;
12723 o_ls += n_set;
12724 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12725 o_bmap += n_after;
12726 isl_seq_cpy(bmap->div[i] + o_bmap,
12727 ls->div->row[i] + o_ls, n_div);
12728 o_bmap += n_div;
12729 o_ls += n_div;
12730 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12731 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
12732 goto error;
12735 isl_local_space_free(ls);
12736 return 0;
12737 error:
12738 isl_local_space_free(ls);
12739 return -1;
12742 /* How many stride constraints does "ma" enforce?
12743 * That is, how many of the affine expressions have a denominator
12744 * different from one?
12746 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12748 int i;
12749 int strides = 0;
12751 for (i = 0; i < ma->n; ++i)
12752 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
12753 strides++;
12755 return strides;
12758 /* For each affine expression in ma of the form
12760 * x_i = (f_i y + h_i)/m_i
12762 * with m_i different from one, add a constraint to "bmap"
12763 * of the form
12765 * f_i y + h_i = m_i alpha_i
12767 * with alpha_i an additional existentially quantified variable.
12769 * The input variables of "ma" correspond to a subset of the variables
12770 * of "bmap". There are "n_before" variables in "bmap" before this
12771 * subset and "n_after" variables after this subset.
12772 * The integer divisions of the affine expressions in "ma" are assumed
12773 * to have been aligned. There are "n_div_ma" of them and
12774 * they appear first in "bmap", straight after the "n_after" variables.
12776 static __isl_give isl_basic_map *add_ma_strides(
12777 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12778 int n_before, int n_after, int n_div_ma)
12780 int i, k;
12781 int div;
12782 int total;
12783 int n_param;
12784 int n_in;
12786 total = isl_basic_map_total_dim(bmap);
12787 n_param = isl_multi_aff_dim(ma, isl_dim_param);
12788 n_in = isl_multi_aff_dim(ma, isl_dim_in);
12789 for (i = 0; i < ma->n; ++i) {
12790 int o_bmap = 0, o_ma = 1;
12792 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
12793 continue;
12794 div = isl_basic_map_alloc_div(bmap);
12795 k = isl_basic_map_alloc_equality(bmap);
12796 if (div < 0 || k < 0)
12797 goto error;
12798 isl_int_set_si(bmap->div[div][0], 0);
12799 isl_seq_cpy(bmap->eq[k] + o_bmap,
12800 ma->u.p[i]->v->el + o_ma, 1 + n_param);
12801 o_bmap += 1 + n_param;
12802 o_ma += 1 + n_param;
12803 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12804 o_bmap += n_before;
12805 isl_seq_cpy(bmap->eq[k] + o_bmap,
12806 ma->u.p[i]->v->el + o_ma, n_in);
12807 o_bmap += n_in;
12808 o_ma += n_in;
12809 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12810 o_bmap += n_after;
12811 isl_seq_cpy(bmap->eq[k] + o_bmap,
12812 ma->u.p[i]->v->el + o_ma, n_div_ma);
12813 o_bmap += n_div_ma;
12814 o_ma += n_div_ma;
12815 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12816 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
12817 total++;
12820 return bmap;
12821 error:
12822 isl_basic_map_free(bmap);
12823 return NULL;
12826 /* Replace the domain or range space (depending on "type) of "space" by "set".
12828 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12829 enum isl_dim_type type, __isl_take isl_space *set)
12831 if (type == isl_dim_in) {
12832 space = isl_space_range(space);
12833 space = isl_space_map_from_domain_and_range(set, space);
12834 } else {
12835 space = isl_space_domain(space);
12836 space = isl_space_map_from_domain_and_range(space, set);
12839 return space;
12842 /* Compute the preimage of the domain or range (depending on "type")
12843 * of "bmap" under the function represented by "ma".
12844 * In other words, plug in "ma" in the domain or range of "bmap".
12845 * The result is a basic map that lives in the same space as "bmap"
12846 * except that the domain or range has been replaced by
12847 * the domain space of "ma".
12849 * If bmap is represented by
12851 * A(p) + S u + B x + T v + C(divs) >= 0,
12853 * where u and x are input and output dimensions if type == isl_dim_out
12854 * while x and v are input and output dimensions if type == isl_dim_in,
12855 * and ma is represented by
12857 * x = D(p) + F(y) + G(divs')
12859 * then the result is
12861 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12863 * The divs in the input set are similarly adjusted.
12864 * In particular
12866 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12868 * becomes
12870 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12871 * B_i G(divs') + c_i(divs))/n_i)
12873 * If bmap is not a rational map and if F(y) involves any denominators
12875 * x_i = (f_i y + h_i)/m_i
12877 * then additional constraints are added to ensure that we only
12878 * map back integer points. That is we enforce
12880 * f_i y + h_i = m_i alpha_i
12882 * with alpha_i an additional existentially quantified variable.
12884 * We first copy over the divs from "ma".
12885 * Then we add the modified constraints and divs from "bmap".
12886 * Finally, we add the stride constraints, if needed.
12888 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12889 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12890 __isl_take isl_multi_aff *ma)
12892 int i, k;
12893 isl_space *space;
12894 isl_basic_map *res = NULL;
12895 int n_before, n_after, n_div_bmap, n_div_ma;
12896 isl_int f, c1, c2, g;
12897 isl_bool rational;
12898 int strides;
12900 isl_int_init(f);
12901 isl_int_init(c1);
12902 isl_int_init(c2);
12903 isl_int_init(g);
12905 ma = isl_multi_aff_align_divs(ma);
12906 if (!bmap || !ma)
12907 goto error;
12908 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12909 goto error;
12911 if (type == isl_dim_in) {
12912 n_before = 0;
12913 n_after = isl_basic_map_dim(bmap, isl_dim_out);
12914 } else {
12915 n_before = isl_basic_map_dim(bmap, isl_dim_in);
12916 n_after = 0;
12918 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12919 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
12921 space = isl_multi_aff_get_domain_space(ma);
12922 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12923 rational = isl_basic_map_is_rational(bmap);
12924 strides = rational ? 0 : multi_aff_strides(ma);
12925 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12926 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12927 if (rational)
12928 res = isl_basic_map_set_rational(res);
12930 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12931 if (isl_basic_map_alloc_div(res) < 0)
12932 goto error;
12934 if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
12935 goto error;
12937 for (i = 0; i < bmap->n_eq; ++i) {
12938 k = isl_basic_map_alloc_equality(res);
12939 if (k < 0)
12940 goto error;
12941 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
12942 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12945 for (i = 0; i < bmap->n_ineq; ++i) {
12946 k = isl_basic_map_alloc_inequality(res);
12947 if (k < 0)
12948 goto error;
12949 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
12950 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12953 for (i = 0; i < bmap->n_div; ++i) {
12954 if (isl_int_is_zero(bmap->div[i][0])) {
12955 isl_int_set_si(res->div[n_div_ma + i][0], 0);
12956 continue;
12958 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
12959 n_before, n_after, n_div_ma, n_div_bmap,
12960 f, c1, c2, g, 1);
12963 if (strides)
12964 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
12966 isl_int_clear(f);
12967 isl_int_clear(c1);
12968 isl_int_clear(c2);
12969 isl_int_clear(g);
12970 isl_basic_map_free(bmap);
12971 isl_multi_aff_free(ma);
12972 res = isl_basic_map_simplify(res);
12973 return isl_basic_map_finalize(res);
12974 error:
12975 isl_int_clear(f);
12976 isl_int_clear(c1);
12977 isl_int_clear(c2);
12978 isl_int_clear(g);
12979 isl_basic_map_free(bmap);
12980 isl_multi_aff_free(ma);
12981 isl_basic_map_free(res);
12982 return NULL;
12985 /* Compute the preimage of "bset" under the function represented by "ma".
12986 * In other words, plug in "ma" in "bset". The result is a basic set
12987 * that lives in the domain space of "ma".
12989 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
12990 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
12992 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
12995 /* Compute the preimage of the domain of "bmap" under the function
12996 * represented by "ma".
12997 * In other words, plug in "ma" in the domain of "bmap".
12998 * The result is a basic map that lives in the same space as "bmap"
12999 * except that the domain has been replaced by the domain space of "ma".
13001 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13002 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13004 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13007 /* Compute the preimage of the range of "bmap" under the function
13008 * represented by "ma".
13009 * In other words, plug in "ma" in the range of "bmap".
13010 * The result is a basic map that lives in the same space as "bmap"
13011 * except that the range has been replaced by the domain space of "ma".
13013 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13014 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13016 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13019 /* Check if the range of "ma" is compatible with the domain or range
13020 * (depending on "type") of "map".
13021 * Return isl_stat_error if anything is wrong.
13023 static isl_stat check_map_compatible_range_multi_aff(
13024 __isl_keep isl_map *map, enum isl_dim_type type,
13025 __isl_keep isl_multi_aff *ma)
13027 isl_bool m;
13028 isl_space *ma_space;
13030 ma_space = isl_multi_aff_get_space(ma);
13031 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
13032 isl_space_free(ma_space);
13033 if (m < 0)
13034 return isl_stat_error;
13035 if (!m)
13036 isl_die(isl_map_get_ctx(map), isl_error_invalid,
13037 "spaces don't match", return isl_stat_error);
13038 return isl_stat_ok;
13041 /* Compute the preimage of the domain or range (depending on "type")
13042 * of "map" under the function represented by "ma".
13043 * In other words, plug in "ma" in the domain or range of "map".
13044 * The result is a map that lives in the same space as "map"
13045 * except that the domain or range has been replaced by
13046 * the domain space of "ma".
13048 * The parameters are assumed to have been aligned.
13050 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13051 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13053 int i;
13054 isl_space *space;
13056 map = isl_map_cow(map);
13057 ma = isl_multi_aff_align_divs(ma);
13058 if (!map || !ma)
13059 goto error;
13060 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13061 goto error;
13063 for (i = 0; i < map->n; ++i) {
13064 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13065 isl_multi_aff_copy(ma));
13066 if (!map->p[i])
13067 goto error;
13070 space = isl_multi_aff_get_domain_space(ma);
13071 space = isl_space_set(isl_map_get_space(map), type, space);
13073 isl_space_free(map->dim);
13074 map->dim = space;
13075 if (!map->dim)
13076 goto error;
13078 isl_multi_aff_free(ma);
13079 if (map->n > 1)
13080 ISL_F_CLR(map, ISL_MAP_DISJOINT);
13081 ISL_F_CLR(map, ISL_SET_NORMALIZED);
13082 return map;
13083 error:
13084 isl_multi_aff_free(ma);
13085 isl_map_free(map);
13086 return NULL;
13089 /* Compute the preimage of the domain or range (depending on "type")
13090 * of "map" under the function represented by "ma".
13091 * In other words, plug in "ma" in the domain or range of "map".
13092 * The result is a map that lives in the same space as "map"
13093 * except that the domain or range has been replaced by
13094 * the domain space of "ma".
13096 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13097 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13099 isl_bool aligned;
13101 if (!map || !ma)
13102 goto error;
13104 aligned = isl_map_space_has_equal_params(map, ma->space);
13105 if (aligned < 0)
13106 goto error;
13107 if (aligned)
13108 return map_preimage_multi_aff(map, type, ma);
13110 if (isl_map_check_named_params(map) < 0)
13111 goto error;
13112 if (!isl_space_has_named_params(ma->space))
13113 isl_die(map->ctx, isl_error_invalid,
13114 "unaligned unnamed parameters", goto error);
13115 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13116 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13118 return map_preimage_multi_aff(map, type, ma);
13119 error:
13120 isl_multi_aff_free(ma);
13121 return isl_map_free(map);
13124 /* Compute the preimage of "set" under the function represented by "ma".
13125 * In other words, plug in "ma" in "set". The result is a set
13126 * that lives in the domain space of "ma".
13128 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13129 __isl_take isl_multi_aff *ma)
13131 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13134 /* Compute the preimage of the domain of "map" under the function
13135 * represented by "ma".
13136 * In other words, plug in "ma" in the domain of "map".
13137 * The result is a map that lives in the same space as "map"
13138 * except that the domain has been replaced by the domain space of "ma".
13140 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13141 __isl_take isl_multi_aff *ma)
13143 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13146 /* Compute the preimage of the range of "map" under the function
13147 * represented by "ma".
13148 * In other words, plug in "ma" in the range of "map".
13149 * The result is a map that lives in the same space as "map"
13150 * except that the range has been replaced by the domain space of "ma".
13152 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13153 __isl_take isl_multi_aff *ma)
13155 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
13158 /* Compute the preimage of "map" under the function represented by "pma".
13159 * In other words, plug in "pma" in the domain or range of "map".
13160 * The result is a map that lives in the same space as "map",
13161 * except that the space of type "type" has been replaced by
13162 * the domain space of "pma".
13164 * The parameters of "map" and "pma" are assumed to have been aligned.
13166 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
13167 __isl_take isl_map *map, enum isl_dim_type type,
13168 __isl_take isl_pw_multi_aff *pma)
13170 int i;
13171 isl_map *res;
13173 if (!pma)
13174 goto error;
13176 if (pma->n == 0) {
13177 isl_pw_multi_aff_free(pma);
13178 res = isl_map_empty(isl_map_get_space(map));
13179 isl_map_free(map);
13180 return res;
13183 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13184 isl_multi_aff_copy(pma->p[0].maff));
13185 if (type == isl_dim_in)
13186 res = isl_map_intersect_domain(res,
13187 isl_map_copy(pma->p[0].set));
13188 else
13189 res = isl_map_intersect_range(res,
13190 isl_map_copy(pma->p[0].set));
13192 for (i = 1; i < pma->n; ++i) {
13193 isl_map *res_i;
13195 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13196 isl_multi_aff_copy(pma->p[i].maff));
13197 if (type == isl_dim_in)
13198 res_i = isl_map_intersect_domain(res_i,
13199 isl_map_copy(pma->p[i].set));
13200 else
13201 res_i = isl_map_intersect_range(res_i,
13202 isl_map_copy(pma->p[i].set));
13203 res = isl_map_union(res, res_i);
13206 isl_pw_multi_aff_free(pma);
13207 isl_map_free(map);
13208 return res;
13209 error:
13210 isl_pw_multi_aff_free(pma);
13211 isl_map_free(map);
13212 return NULL;
13215 /* Compute the preimage of "map" under the function represented by "pma".
13216 * In other words, plug in "pma" in the domain or range of "map".
13217 * The result is a map that lives in the same space as "map",
13218 * except that the space of type "type" has been replaced by
13219 * the domain space of "pma".
13221 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
13222 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
13224 isl_bool aligned;
13226 if (!map || !pma)
13227 goto error;
13229 aligned = isl_map_space_has_equal_params(map, pma->dim);
13230 if (aligned < 0)
13231 goto error;
13232 if (aligned)
13233 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13235 if (isl_map_check_named_params(map) < 0)
13236 goto error;
13237 if (isl_pw_multi_aff_check_named_params(pma) < 0)
13238 goto error;
13239 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
13240 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
13242 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13243 error:
13244 isl_pw_multi_aff_free(pma);
13245 return isl_map_free(map);
13248 /* Compute the preimage of "set" under the function represented by "pma".
13249 * In other words, plug in "pma" in "set". The result is a set
13250 * that lives in the domain space of "pma".
13252 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
13253 __isl_take isl_pw_multi_aff *pma)
13255 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
13258 /* Compute the preimage of the domain of "map" under the function
13259 * represented by "pma".
13260 * In other words, plug in "pma" in the domain of "map".
13261 * The result is a map that lives in the same space as "map",
13262 * except that domain space has been replaced by the domain space of "pma".
13264 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
13265 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13267 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
13270 /* Compute the preimage of the range of "map" under the function
13271 * represented by "pma".
13272 * In other words, plug in "pma" in the range of "map".
13273 * The result is a map that lives in the same space as "map",
13274 * except that range space has been replaced by the domain space of "pma".
13276 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
13277 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13279 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
13282 /* Compute the preimage of "map" under the function represented by "mpa".
13283 * In other words, plug in "mpa" in the domain or range of "map".
13284 * The result is a map that lives in the same space as "map",
13285 * except that the space of type "type" has been replaced by
13286 * the domain space of "mpa".
13288 * If the map does not involve any constraints that refer to the
13289 * dimensions of the substituted space, then the only possible
13290 * effect of "mpa" on the map is to map the space to a different space.
13291 * We create a separate isl_multi_aff to effectuate this change
13292 * in order to avoid spurious splitting of the map along the pieces
13293 * of "mpa".
13294 * If "mpa" has a non-trivial explicit domain, however,
13295 * then the full substitution should be performed.
13297 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
13298 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
13300 int n;
13301 isl_bool full;
13302 isl_pw_multi_aff *pma;
13304 if (!map || !mpa)
13305 goto error;
13307 n = isl_map_dim(map, type);
13308 full = isl_map_involves_dims(map, type, 0, n);
13309 if (full >= 0 && !full)
13310 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
13311 if (full < 0)
13312 goto error;
13313 if (!full) {
13314 isl_space *space;
13315 isl_multi_aff *ma;
13317 space = isl_multi_pw_aff_get_space(mpa);
13318 isl_multi_pw_aff_free(mpa);
13319 ma = isl_multi_aff_zero(space);
13320 return isl_map_preimage_multi_aff(map, type, ma);
13323 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
13324 return isl_map_preimage_pw_multi_aff(map, type, pma);
13325 error:
13326 isl_map_free(map);
13327 isl_multi_pw_aff_free(mpa);
13328 return NULL;
13331 /* Compute the preimage of "map" under the function represented by "mpa".
13332 * In other words, plug in "mpa" in the domain "map".
13333 * The result is a map that lives in the same space as "map",
13334 * except that domain space has been replaced by the domain space of "mpa".
13336 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
13337 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
13339 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
13342 /* Compute the preimage of "set" by the function represented by "mpa".
13343 * In other words, plug in "mpa" in "set".
13345 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
13346 __isl_take isl_multi_pw_aff *mpa)
13348 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
13351 /* Return a copy of the equality constraints of "bset" as a matrix.
13353 __isl_give isl_mat *isl_basic_set_extract_equalities(
13354 __isl_keep isl_basic_set *bset)
13356 isl_ctx *ctx;
13357 unsigned total;
13359 if (!bset)
13360 return NULL;
13362 ctx = isl_basic_set_get_ctx(bset);
13363 total = 1 + isl_basic_set_dim(bset, isl_dim_all);
13364 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
13367 /* Are the "n" "coefficients" starting at "first" of the integer division
13368 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
13369 * to each other?
13370 * The "coefficient" at position 0 is the denominator.
13371 * The "coefficient" at position 1 is the constant term.
13373 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
13374 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
13375 unsigned first, unsigned n)
13377 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
13378 return isl_bool_error;
13379 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
13380 return isl_bool_error;
13381 return isl_seq_eq(bmap1->div[pos1] + first,
13382 bmap2->div[pos2] + first, n);
13385 /* Are the integer division expressions at position "pos1" in "bmap1" and
13386 * "pos2" in "bmap2" equal to each other, except that the constant terms
13387 * are different?
13389 isl_bool isl_basic_map_equal_div_expr_except_constant(
13390 __isl_keep isl_basic_map *bmap1, int pos1,
13391 __isl_keep isl_basic_map *bmap2, int pos2)
13393 isl_bool equal;
13394 unsigned total;
13396 if (!bmap1 || !bmap2)
13397 return isl_bool_error;
13398 total = isl_basic_map_total_dim(bmap1);
13399 if (total != isl_basic_map_total_dim(bmap2))
13400 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
13401 "incomparable div expressions", return isl_bool_error);
13402 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13403 0, 1);
13404 if (equal < 0 || !equal)
13405 return equal;
13406 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13407 1, 1);
13408 if (equal < 0 || equal)
13409 return isl_bool_not(equal);
13410 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13411 2, total);
13414 /* Replace the numerator of the constant term of the integer division
13415 * expression at position "div" in "bmap" by "value".
13416 * The caller guarantees that this does not change the meaning
13417 * of the input.
13419 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
13420 __isl_take isl_basic_map *bmap, int div, int value)
13422 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
13423 return isl_basic_map_free(bmap);
13425 isl_int_set_si(bmap->div[div][1], value);
13427 return bmap;
13430 /* Is the point "inner" internal to inequality constraint "ineq"
13431 * of "bset"?
13432 * The point is considered to be internal to the inequality constraint,
13433 * if it strictly lies on the positive side of the inequality constraint,
13434 * or if it lies on the constraint and the constraint is lexico-positive.
13436 static isl_bool is_internal(__isl_keep isl_vec *inner,
13437 __isl_keep isl_basic_set *bset, int ineq)
13439 isl_ctx *ctx;
13440 int pos;
13441 unsigned total;
13443 if (!inner || !bset)
13444 return isl_bool_error;
13446 ctx = isl_basic_set_get_ctx(bset);
13447 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13448 &ctx->normalize_gcd);
13449 if (!isl_int_is_zero(ctx->normalize_gcd))
13450 return isl_int_is_nonneg(ctx->normalize_gcd);
13452 total = isl_basic_set_dim(bset, isl_dim_all);
13453 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13454 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13457 /* Tighten the inequality constraints of "bset" that are outward with respect
13458 * to the point "vec".
13459 * That is, tighten the constraints that are not satisfied by "vec".
13461 * "vec" is a point internal to some superset S of "bset" that is used
13462 * to make the subsets of S disjoint, by tightening one half of the constraints
13463 * that separate two subsets. In particular, the constraints of S
13464 * are all satisfied by "vec" and should not be tightened.
13465 * Of the internal constraints, those that have "vec" on the outside
13466 * are tightened. The shared facet is included in the adjacent subset
13467 * with the opposite constraint.
13468 * For constraints that saturate "vec", this criterion cannot be used
13469 * to determine which of the two sides should be tightened.
13470 * Instead, the sign of the first non-zero coefficient is used
13471 * to make this choice. Note that this second criterion is never used
13472 * on the constraints of S since "vec" is interior to "S".
13474 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13475 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13477 int j;
13479 bset = isl_basic_set_cow(bset);
13480 if (!bset)
13481 return NULL;
13482 for (j = 0; j < bset->n_ineq; ++j) {
13483 isl_bool internal;
13485 internal = is_internal(vec, bset, j);
13486 if (internal < 0)
13487 return isl_basic_set_free(bset);
13488 if (internal)
13489 continue;
13490 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13493 return bset;
13496 /* Replace the variables x of type "type" starting at "first" in "bmap"
13497 * by x' with x = M x' with M the matrix trans.
13498 * That is, replace the corresponding coefficients c by c M.
13500 * The transformation matrix should be a square matrix.
13502 __isl_give isl_basic_map *isl_basic_map_transform_dims(
13503 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
13504 __isl_take isl_mat *trans)
13506 unsigned pos;
13508 bmap = isl_basic_map_cow(bmap);
13509 if (!bmap || !trans)
13510 goto error;
13512 if (trans->n_row != trans->n_col)
13513 isl_die(trans->ctx, isl_error_invalid,
13514 "expecting square transformation matrix", goto error);
13515 if (first + trans->n_row > isl_basic_map_dim(bmap, type))
13516 isl_die(trans->ctx, isl_error_invalid,
13517 "oversized transformation matrix", goto error);
13519 pos = isl_basic_map_offset(bmap, type) + first;
13521 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
13522 isl_mat_copy(trans)) < 0)
13523 goto error;
13524 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
13525 isl_mat_copy(trans)) < 0)
13526 goto error;
13527 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
13528 isl_mat_copy(trans)) < 0)
13529 goto error;
13531 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
13532 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
13534 isl_mat_free(trans);
13535 return bmap;
13536 error:
13537 isl_mat_free(trans);
13538 isl_basic_map_free(bmap);
13539 return NULL;
13542 /* Replace the variables x of type "type" starting at "first" in "bset"
13543 * by x' with x = M x' with M the matrix trans.
13544 * That is, replace the corresponding coefficients c by c M.
13546 * The transformation matrix should be a square matrix.
13548 __isl_give isl_basic_set *isl_basic_set_transform_dims(
13549 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
13550 __isl_take isl_mat *trans)
13552 return isl_basic_map_transform_dims(bset, type, first, trans);