isl_map.c: extract out shared isl_basic_map_has_equal_params
[isl.git] / isl_map.c
blob5da873f99ad74a98ad0f4fd2f2ec1fed0ce02550
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/constraint.h>
27 #include "isl_space_private.h"
28 #include "isl_equalities.h"
29 #include <isl_lp_private.h>
30 #include <isl_seq.h>
31 #include <isl/set.h>
32 #include <isl/map.h>
33 #include <isl_reordering.h>
34 #include "isl_sample.h"
35 #include <isl_sort.h>
36 #include "isl_tab.h"
37 #include <isl/vec.h>
38 #include <isl_mat_private.h>
39 #include <isl_vec_private.h>
40 #include <isl_dim_map.h>
41 #include <isl_local_space_private.h>
42 #include <isl_aff_private.h>
43 #include <isl_options_private.h>
44 #include <isl_morph.h>
45 #include <isl_val_private.h>
46 #include <isl/deprecated/map_int.h>
47 #include <isl/deprecated/set_int.h>
49 #include <bset_to_bmap.c>
50 #include <bset_from_bmap.c>
51 #include <set_to_map.c>
52 #include <set_from_map.c>
54 static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
56 switch (type) {
57 case isl_dim_param: return dim->nparam;
58 case isl_dim_in: return dim->n_in;
59 case isl_dim_out: return dim->n_out;
60 case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
61 default: return 0;
65 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
67 switch (type) {
68 case isl_dim_param: return 1;
69 case isl_dim_in: return 1 + dim->nparam;
70 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
71 default: return 0;
75 unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
76 enum isl_dim_type type)
78 if (!bmap)
79 return 0;
80 switch (type) {
81 case isl_dim_cst: return 1;
82 case isl_dim_param:
83 case isl_dim_in:
84 case isl_dim_out: return isl_space_dim(bmap->dim, type);
85 case isl_dim_div: return bmap->n_div;
86 case isl_dim_all: return isl_basic_map_total_dim(bmap);
87 default: return 0;
91 /* Return the space of "map".
93 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
95 return map ? map->dim : NULL;
98 unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
100 return map ? n(map->dim, type) : 0;
103 unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
105 return set ? n(set->dim, type) : 0;
108 unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
109 enum isl_dim_type type)
111 isl_space *space;
113 if (!bmap)
114 return 0;
116 space = bmap->dim;
117 switch (type) {
118 case isl_dim_cst: return 0;
119 case isl_dim_param: return 1;
120 case isl_dim_in: return 1 + space->nparam;
121 case isl_dim_out: return 1 + space->nparam + space->n_in;
122 case isl_dim_div: return 1 + space->nparam + space->n_in +
123 space->n_out;
124 default: return 0;
128 unsigned isl_basic_set_offset(struct isl_basic_set *bset,
129 enum isl_dim_type type)
131 return isl_basic_map_offset(bset, type);
134 static unsigned map_offset(struct isl_map *map, enum isl_dim_type type)
136 return pos(map->dim, type);
139 unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
140 enum isl_dim_type type)
142 return isl_basic_map_dim(bset, type);
145 unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
147 return isl_basic_set_dim(bset, isl_dim_set);
150 unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
152 return isl_basic_set_dim(bset, isl_dim_param);
155 unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset)
157 if (!bset)
158 return 0;
159 return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
162 unsigned isl_set_n_dim(__isl_keep isl_set *set)
164 return isl_set_dim(set, isl_dim_set);
167 unsigned isl_set_n_param(__isl_keep isl_set *set)
169 return isl_set_dim(set, isl_dim_param);
172 unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap)
174 return bmap ? bmap->dim->n_in : 0;
177 unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap)
179 return bmap ? bmap->dim->n_out : 0;
182 unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap)
184 return bmap ? bmap->dim->nparam : 0;
187 unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap)
189 return bmap ? bmap->n_div : 0;
192 unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap)
194 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
197 unsigned isl_map_n_in(const struct isl_map *map)
199 return map ? map->dim->n_in : 0;
202 unsigned isl_map_n_out(const struct isl_map *map)
204 return map ? map->dim->n_out : 0;
207 unsigned isl_map_n_param(const struct isl_map *map)
209 return map ? map->dim->nparam : 0;
212 /* Do "bmap1" and "bmap2" have the same parameters?
214 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
215 __isl_keep isl_basic_map *bmap2)
217 isl_space *space1, *space2;
219 space1 = isl_basic_map_peek_space(bmap1);
220 space2 = isl_basic_map_peek_space(bmap2);
221 return isl_space_match(space1, isl_dim_param, space2, isl_dim_param);
224 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
225 __isl_keep isl_set *set)
227 isl_bool m;
228 if (!map || !set)
229 return isl_bool_error;
230 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
231 if (m < 0 || !m)
232 return m;
233 return isl_space_tuple_is_equal(map->dim, isl_dim_in,
234 set->dim, isl_dim_set);
237 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
238 __isl_keep isl_basic_set *bset)
240 isl_bool m;
241 if (!bmap || !bset)
242 return isl_bool_error;
243 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
244 if (m < 0 || !m)
245 return m;
246 return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
247 bset->dim, isl_dim_set);
250 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
251 __isl_keep isl_set *set)
253 isl_bool m;
254 if (!map || !set)
255 return isl_bool_error;
256 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
257 if (m < 0 || !m)
258 return m;
259 return isl_space_tuple_is_equal(map->dim, isl_dim_out,
260 set->dim, isl_dim_set);
263 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
264 __isl_keep isl_basic_set *bset)
266 isl_bool m;
267 if (!bmap || !bset)
268 return isl_bool_error;
269 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
270 if (m < 0 || !m)
271 return m;
272 return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
273 bset->dim, isl_dim_set);
276 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
278 return bmap ? bmap->ctx : NULL;
281 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
283 return bset ? bset->ctx : NULL;
286 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
288 return map ? map->ctx : NULL;
291 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
293 return set ? set->ctx : NULL;
296 /* Return the space of "bmap".
298 __isl_keep isl_space *isl_basic_map_peek_space(
299 __isl_keep const isl_basic_map *bmap)
301 return bmap ? bmap->dim : NULL;
304 /* Return the space of "bset".
306 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
308 return isl_basic_map_peek_space(bset_to_bmap(bset));
311 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
313 return isl_space_copy(isl_basic_map_peek_space(bmap));
316 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
318 return isl_basic_map_get_space(bset_to_bmap(bset));
321 /* Extract the divs in "bmap" as a matrix.
323 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
325 int i;
326 isl_ctx *ctx;
327 isl_mat *div;
328 unsigned total;
329 unsigned cols;
331 if (!bmap)
332 return NULL;
334 ctx = isl_basic_map_get_ctx(bmap);
335 total = isl_space_dim(bmap->dim, isl_dim_all);
336 cols = 1 + 1 + total + bmap->n_div;
337 div = isl_mat_alloc(ctx, bmap->n_div, cols);
338 if (!div)
339 return NULL;
341 for (i = 0; i < bmap->n_div; ++i)
342 isl_seq_cpy(div->row[i], bmap->div[i], cols);
344 return div;
347 /* Extract the divs in "bset" as a matrix.
349 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
351 return isl_basic_map_get_divs(bset);
354 __isl_give isl_local_space *isl_basic_map_get_local_space(
355 __isl_keep isl_basic_map *bmap)
357 isl_mat *div;
359 if (!bmap)
360 return NULL;
362 div = isl_basic_map_get_divs(bmap);
363 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
366 __isl_give isl_local_space *isl_basic_set_get_local_space(
367 __isl_keep isl_basic_set *bset)
369 return isl_basic_map_get_local_space(bset);
372 /* For each known div d = floor(f/m), add the constraints
374 * f - m d >= 0
375 * -(f-(m-1)) + m d >= 0
377 * Do not finalize the result.
379 static __isl_give isl_basic_map *add_known_div_constraints(
380 __isl_take isl_basic_map *bmap)
382 int i;
383 unsigned n_div;
385 if (!bmap)
386 return NULL;
387 n_div = isl_basic_map_dim(bmap, isl_dim_div);
388 if (n_div == 0)
389 return bmap;
390 bmap = isl_basic_map_cow(bmap);
391 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
392 if (!bmap)
393 return NULL;
394 for (i = 0; i < n_div; ++i) {
395 if (isl_int_is_zero(bmap->div[i][0]))
396 continue;
397 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
398 return isl_basic_map_free(bmap);
401 return bmap;
404 __isl_give isl_basic_map *isl_basic_map_from_local_space(
405 __isl_take isl_local_space *ls)
407 int i;
408 int n_div;
409 isl_basic_map *bmap;
411 if (!ls)
412 return NULL;
414 n_div = isl_local_space_dim(ls, isl_dim_div);
415 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
416 n_div, 0, 2 * n_div);
418 for (i = 0; i < n_div; ++i)
419 if (isl_basic_map_alloc_div(bmap) < 0)
420 goto error;
422 for (i = 0; i < n_div; ++i)
423 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
424 bmap = add_known_div_constraints(bmap);
426 isl_local_space_free(ls);
427 return bmap;
428 error:
429 isl_local_space_free(ls);
430 isl_basic_map_free(bmap);
431 return NULL;
434 __isl_give isl_basic_set *isl_basic_set_from_local_space(
435 __isl_take isl_local_space *ls)
437 return isl_basic_map_from_local_space(ls);
440 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
442 return isl_space_copy(isl_map_peek_space(map));
445 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
447 if (!set)
448 return NULL;
449 return isl_space_copy(set->dim);
452 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
453 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
455 bmap = isl_basic_map_cow(bmap);
456 if (!bmap)
457 return NULL;
458 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
459 if (!bmap->dim)
460 goto error;
461 bmap = isl_basic_map_finalize(bmap);
462 return bmap;
463 error:
464 isl_basic_map_free(bmap);
465 return NULL;
468 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
469 __isl_take isl_basic_set *bset, const char *s)
471 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
474 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
475 enum isl_dim_type type)
477 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
480 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
481 enum isl_dim_type type, const char *s)
483 int i;
485 map = isl_map_cow(map);
486 if (!map)
487 return NULL;
489 map->dim = isl_space_set_tuple_name(map->dim, type, s);
490 if (!map->dim)
491 goto error;
493 for (i = 0; i < map->n; ++i) {
494 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
495 if (!map->p[i])
496 goto error;
499 return map;
500 error:
501 isl_map_free(map);
502 return NULL;
505 /* Replace the identifier of the tuple of type "type" by "id".
507 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
508 __isl_take isl_basic_map *bmap,
509 enum isl_dim_type type, __isl_take isl_id *id)
511 bmap = isl_basic_map_cow(bmap);
512 if (!bmap)
513 goto error;
514 bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
515 if (!bmap->dim)
516 return isl_basic_map_free(bmap);
517 bmap = isl_basic_map_finalize(bmap);
518 return bmap;
519 error:
520 isl_id_free(id);
521 return NULL;
524 /* Replace the identifier of the tuple by "id".
526 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
527 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
529 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
532 /* Does the input or output tuple have a name?
534 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
536 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
539 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
540 enum isl_dim_type type)
542 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
545 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
546 const char *s)
548 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
549 isl_dim_set, s));
552 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
553 enum isl_dim_type type, __isl_take isl_id *id)
555 map = isl_map_cow(map);
556 if (!map)
557 goto error;
559 map->dim = isl_space_set_tuple_id(map->dim, type, id);
561 return isl_map_reset_space(map, isl_space_copy(map->dim));
562 error:
563 isl_id_free(id);
564 return NULL;
567 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
568 __isl_take isl_id *id)
570 return isl_map_set_tuple_id(set, isl_dim_set, id);
573 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
574 enum isl_dim_type type)
576 map = isl_map_cow(map);
577 if (!map)
578 return NULL;
580 map->dim = isl_space_reset_tuple_id(map->dim, type);
582 return isl_map_reset_space(map, isl_space_copy(map->dim));
585 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
587 return isl_map_reset_tuple_id(set, isl_dim_set);
590 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
592 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
595 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
596 enum isl_dim_type type)
598 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
601 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
603 return isl_map_has_tuple_id(set, isl_dim_set);
606 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
608 return isl_map_get_tuple_id(set, isl_dim_set);
611 /* Does the set tuple have a name?
613 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
615 if (!set)
616 return isl_bool_error;
617 return isl_space_has_tuple_name(set->dim, isl_dim_set);
621 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
623 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
626 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
628 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
631 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
632 enum isl_dim_type type, unsigned pos)
634 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
637 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
638 enum isl_dim_type type, unsigned pos)
640 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
643 /* Does the given dimension have a name?
645 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
646 enum isl_dim_type type, unsigned pos)
648 if (!map)
649 return isl_bool_error;
650 return isl_space_has_dim_name(map->dim, type, pos);
653 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
654 enum isl_dim_type type, unsigned pos)
656 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
659 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
660 enum isl_dim_type type, unsigned pos)
662 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
665 /* Does the given dimension have a name?
667 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
668 enum isl_dim_type type, unsigned pos)
670 if (!set)
671 return isl_bool_error;
672 return isl_space_has_dim_name(set->dim, type, pos);
675 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
676 __isl_take isl_basic_map *bmap,
677 enum isl_dim_type type, unsigned pos, const char *s)
679 bmap = isl_basic_map_cow(bmap);
680 if (!bmap)
681 return NULL;
682 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
683 if (!bmap->dim)
684 goto error;
685 return isl_basic_map_finalize(bmap);
686 error:
687 isl_basic_map_free(bmap);
688 return NULL;
691 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
692 enum isl_dim_type type, unsigned pos, const char *s)
694 int i;
696 map = isl_map_cow(map);
697 if (!map)
698 return NULL;
700 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
701 if (!map->dim)
702 goto error;
704 for (i = 0; i < map->n; ++i) {
705 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
706 if (!map->p[i])
707 goto error;
710 return map;
711 error:
712 isl_map_free(map);
713 return NULL;
716 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
717 __isl_take isl_basic_set *bset,
718 enum isl_dim_type type, unsigned pos, const char *s)
720 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
721 type, pos, s));
724 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
725 enum isl_dim_type type, unsigned pos, const char *s)
727 return set_from_map(isl_map_set_dim_name(set_to_map(set),
728 type, pos, s));
731 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
732 enum isl_dim_type type, unsigned pos)
734 if (!bmap)
735 return isl_bool_error;
736 return isl_space_has_dim_id(bmap->dim, type, pos);
739 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
740 enum isl_dim_type type, unsigned pos)
742 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
745 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
746 enum isl_dim_type type, unsigned pos)
748 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
751 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
752 enum isl_dim_type type, unsigned pos)
754 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
757 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
758 enum isl_dim_type type, unsigned pos)
760 return isl_map_has_dim_id(set, type, pos);
763 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
764 enum isl_dim_type type, unsigned pos)
766 return isl_map_get_dim_id(set, type, pos);
769 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
770 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
772 map = isl_map_cow(map);
773 if (!map)
774 goto error;
776 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
778 return isl_map_reset_space(map, isl_space_copy(map->dim));
779 error:
780 isl_id_free(id);
781 return NULL;
784 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
785 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
787 return isl_map_set_dim_id(set, type, pos, id);
790 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
791 __isl_keep isl_id *id)
793 if (!map)
794 return -1;
795 return isl_space_find_dim_by_id(map->dim, type, id);
798 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
799 __isl_keep isl_id *id)
801 return isl_map_find_dim_by_id(set, type, id);
804 /* Return the position of the dimension of the given type and name
805 * in "bmap".
806 * Return -1 if no such dimension can be found.
808 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
809 enum isl_dim_type type, const char *name)
811 if (!bmap)
812 return -1;
813 return isl_space_find_dim_by_name(bmap->dim, type, name);
816 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
817 const char *name)
819 if (!map)
820 return -1;
821 return isl_space_find_dim_by_name(map->dim, type, name);
824 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
825 const char *name)
827 return isl_map_find_dim_by_name(set, type, name);
830 /* Reset the user pointer on all identifiers of parameters and tuples
831 * of the space of "map".
833 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
835 isl_space *space;
837 space = isl_map_get_space(map);
838 space = isl_space_reset_user(space);
839 map = isl_map_reset_space(map, space);
841 return map;
844 /* Reset the user pointer on all identifiers of parameters and tuples
845 * of the space of "set".
847 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
849 return isl_map_reset_user(set);
852 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
854 if (!bmap)
855 return isl_bool_error;
856 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
859 /* Has "map" been marked as a rational map?
860 * In particular, have all basic maps in "map" been marked this way?
861 * An empty map is not considered to be rational.
862 * Maps where only some of the basic maps are marked rational
863 * are not allowed.
865 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
867 int i;
868 isl_bool rational;
870 if (!map)
871 return isl_bool_error;
872 if (map->n == 0)
873 return isl_bool_false;
874 rational = isl_basic_map_is_rational(map->p[0]);
875 if (rational < 0)
876 return rational;
877 for (i = 1; i < map->n; ++i) {
878 isl_bool rational_i;
880 rational_i = isl_basic_map_is_rational(map->p[i]);
881 if (rational_i < 0)
882 return rational_i;
883 if (rational != rational_i)
884 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
885 "mixed rational and integer basic maps "
886 "not supported", return isl_bool_error);
889 return rational;
892 /* Has "set" been marked as a rational set?
893 * In particular, have all basic set in "set" been marked this way?
894 * An empty set is not considered to be rational.
895 * Sets where only some of the basic sets are marked rational
896 * are not allowed.
898 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
900 return isl_map_is_rational(set);
903 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
905 return isl_basic_map_is_rational(bset);
908 /* Does "bmap" contain any rational points?
910 * If "bmap" has an equality for each dimension, equating the dimension
911 * to an integer constant, then it has no rational points, even if it
912 * is marked as rational.
914 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
916 isl_bool has_rational = isl_bool_true;
917 unsigned total;
919 if (!bmap)
920 return isl_bool_error;
921 if (isl_basic_map_plain_is_empty(bmap))
922 return isl_bool_false;
923 if (!isl_basic_map_is_rational(bmap))
924 return isl_bool_false;
925 bmap = isl_basic_map_copy(bmap);
926 bmap = isl_basic_map_implicit_equalities(bmap);
927 if (!bmap)
928 return isl_bool_error;
929 total = isl_basic_map_total_dim(bmap);
930 if (bmap->n_eq == total) {
931 int i, j;
932 for (i = 0; i < bmap->n_eq; ++i) {
933 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
934 if (j < 0)
935 break;
936 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
937 !isl_int_is_negone(bmap->eq[i][1 + j]))
938 break;
939 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
940 total - j - 1);
941 if (j >= 0)
942 break;
944 if (i == bmap->n_eq)
945 has_rational = isl_bool_false;
947 isl_basic_map_free(bmap);
949 return has_rational;
952 /* Does "map" contain any rational points?
954 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
956 int i;
957 isl_bool has_rational;
959 if (!map)
960 return isl_bool_error;
961 for (i = 0; i < map->n; ++i) {
962 has_rational = isl_basic_map_has_rational(map->p[i]);
963 if (has_rational < 0 || has_rational)
964 return has_rational;
966 return isl_bool_false;
969 /* Does "set" contain any rational points?
971 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
973 return isl_map_has_rational(set);
976 /* Is this basic set a parameter domain?
978 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
980 if (!bset)
981 return isl_bool_error;
982 return isl_space_is_params(bset->dim);
985 /* Is this set a parameter domain?
987 isl_bool isl_set_is_params(__isl_keep isl_set *set)
989 if (!set)
990 return isl_bool_error;
991 return isl_space_is_params(set->dim);
994 /* Is this map actually a parameter domain?
995 * Users should never call this function. Outside of isl,
996 * a map can never be a parameter domain.
998 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1000 if (!map)
1001 return isl_bool_error;
1002 return isl_space_is_params(map->dim);
1005 static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
1006 struct isl_basic_map *bmap, unsigned extra,
1007 unsigned n_eq, unsigned n_ineq)
1009 int i;
1010 size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
1012 bmap->ctx = ctx;
1013 isl_ctx_ref(ctx);
1015 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1016 if (isl_blk_is_error(bmap->block))
1017 goto error;
1019 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1020 if ((n_ineq + n_eq) && !bmap->ineq)
1021 goto error;
1023 if (extra == 0) {
1024 bmap->block2 = isl_blk_empty();
1025 bmap->div = NULL;
1026 } else {
1027 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1028 if (isl_blk_is_error(bmap->block2))
1029 goto error;
1031 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1032 if (!bmap->div)
1033 goto error;
1036 for (i = 0; i < n_ineq + n_eq; ++i)
1037 bmap->ineq[i] = bmap->block.data + i * row_size;
1039 for (i = 0; i < extra; ++i)
1040 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1042 bmap->ref = 1;
1043 bmap->flags = 0;
1044 bmap->c_size = n_eq + n_ineq;
1045 bmap->eq = bmap->ineq + n_ineq;
1046 bmap->extra = extra;
1047 bmap->n_eq = 0;
1048 bmap->n_ineq = 0;
1049 bmap->n_div = 0;
1050 bmap->sample = NULL;
1052 return bmap;
1053 error:
1054 isl_basic_map_free(bmap);
1055 return NULL;
1058 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1059 unsigned nparam, unsigned dim, unsigned extra,
1060 unsigned n_eq, unsigned n_ineq)
1062 struct isl_basic_map *bmap;
1063 isl_space *space;
1065 space = isl_space_set_alloc(ctx, nparam, dim);
1066 if (!space)
1067 return NULL;
1069 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1070 return bset_from_bmap(bmap);
1073 struct isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1074 unsigned extra, unsigned n_eq, unsigned n_ineq)
1076 struct isl_basic_map *bmap;
1077 if (!dim)
1078 return NULL;
1079 isl_assert(dim->ctx, dim->n_in == 0, goto error);
1080 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1081 return bset_from_bmap(bmap);
1082 error:
1083 isl_space_free(dim);
1084 return NULL;
1087 struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
1088 unsigned extra, unsigned n_eq, unsigned n_ineq)
1090 struct isl_basic_map *bmap;
1092 if (!dim)
1093 return NULL;
1094 bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
1095 if (!bmap)
1096 goto error;
1097 bmap->dim = dim;
1099 return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
1100 error:
1101 isl_space_free(dim);
1102 return NULL;
1105 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1106 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1107 unsigned n_eq, unsigned n_ineq)
1109 struct isl_basic_map *bmap;
1110 isl_space *dim;
1112 dim = isl_space_alloc(ctx, nparam, in, out);
1113 if (!dim)
1114 return NULL;
1116 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1117 return bmap;
1120 static void dup_constraints(
1121 struct isl_basic_map *dst, struct isl_basic_map *src)
1123 int i;
1124 unsigned total = isl_basic_map_total_dim(src);
1126 for (i = 0; i < src->n_eq; ++i) {
1127 int j = isl_basic_map_alloc_equality(dst);
1128 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1131 for (i = 0; i < src->n_ineq; ++i) {
1132 int j = isl_basic_map_alloc_inequality(dst);
1133 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1136 for (i = 0; i < src->n_div; ++i) {
1137 int j = isl_basic_map_alloc_div(dst);
1138 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1140 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1143 struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap)
1145 struct isl_basic_map *dup;
1147 if (!bmap)
1148 return NULL;
1149 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1150 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1151 if (!dup)
1152 return NULL;
1153 dup_constraints(dup, bmap);
1154 dup->flags = bmap->flags;
1155 dup->sample = isl_vec_copy(bmap->sample);
1156 return dup;
1159 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1161 struct isl_basic_map *dup;
1163 dup = isl_basic_map_dup(bset_to_bmap(bset));
1164 return bset_from_bmap(dup);
1167 struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset)
1169 if (!bset)
1170 return NULL;
1172 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1173 bset->ref++;
1174 return bset;
1176 return isl_basic_set_dup(bset);
1179 struct isl_set *isl_set_copy(struct isl_set *set)
1181 if (!set)
1182 return NULL;
1184 set->ref++;
1185 return set;
1188 struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap)
1190 if (!bmap)
1191 return NULL;
1193 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1194 bmap->ref++;
1195 return bmap;
1197 bmap = isl_basic_map_dup(bmap);
1198 if (bmap)
1199 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1200 return bmap;
1203 struct isl_map *isl_map_copy(struct isl_map *map)
1205 if (!map)
1206 return NULL;
1208 map->ref++;
1209 return map;
1212 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1214 if (!bmap)
1215 return NULL;
1217 if (--bmap->ref > 0)
1218 return NULL;
1220 isl_ctx_deref(bmap->ctx);
1221 free(bmap->div);
1222 isl_blk_free(bmap->ctx, bmap->block2);
1223 free(bmap->ineq);
1224 isl_blk_free(bmap->ctx, bmap->block);
1225 isl_vec_free(bmap->sample);
1226 isl_space_free(bmap->dim);
1227 free(bmap);
1229 return NULL;
1232 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1234 return isl_basic_map_free(bset_to_bmap(bset));
1237 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1239 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1242 /* Check that "map" has only named parameters, reporting an error
1243 * if it does not.
1245 isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1247 return isl_space_check_named_params(isl_map_peek_space(map));
1250 /* Check that "bmap1" and "bmap2" have the same parameters,
1251 * reporting an error if they do not.
1253 static isl_stat isl_basic_map_check_equal_params(
1254 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1256 isl_bool match;
1258 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1259 if (match < 0)
1260 return isl_stat_error;
1261 if (!match)
1262 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1263 "parameters don't match", return isl_stat_error);
1264 return isl_stat_ok;
1267 __isl_give isl_map *isl_map_align_params_map_map_and(
1268 __isl_take isl_map *map1, __isl_take isl_map *map2,
1269 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1270 __isl_take isl_map *map2))
1272 if (!map1 || !map2)
1273 goto error;
1274 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1275 return fn(map1, map2);
1276 if (isl_map_check_named_params(map1) < 0)
1277 goto error;
1278 if (isl_map_check_named_params(map2) < 0)
1279 goto error;
1280 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1281 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1282 return fn(map1, map2);
1283 error:
1284 isl_map_free(map1);
1285 isl_map_free(map2);
1286 return NULL;
1289 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1290 __isl_keep isl_map *map2,
1291 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1293 isl_bool r;
1295 if (!map1 || !map2)
1296 return isl_bool_error;
1297 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1298 return fn(map1, map2);
1299 if (isl_map_check_named_params(map1) < 0)
1300 return isl_bool_error;
1301 if (isl_map_check_named_params(map2) < 0)
1302 return isl_bool_error;
1303 map1 = isl_map_copy(map1);
1304 map2 = isl_map_copy(map2);
1305 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1306 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1307 r = fn(map1, map2);
1308 isl_map_free(map1);
1309 isl_map_free(map2);
1310 return r;
1313 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1315 struct isl_ctx *ctx;
1316 if (!bmap)
1317 return -1;
1318 ctx = bmap->ctx;
1319 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1320 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1321 return -1);
1322 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1323 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1324 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1325 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1326 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1327 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1328 isl_int *t;
1329 int j = isl_basic_map_alloc_inequality(bmap);
1330 if (j < 0)
1331 return -1;
1332 t = bmap->ineq[j];
1333 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1334 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1335 bmap->eq[-1] = t;
1336 bmap->n_eq++;
1337 bmap->n_ineq--;
1338 bmap->eq--;
1339 return 0;
1341 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1342 bmap->extra - bmap->n_div);
1343 return bmap->n_eq++;
1346 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1348 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1351 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1353 if (!bmap)
1354 return -1;
1355 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1356 bmap->n_eq -= n;
1357 return 0;
1360 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1362 return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1365 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1367 isl_int *t;
1368 if (!bmap)
1369 return -1;
1370 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1372 if (pos != bmap->n_eq - 1) {
1373 t = bmap->eq[pos];
1374 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1375 bmap->eq[bmap->n_eq - 1] = t;
1377 bmap->n_eq--;
1378 return 0;
1381 /* Turn inequality "pos" of "bmap" into an equality.
1383 * In particular, we move the inequality in front of the equalities
1384 * and move the last inequality in the position of the moved inequality.
1385 * Note that isl_tab_make_equalities_explicit depends on this particular
1386 * change in the ordering of the constraints.
1388 void isl_basic_map_inequality_to_equality(
1389 struct isl_basic_map *bmap, unsigned pos)
1391 isl_int *t;
1393 t = bmap->ineq[pos];
1394 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1395 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1396 bmap->eq[-1] = t;
1397 bmap->n_eq++;
1398 bmap->n_ineq--;
1399 bmap->eq--;
1400 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1401 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1402 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1403 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1406 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1408 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1411 int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap)
1413 struct isl_ctx *ctx;
1414 if (!bmap)
1415 return -1;
1416 ctx = bmap->ctx;
1417 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1418 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1419 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1420 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1421 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1422 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1423 1 + isl_basic_map_total_dim(bmap),
1424 bmap->extra - bmap->n_div);
1425 return bmap->n_ineq++;
1428 int isl_basic_set_alloc_inequality(struct isl_basic_set *bset)
1430 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1433 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1435 if (!bmap)
1436 return -1;
1437 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1438 bmap->n_ineq -= n;
1439 return 0;
1442 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1444 return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1447 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1449 isl_int *t;
1450 if (!bmap)
1451 return -1;
1452 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1454 if (pos != bmap->n_ineq - 1) {
1455 t = bmap->ineq[pos];
1456 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1457 bmap->ineq[bmap->n_ineq - 1] = t;
1458 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1460 bmap->n_ineq--;
1461 return 0;
1464 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1466 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1469 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1470 isl_int *eq)
1472 int k;
1474 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1475 if (!bmap)
1476 return NULL;
1477 k = isl_basic_map_alloc_equality(bmap);
1478 if (k < 0)
1479 goto error;
1480 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1481 return bmap;
1482 error:
1483 isl_basic_map_free(bmap);
1484 return NULL;
1487 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1488 isl_int *eq)
1490 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1493 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1494 isl_int *ineq)
1496 int k;
1498 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1499 if (!bmap)
1500 return NULL;
1501 k = isl_basic_map_alloc_inequality(bmap);
1502 if (k < 0)
1503 goto error;
1504 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1505 return bmap;
1506 error:
1507 isl_basic_map_free(bmap);
1508 return NULL;
1511 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1512 isl_int *ineq)
1514 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1517 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1519 if (!bmap)
1520 return -1;
1521 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1522 isl_seq_clr(bmap->div[bmap->n_div] +
1523 1 + 1 + isl_basic_map_total_dim(bmap),
1524 bmap->extra - bmap->n_div);
1525 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1526 return bmap->n_div++;
1529 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1531 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1534 /* Check that there are "n" dimensions of type "type" starting at "first"
1535 * in "bmap".
1537 static isl_stat isl_basic_map_check_range(__isl_keep isl_basic_map *bmap,
1538 enum isl_dim_type type, unsigned first, unsigned n)
1540 unsigned dim;
1542 if (!bmap)
1543 return isl_stat_error;
1544 dim = isl_basic_map_dim(bmap, type);
1545 if (first + n > dim || first + n < first)
1546 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1547 "position or range out of bounds",
1548 return isl_stat_error);
1549 return isl_stat_ok;
1552 /* Insert an extra integer division, prescribed by "div", to "bmap"
1553 * at (integer division) position "pos".
1555 * The integer division is first added at the end and then moved
1556 * into the right position.
1558 __isl_give isl_basic_map *isl_basic_map_insert_div(
1559 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1561 int i, k;
1563 bmap = isl_basic_map_cow(bmap);
1564 if (!bmap || !div)
1565 return isl_basic_map_free(bmap);
1567 if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1568 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1569 "unexpected size", return isl_basic_map_free(bmap));
1570 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1571 return isl_basic_map_free(bmap);
1573 bmap = isl_basic_map_extend_space(bmap,
1574 isl_basic_map_get_space(bmap), 1, 0, 2);
1575 k = isl_basic_map_alloc_div(bmap);
1576 if (k < 0)
1577 return isl_basic_map_free(bmap);
1578 isl_seq_cpy(bmap->div[k], div->el, div->size);
1579 isl_int_set_si(bmap->div[k][div->size], 0);
1581 for (i = k; i > pos; --i)
1582 isl_basic_map_swap_div(bmap, i, i - 1);
1584 return bmap;
1587 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1589 if (!bmap)
1590 return isl_stat_error;
1591 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1592 bmap->n_div -= n;
1593 return isl_stat_ok;
1596 /* Copy constraint from src to dst, putting the vars of src at offset
1597 * dim_off in dst and the divs of src at offset div_off in dst.
1598 * If both sets are actually map, then dim_off applies to the input
1599 * variables.
1601 static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
1602 struct isl_basic_map *src_map, isl_int *src,
1603 unsigned in_off, unsigned out_off, unsigned div_off)
1605 unsigned src_nparam = isl_basic_map_n_param(src_map);
1606 unsigned dst_nparam = isl_basic_map_n_param(dst_map);
1607 unsigned src_in = isl_basic_map_n_in(src_map);
1608 unsigned dst_in = isl_basic_map_n_in(dst_map);
1609 unsigned src_out = isl_basic_map_n_out(src_map);
1610 unsigned dst_out = isl_basic_map_n_out(dst_map);
1611 isl_int_set(dst[0], src[0]);
1612 isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
1613 if (dst_nparam > src_nparam)
1614 isl_seq_clr(dst+1+src_nparam,
1615 dst_nparam - src_nparam);
1616 isl_seq_clr(dst+1+dst_nparam, in_off);
1617 isl_seq_cpy(dst+1+dst_nparam+in_off,
1618 src+1+src_nparam,
1619 isl_min(dst_in-in_off, src_in));
1620 if (dst_in-in_off > src_in)
1621 isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
1622 dst_in - in_off - src_in);
1623 isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
1624 isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
1625 src+1+src_nparam+src_in,
1626 isl_min(dst_out-out_off, src_out));
1627 if (dst_out-out_off > src_out)
1628 isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
1629 dst_out - out_off - src_out);
1630 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
1631 isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
1632 src+1+src_nparam+src_in+src_out,
1633 isl_min(dst_map->extra-div_off, src_map->n_div));
1634 if (dst_map->n_div-div_off > src_map->n_div)
1635 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
1636 div_off+src_map->n_div,
1637 dst_map->n_div - div_off - src_map->n_div);
1640 static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
1641 struct isl_basic_map *src_map, isl_int *src,
1642 unsigned in_off, unsigned out_off, unsigned div_off)
1644 isl_int_set(dst[0], src[0]);
1645 copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
1648 static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1,
1649 struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos)
1651 int i;
1652 unsigned div_off;
1654 if (!bmap1 || !bmap2)
1655 goto error;
1657 div_off = bmap1->n_div;
1659 for (i = 0; i < bmap2->n_eq; ++i) {
1660 int i1 = isl_basic_map_alloc_equality(bmap1);
1661 if (i1 < 0)
1662 goto error;
1663 copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
1664 i_pos, o_pos, div_off);
1667 for (i = 0; i < bmap2->n_ineq; ++i) {
1668 int i1 = isl_basic_map_alloc_inequality(bmap1);
1669 if (i1 < 0)
1670 goto error;
1671 copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
1672 i_pos, o_pos, div_off);
1675 for (i = 0; i < bmap2->n_div; ++i) {
1676 int i1 = isl_basic_map_alloc_div(bmap1);
1677 if (i1 < 0)
1678 goto error;
1679 copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
1680 i_pos, o_pos, div_off);
1683 isl_basic_map_free(bmap2);
1685 return bmap1;
1687 error:
1688 isl_basic_map_free(bmap1);
1689 isl_basic_map_free(bmap2);
1690 return NULL;
1693 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1694 struct isl_basic_set *bset2, unsigned pos)
1696 return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1697 bset_to_bmap(bset2), 0, pos));
1700 struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base,
1701 __isl_take isl_space *dim, unsigned extra,
1702 unsigned n_eq, unsigned n_ineq)
1704 struct isl_basic_map *ext;
1705 unsigned flags;
1706 int dims_ok;
1708 if (!dim)
1709 goto error;
1711 if (!base)
1712 goto error;
1714 dims_ok = isl_space_is_equal(base->dim, dim) &&
1715 base->extra >= base->n_div + extra;
1717 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1718 room_for_ineq(base, n_ineq)) {
1719 isl_space_free(dim);
1720 return base;
1723 isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
1724 isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
1725 isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
1726 extra += base->extra;
1727 n_eq += base->n_eq;
1728 n_ineq += base->n_ineq;
1730 ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1731 dim = NULL;
1732 if (!ext)
1733 goto error;
1735 if (dims_ok)
1736 ext->sample = isl_vec_copy(base->sample);
1737 flags = base->flags;
1738 ext = add_constraints(ext, base, 0, 0);
1739 if (ext) {
1740 ext->flags = flags;
1741 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1744 return ext;
1746 error:
1747 isl_space_free(dim);
1748 isl_basic_map_free(base);
1749 return NULL;
1752 struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base,
1753 __isl_take isl_space *dim, unsigned extra,
1754 unsigned n_eq, unsigned n_ineq)
1756 return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1757 dim, extra, n_eq, n_ineq));
1760 struct isl_basic_map *isl_basic_map_extend_constraints(
1761 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1763 if (!base)
1764 return NULL;
1765 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1766 0, n_eq, n_ineq);
1769 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1770 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1771 unsigned n_eq, unsigned n_ineq)
1773 struct isl_basic_map *bmap;
1774 isl_space *dim;
1776 if (!base)
1777 return NULL;
1778 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1779 if (!dim)
1780 goto error;
1782 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1783 return bmap;
1784 error:
1785 isl_basic_map_free(base);
1786 return NULL;
1789 struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
1790 unsigned nparam, unsigned dim, unsigned extra,
1791 unsigned n_eq, unsigned n_ineq)
1793 return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
1794 nparam, 0, dim, extra, n_eq, n_ineq));
1797 struct isl_basic_set *isl_basic_set_extend_constraints(
1798 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1800 isl_basic_map *bmap = bset_to_bmap(base);
1801 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1802 return bset_from_bmap(bmap);
1805 struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset)
1807 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1810 struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap)
1812 if (!bmap)
1813 return NULL;
1815 if (bmap->ref > 1) {
1816 bmap->ref--;
1817 bmap = isl_basic_map_dup(bmap);
1819 if (bmap) {
1820 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1821 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1823 return bmap;
1826 /* Clear all cached information in "map", either because it is about
1827 * to be modified or because it is being freed.
1828 * Always return the same pointer that is passed in.
1829 * This is needed for the use in isl_map_free.
1831 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1833 isl_basic_map_free(map->cached_simple_hull[0]);
1834 isl_basic_map_free(map->cached_simple_hull[1]);
1835 map->cached_simple_hull[0] = NULL;
1836 map->cached_simple_hull[1] = NULL;
1837 return map;
1840 struct isl_set *isl_set_cow(struct isl_set *set)
1842 return isl_map_cow(set);
1845 /* Return an isl_map that is equal to "map" and that has only
1846 * a single reference.
1848 * If the original input already has only one reference, then
1849 * simply return it, but clear all cached information, since
1850 * it may be rendered invalid by the operations that will be
1851 * performed on the result.
1853 * Otherwise, create a duplicate (without any cached information).
1855 struct isl_map *isl_map_cow(struct isl_map *map)
1857 if (!map)
1858 return NULL;
1860 if (map->ref == 1)
1861 return clear_caches(map);
1862 map->ref--;
1863 return isl_map_dup(map);
1866 static void swap_vars(struct isl_blk blk, isl_int *a,
1867 unsigned a_len, unsigned b_len)
1869 isl_seq_cpy(blk.data, a+a_len, b_len);
1870 isl_seq_cpy(blk.data+b_len, a, a_len);
1871 isl_seq_cpy(a, blk.data, b_len+a_len);
1874 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1875 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1877 int i;
1878 struct isl_blk blk;
1880 if (!bmap)
1881 goto error;
1883 isl_assert(bmap->ctx,
1884 pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
1886 if (n1 == 0 || n2 == 0)
1887 return bmap;
1889 bmap = isl_basic_map_cow(bmap);
1890 if (!bmap)
1891 return NULL;
1893 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
1894 if (isl_blk_is_error(blk))
1895 goto error;
1897 for (i = 0; i < bmap->n_eq; ++i)
1898 swap_vars(blk,
1899 bmap->eq[i] + pos, n1, n2);
1901 for (i = 0; i < bmap->n_ineq; ++i)
1902 swap_vars(blk,
1903 bmap->ineq[i] + pos, n1, n2);
1905 for (i = 0; i < bmap->n_div; ++i)
1906 swap_vars(blk,
1907 bmap->div[i]+1 + pos, n1, n2);
1909 isl_blk_free(bmap->ctx, blk);
1911 ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
1912 bmap = isl_basic_map_gauss(bmap, NULL);
1913 return isl_basic_map_finalize(bmap);
1914 error:
1915 isl_basic_map_free(bmap);
1916 return NULL;
1919 struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap)
1921 int i = 0;
1922 unsigned total;
1923 if (!bmap)
1924 goto error;
1925 total = isl_basic_map_total_dim(bmap);
1926 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
1927 return isl_basic_map_free(bmap);
1928 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
1929 if (bmap->n_eq > 0)
1930 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
1931 else {
1932 i = isl_basic_map_alloc_equality(bmap);
1933 if (i < 0)
1934 goto error;
1936 isl_int_set_si(bmap->eq[i][0], 1);
1937 isl_seq_clr(bmap->eq[i]+1, total);
1938 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
1939 isl_vec_free(bmap->sample);
1940 bmap->sample = NULL;
1941 return isl_basic_map_finalize(bmap);
1942 error:
1943 isl_basic_map_free(bmap);
1944 return NULL;
1947 struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset)
1949 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
1952 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
1953 * of "bmap").
1955 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
1957 isl_int *t = bmap->div[a];
1958 bmap->div[a] = bmap->div[b];
1959 bmap->div[b] = t;
1962 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
1963 * div definitions accordingly.
1965 void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
1967 int i;
1968 unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
1970 swap_div(bmap, a, b);
1972 for (i = 0; i < bmap->n_eq; ++i)
1973 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
1975 for (i = 0; i < bmap->n_ineq; ++i)
1976 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
1978 for (i = 0; i < bmap->n_div; ++i)
1979 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
1980 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1983 /* Swap divs "a" and "b" in "bset" and adjust the constraints and
1984 * div definitions accordingly.
1986 void isl_basic_set_swap_div(__isl_keep isl_basic_set *bset, int a, int b)
1988 isl_basic_map_swap_div(bset, a, b);
1991 /* Eliminate the specified n dimensions starting at first from the
1992 * constraints, without removing the dimensions from the space.
1993 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1995 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
1996 enum isl_dim_type type, unsigned first, unsigned n)
1998 int i;
2000 if (!map)
2001 return NULL;
2002 if (n == 0)
2003 return map;
2005 if (first + n > isl_map_dim(map, type) || first + n < first)
2006 isl_die(map->ctx, isl_error_invalid,
2007 "index out of bounds", goto error);
2009 map = isl_map_cow(map);
2010 if (!map)
2011 return NULL;
2013 for (i = 0; i < map->n; ++i) {
2014 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2015 if (!map->p[i])
2016 goto error;
2018 return map;
2019 error:
2020 isl_map_free(map);
2021 return NULL;
2024 /* Eliminate the specified n dimensions starting at first from the
2025 * constraints, without removing the dimensions from the space.
2026 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2028 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2029 enum isl_dim_type type, unsigned first, unsigned n)
2031 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2034 /* Eliminate the specified n dimensions starting at first from the
2035 * constraints, without removing the dimensions from the space.
2036 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2038 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2039 unsigned first, unsigned n)
2041 return isl_set_eliminate(set, isl_dim_set, first, n);
2044 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2045 __isl_take isl_basic_map *bmap)
2047 if (!bmap)
2048 return NULL;
2049 bmap = isl_basic_map_eliminate_vars(bmap,
2050 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
2051 if (!bmap)
2052 return NULL;
2053 bmap->n_div = 0;
2054 return isl_basic_map_finalize(bmap);
2057 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2058 __isl_take isl_basic_set *bset)
2060 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2063 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2065 int i;
2067 if (!map)
2068 return NULL;
2069 if (map->n == 0)
2070 return map;
2072 map = isl_map_cow(map);
2073 if (!map)
2074 return NULL;
2076 for (i = 0; i < map->n; ++i) {
2077 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2078 if (!map->p[i])
2079 goto error;
2081 return map;
2082 error:
2083 isl_map_free(map);
2084 return NULL;
2087 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2089 return isl_map_remove_divs(set);
2092 struct isl_basic_map *isl_basic_map_remove_dims(struct isl_basic_map *bmap,
2093 enum isl_dim_type type, unsigned first, unsigned n)
2095 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2096 return isl_basic_map_free(bmap);
2097 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2098 return bmap;
2099 bmap = isl_basic_map_eliminate_vars(bmap,
2100 isl_basic_map_offset(bmap, type) - 1 + first, n);
2101 if (!bmap)
2102 return bmap;
2103 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2104 return bmap;
2105 bmap = isl_basic_map_drop(bmap, type, first, n);
2106 return bmap;
2109 /* Return true if the definition of the given div (recursively) involves
2110 * any of the given variables.
2112 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2113 unsigned first, unsigned n)
2115 int i;
2116 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2118 if (isl_int_is_zero(bmap->div[div][0]))
2119 return isl_bool_false;
2120 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2121 return isl_bool_true;
2123 for (i = bmap->n_div - 1; i >= 0; --i) {
2124 isl_bool involves;
2126 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2127 continue;
2128 involves = div_involves_vars(bmap, i, first, n);
2129 if (involves < 0 || involves)
2130 return involves;
2133 return isl_bool_false;
2136 /* Try and add a lower and/or upper bound on "div" to "bmap"
2137 * based on inequality "i".
2138 * "total" is the total number of variables (excluding the divs).
2139 * "v" is a temporary object that can be used during the calculations.
2140 * If "lb" is set, then a lower bound should be constructed.
2141 * If "ub" is set, then an upper bound should be constructed.
2143 * The calling function has already checked that the inequality does not
2144 * reference "div", but we still need to check that the inequality is
2145 * of the right form. We'll consider the case where we want to construct
2146 * a lower bound. The construction of upper bounds is similar.
2148 * Let "div" be of the form
2150 * q = floor((a + f(x))/d)
2152 * We essentially check if constraint "i" is of the form
2154 * b + f(x) >= 0
2156 * so that we can use it to derive a lower bound on "div".
2157 * However, we allow a slightly more general form
2159 * b + g(x) >= 0
2161 * with the condition that the coefficients of g(x) - f(x) are all
2162 * divisible by d.
2163 * Rewriting this constraint as
2165 * 0 >= -b - g(x)
2167 * adding a + f(x) to both sides and dividing by d, we obtain
2169 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2171 * Taking the floor on both sides, we obtain
2173 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2175 * or
2177 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2179 * In the case of an upper bound, we construct the constraint
2181 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2184 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2185 __isl_take isl_basic_map *bmap, int div, int i,
2186 unsigned total, isl_int v, int lb, int ub)
2188 int j;
2190 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2191 if (lb) {
2192 isl_int_sub(v, bmap->ineq[i][1 + j],
2193 bmap->div[div][1 + 1 + j]);
2194 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2196 if (ub) {
2197 isl_int_add(v, bmap->ineq[i][1 + j],
2198 bmap->div[div][1 + 1 + j]);
2199 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2202 if (!lb && !ub)
2203 return bmap;
2205 bmap = isl_basic_map_cow(bmap);
2206 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2207 if (lb) {
2208 int k = isl_basic_map_alloc_inequality(bmap);
2209 if (k < 0)
2210 goto error;
2211 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2212 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2213 bmap->div[div][1 + j]);
2214 isl_int_cdiv_q(bmap->ineq[k][j],
2215 bmap->ineq[k][j], bmap->div[div][0]);
2217 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2219 if (ub) {
2220 int k = isl_basic_map_alloc_inequality(bmap);
2221 if (k < 0)
2222 goto error;
2223 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2224 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2225 bmap->div[div][1 + j]);
2226 isl_int_fdiv_q(bmap->ineq[k][j],
2227 bmap->ineq[k][j], bmap->div[div][0]);
2229 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2232 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2233 return bmap;
2234 error:
2235 isl_basic_map_free(bmap);
2236 return NULL;
2239 /* This function is called right before "div" is eliminated from "bmap"
2240 * using Fourier-Motzkin.
2241 * Look through the constraints of "bmap" for constraints on the argument
2242 * of the integer division and use them to construct constraints on the
2243 * integer division itself. These constraints can then be combined
2244 * during the Fourier-Motzkin elimination.
2245 * Note that it is only useful to introduce lower bounds on "div"
2246 * if "bmap" already contains upper bounds on "div" as the newly
2247 * introduce lower bounds can then be combined with the pre-existing
2248 * upper bounds. Similarly for upper bounds.
2249 * We therefore first check if "bmap" contains any lower and/or upper bounds
2250 * on "div".
2252 * It is interesting to note that the introduction of these constraints
2253 * can indeed lead to more accurate results, even when compared to
2254 * deriving constraints on the argument of "div" from constraints on "div".
2255 * Consider, for example, the set
2257 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2259 * The second constraint can be rewritten as
2261 * 2 * [(-i-2j+3)/4] + k >= 0
2263 * from which we can derive
2265 * -i - 2j + 3 >= -2k
2267 * or
2269 * i + 2j <= 3 + 2k
2271 * Combined with the first constraint, we obtain
2273 * -3 <= 3 + 2k or k >= -3
2275 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2276 * the first constraint, we obtain
2278 * [(i + 2j)/4] >= [-3/4] = -1
2280 * Combining this constraint with the second constraint, we obtain
2282 * k >= -2
2284 static __isl_give isl_basic_map *insert_bounds_on_div(
2285 __isl_take isl_basic_map *bmap, int div)
2287 int i;
2288 int check_lb, check_ub;
2289 isl_int v;
2290 unsigned total;
2292 if (!bmap)
2293 return NULL;
2295 if (isl_int_is_zero(bmap->div[div][0]))
2296 return bmap;
2298 total = isl_space_dim(bmap->dim, isl_dim_all);
2300 check_lb = 0;
2301 check_ub = 0;
2302 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2303 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2304 if (s > 0)
2305 check_ub = 1;
2306 if (s < 0)
2307 check_lb = 1;
2310 if (!check_lb && !check_ub)
2311 return bmap;
2313 isl_int_init(v);
2315 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2316 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2317 continue;
2319 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2320 check_lb, check_ub);
2323 isl_int_clear(v);
2325 return bmap;
2328 /* Remove all divs (recursively) involving any of the given dimensions
2329 * in their definitions.
2331 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2332 __isl_take isl_basic_map *bmap,
2333 enum isl_dim_type type, unsigned first, unsigned n)
2335 int i;
2337 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2338 return isl_basic_map_free(bmap);
2339 first += isl_basic_map_offset(bmap, type);
2341 for (i = bmap->n_div - 1; i >= 0; --i) {
2342 isl_bool involves;
2344 involves = div_involves_vars(bmap, i, first, n);
2345 if (involves < 0)
2346 return isl_basic_map_free(bmap);
2347 if (!involves)
2348 continue;
2349 bmap = insert_bounds_on_div(bmap, i);
2350 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2351 if (!bmap)
2352 return NULL;
2353 i = bmap->n_div;
2356 return bmap;
2359 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2360 __isl_take isl_basic_set *bset,
2361 enum isl_dim_type type, unsigned first, unsigned n)
2363 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2366 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2367 enum isl_dim_type type, unsigned first, unsigned n)
2369 int i;
2371 if (!map)
2372 return NULL;
2373 if (map->n == 0)
2374 return map;
2376 map = isl_map_cow(map);
2377 if (!map)
2378 return NULL;
2380 for (i = 0; i < map->n; ++i) {
2381 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2382 type, first, n);
2383 if (!map->p[i])
2384 goto error;
2386 return map;
2387 error:
2388 isl_map_free(map);
2389 return NULL;
2392 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2393 enum isl_dim_type type, unsigned first, unsigned n)
2395 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2396 type, first, n));
2399 /* Does the description of "bmap" depend on the specified dimensions?
2400 * We also check whether the dimensions appear in any of the div definitions.
2401 * In principle there is no need for this check. If the dimensions appear
2402 * in a div definition, they also appear in the defining constraints of that
2403 * div.
2405 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2406 enum isl_dim_type type, unsigned first, unsigned n)
2408 int i;
2410 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2411 return isl_bool_error;
2413 first += isl_basic_map_offset(bmap, type);
2414 for (i = 0; i < bmap->n_eq; ++i)
2415 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2416 return isl_bool_true;
2417 for (i = 0; i < bmap->n_ineq; ++i)
2418 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2419 return isl_bool_true;
2420 for (i = 0; i < bmap->n_div; ++i) {
2421 if (isl_int_is_zero(bmap->div[i][0]))
2422 continue;
2423 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2424 return isl_bool_true;
2427 return isl_bool_false;
2430 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2431 enum isl_dim_type type, unsigned first, unsigned n)
2433 int i;
2435 if (!map)
2436 return isl_bool_error;
2438 if (first + n > isl_map_dim(map, type))
2439 isl_die(map->ctx, isl_error_invalid,
2440 "index out of bounds", return isl_bool_error);
2442 for (i = 0; i < map->n; ++i) {
2443 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2444 type, first, n);
2445 if (involves < 0 || involves)
2446 return involves;
2449 return isl_bool_false;
2452 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2453 enum isl_dim_type type, unsigned first, unsigned n)
2455 return isl_basic_map_involves_dims(bset, type, first, n);
2458 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2459 enum isl_dim_type type, unsigned first, unsigned n)
2461 return isl_map_involves_dims(set, type, first, n);
2464 /* Drop all constraints in bmap that involve any of the dimensions
2465 * first to first+n-1.
2467 static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2468 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2470 int i;
2472 if (n == 0)
2473 return bmap;
2475 bmap = isl_basic_map_cow(bmap);
2477 if (!bmap)
2478 return NULL;
2480 for (i = bmap->n_eq - 1; i >= 0; --i) {
2481 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2482 continue;
2483 isl_basic_map_drop_equality(bmap, i);
2486 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2487 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2488 continue;
2489 isl_basic_map_drop_inequality(bmap, i);
2492 bmap = isl_basic_map_add_known_div_constraints(bmap);
2493 return bmap;
2496 /* Drop all constraints in bset that involve any of the dimensions
2497 * first to first+n-1.
2499 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2500 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2502 return isl_basic_map_drop_constraints_involving(bset, first, n);
2505 /* Drop all constraints in bmap that do not involve any of the dimensions
2506 * first to first + n - 1 of the given type.
2508 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2509 __isl_take isl_basic_map *bmap,
2510 enum isl_dim_type type, unsigned first, unsigned n)
2512 int i;
2514 if (n == 0) {
2515 isl_space *space = isl_basic_map_get_space(bmap);
2516 isl_basic_map_free(bmap);
2517 return isl_basic_map_universe(space);
2519 bmap = isl_basic_map_cow(bmap);
2520 if (!bmap)
2521 return NULL;
2523 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2524 return isl_basic_map_free(bmap);
2526 first += isl_basic_map_offset(bmap, type) - 1;
2528 for (i = bmap->n_eq - 1; i >= 0; --i) {
2529 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2530 continue;
2531 isl_basic_map_drop_equality(bmap, i);
2534 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2535 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2536 continue;
2537 isl_basic_map_drop_inequality(bmap, i);
2540 bmap = isl_basic_map_add_known_div_constraints(bmap);
2541 return bmap;
2544 /* Drop all constraints in bset that do not involve any of the dimensions
2545 * first to first + n - 1 of the given type.
2547 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2548 __isl_take isl_basic_set *bset,
2549 enum isl_dim_type type, unsigned first, unsigned n)
2551 return isl_basic_map_drop_constraints_not_involving_dims(bset,
2552 type, first, n);
2555 /* Drop all constraints in bmap that involve any of the dimensions
2556 * first to first + n - 1 of the given type.
2558 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2559 __isl_take isl_basic_map *bmap,
2560 enum isl_dim_type type, unsigned first, unsigned n)
2562 if (!bmap)
2563 return NULL;
2564 if (n == 0)
2565 return bmap;
2567 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2568 return isl_basic_map_free(bmap);
2570 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2571 first += isl_basic_map_offset(bmap, type) - 1;
2572 return isl_basic_map_drop_constraints_involving(bmap, first, n);
2575 /* Drop all constraints in bset that involve any of the dimensions
2576 * first to first + n - 1 of the given type.
2578 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2579 __isl_take isl_basic_set *bset,
2580 enum isl_dim_type type, unsigned first, unsigned n)
2582 return isl_basic_map_drop_constraints_involving_dims(bset,
2583 type, first, n);
2586 /* Drop constraints from "map" by applying "drop" to each basic map.
2588 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2589 enum isl_dim_type type, unsigned first, unsigned n,
2590 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2591 enum isl_dim_type type, unsigned first, unsigned n))
2593 int i;
2594 unsigned dim;
2596 if (!map)
2597 return NULL;
2599 dim = isl_map_dim(map, type);
2600 if (first + n > dim || first + n < first)
2601 isl_die(isl_map_get_ctx(map), isl_error_invalid,
2602 "index out of bounds", return isl_map_free(map));
2604 map = isl_map_cow(map);
2605 if (!map)
2606 return NULL;
2608 for (i = 0; i < map->n; ++i) {
2609 map->p[i] = drop(map->p[i], type, first, n);
2610 if (!map->p[i])
2611 return isl_map_free(map);
2614 if (map->n > 1)
2615 ISL_F_CLR(map, ISL_MAP_DISJOINT);
2617 return map;
2620 /* Drop all constraints in map that involve any of the dimensions
2621 * first to first + n - 1 of the given type.
2623 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
2624 __isl_take isl_map *map,
2625 enum isl_dim_type type, unsigned first, unsigned n)
2627 if (n == 0)
2628 return map;
2629 return drop_constraints(map, type, first, n,
2630 &isl_basic_map_drop_constraints_involving_dims);
2633 /* Drop all constraints in "map" that do not involve any of the dimensions
2634 * first to first + n - 1 of the given type.
2636 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
2637 __isl_take isl_map *map,
2638 enum isl_dim_type type, unsigned first, unsigned n)
2640 if (n == 0) {
2641 isl_space *space = isl_map_get_space(map);
2642 isl_map_free(map);
2643 return isl_map_universe(space);
2645 return drop_constraints(map, type, first, n,
2646 &isl_basic_map_drop_constraints_not_involving_dims);
2649 /* Drop all constraints in set that involve any of the dimensions
2650 * first to first + n - 1 of the given type.
2652 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
2653 __isl_take isl_set *set,
2654 enum isl_dim_type type, unsigned first, unsigned n)
2656 return isl_map_drop_constraints_involving_dims(set, type, first, n);
2659 /* Drop all constraints in "set" that do not involve any of the dimensions
2660 * first to first + n - 1 of the given type.
2662 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
2663 __isl_take isl_set *set,
2664 enum isl_dim_type type, unsigned first, unsigned n)
2666 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
2669 /* Does local variable "div" of "bmap" have a complete explicit representation?
2670 * Having a complete explicit representation requires not only
2671 * an explicit representation, but also that all local variables
2672 * that appear in this explicit representation in turn have
2673 * a complete explicit representation.
2675 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
2677 int i;
2678 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2679 isl_bool marked;
2681 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
2682 if (marked < 0 || marked)
2683 return isl_bool_not(marked);
2685 for (i = bmap->n_div - 1; i >= 0; --i) {
2686 isl_bool known;
2688 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2689 continue;
2690 known = isl_basic_map_div_is_known(bmap, i);
2691 if (known < 0 || !known)
2692 return known;
2695 return isl_bool_true;
2698 /* Remove all divs that are unknown or defined in terms of unknown divs.
2700 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
2701 __isl_take isl_basic_map *bmap)
2703 int i;
2705 if (!bmap)
2706 return NULL;
2708 for (i = bmap->n_div - 1; i >= 0; --i) {
2709 if (isl_basic_map_div_is_known(bmap, i))
2710 continue;
2711 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2712 if (!bmap)
2713 return NULL;
2714 i = bmap->n_div;
2717 return bmap;
2720 /* Remove all divs that are unknown or defined in terms of unknown divs.
2722 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
2723 __isl_take isl_basic_set *bset)
2725 return isl_basic_map_remove_unknown_divs(bset);
2728 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
2730 int i;
2732 if (!map)
2733 return NULL;
2734 if (map->n == 0)
2735 return map;
2737 map = isl_map_cow(map);
2738 if (!map)
2739 return NULL;
2741 for (i = 0; i < map->n; ++i) {
2742 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
2743 if (!map->p[i])
2744 goto error;
2746 return map;
2747 error:
2748 isl_map_free(map);
2749 return NULL;
2752 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
2754 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
2757 __isl_give isl_basic_set *isl_basic_set_remove_dims(
2758 __isl_take isl_basic_set *bset,
2759 enum isl_dim_type type, unsigned first, unsigned n)
2761 isl_basic_map *bmap = bset_to_bmap(bset);
2762 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
2763 return bset_from_bmap(bmap);
2766 struct isl_map *isl_map_remove_dims(struct isl_map *map,
2767 enum isl_dim_type type, unsigned first, unsigned n)
2769 int i;
2771 if (n == 0)
2772 return map;
2774 map = isl_map_cow(map);
2775 if (!map)
2776 return NULL;
2777 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
2779 for (i = 0; i < map->n; ++i) {
2780 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
2781 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
2782 if (!map->p[i])
2783 goto error;
2785 map = isl_map_drop(map, type, first, n);
2786 return map;
2787 error:
2788 isl_map_free(map);
2789 return NULL;
2792 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
2793 enum isl_dim_type type, unsigned first, unsigned n)
2795 return set_from_map(isl_map_remove_dims(set_to_map(bset),
2796 type, first, n));
2799 /* Project out n inputs starting at first using Fourier-Motzkin */
2800 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
2801 unsigned first, unsigned n)
2803 return isl_map_remove_dims(map, isl_dim_in, first, n);
2806 static void dump_term(struct isl_basic_map *bmap,
2807 isl_int c, int pos, FILE *out)
2809 const char *name;
2810 unsigned in = isl_basic_map_n_in(bmap);
2811 unsigned dim = in + isl_basic_map_n_out(bmap);
2812 unsigned nparam = isl_basic_map_n_param(bmap);
2813 if (!pos)
2814 isl_int_print(out, c, 0);
2815 else {
2816 if (!isl_int_is_one(c))
2817 isl_int_print(out, c, 0);
2818 if (pos < 1 + nparam) {
2819 name = isl_space_get_dim_name(bmap->dim,
2820 isl_dim_param, pos - 1);
2821 if (name)
2822 fprintf(out, "%s", name);
2823 else
2824 fprintf(out, "p%d", pos - 1);
2825 } else if (pos < 1 + nparam + in)
2826 fprintf(out, "i%d", pos - 1 - nparam);
2827 else if (pos < 1 + nparam + dim)
2828 fprintf(out, "o%d", pos - 1 - nparam - in);
2829 else
2830 fprintf(out, "e%d", pos - 1 - nparam - dim);
2834 static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
2835 int sign, FILE *out)
2837 int i;
2838 int first;
2839 unsigned len = 1 + isl_basic_map_total_dim(bmap);
2840 isl_int v;
2842 isl_int_init(v);
2843 for (i = 0, first = 1; i < len; ++i) {
2844 if (isl_int_sgn(c[i]) * sign <= 0)
2845 continue;
2846 if (!first)
2847 fprintf(out, " + ");
2848 first = 0;
2849 isl_int_abs(v, c[i]);
2850 dump_term(bmap, v, i, out);
2852 isl_int_clear(v);
2853 if (first)
2854 fprintf(out, "0");
2857 static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
2858 const char *op, FILE *out, int indent)
2860 int i;
2862 fprintf(out, "%*s", indent, "");
2864 dump_constraint_sign(bmap, c, 1, out);
2865 fprintf(out, " %s ", op);
2866 dump_constraint_sign(bmap, c, -1, out);
2868 fprintf(out, "\n");
2870 for (i = bmap->n_div; i < bmap->extra; ++i) {
2871 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
2872 continue;
2873 fprintf(out, "%*s", indent, "");
2874 fprintf(out, "ERROR: unused div coefficient not zero\n");
2875 abort();
2879 static void dump_constraints(struct isl_basic_map *bmap,
2880 isl_int **c, unsigned n,
2881 const char *op, FILE *out, int indent)
2883 int i;
2885 for (i = 0; i < n; ++i)
2886 dump_constraint(bmap, c[i], op, out, indent);
2889 static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
2891 int j;
2892 int first = 1;
2893 unsigned total = isl_basic_map_total_dim(bmap);
2895 for (j = 0; j < 1 + total; ++j) {
2896 if (isl_int_is_zero(exp[j]))
2897 continue;
2898 if (!first && isl_int_is_pos(exp[j]))
2899 fprintf(out, "+");
2900 dump_term(bmap, exp[j], j, out);
2901 first = 0;
2905 static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
2907 int i;
2909 dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
2910 dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
2912 for (i = 0; i < bmap->n_div; ++i) {
2913 fprintf(out, "%*s", indent, "");
2914 fprintf(out, "e%d = [(", i);
2915 dump_affine(bmap, bmap->div[i]+1, out);
2916 fprintf(out, ")/");
2917 isl_int_print(out, bmap->div[i][0], 0);
2918 fprintf(out, "]\n");
2922 void isl_basic_set_print_internal(struct isl_basic_set *bset,
2923 FILE *out, int indent)
2925 if (!bset) {
2926 fprintf(out, "null basic set\n");
2927 return;
2930 fprintf(out, "%*s", indent, "");
2931 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
2932 bset->ref, bset->dim->nparam, bset->dim->n_out,
2933 bset->extra, bset->flags);
2934 dump(bset_to_bmap(bset), out, indent);
2937 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
2938 FILE *out, int indent)
2940 if (!bmap) {
2941 fprintf(out, "null basic map\n");
2942 return;
2945 fprintf(out, "%*s", indent, "");
2946 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
2947 "flags: %x, n_name: %d\n",
2948 bmap->ref,
2949 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
2950 bmap->extra, bmap->flags, bmap->dim->n_id);
2951 dump(bmap, out, indent);
2954 int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
2956 unsigned total;
2957 if (!bmap)
2958 return -1;
2959 total = isl_basic_map_total_dim(bmap);
2960 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
2961 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
2962 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
2963 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2964 return 0;
2967 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
2968 unsigned flags)
2970 if (!space)
2971 return NULL;
2972 if (isl_space_dim(space, isl_dim_in) != 0)
2973 isl_die(isl_space_get_ctx(space), isl_error_invalid,
2974 "set cannot have input dimensions", goto error);
2975 return isl_map_alloc_space(space, n, flags);
2976 error:
2977 isl_space_free(space);
2978 return NULL;
2981 /* Make sure "map" has room for at least "n" more basic maps.
2983 struct isl_map *isl_map_grow(struct isl_map *map, int n)
2985 int i;
2986 struct isl_map *grown = NULL;
2988 if (!map)
2989 return NULL;
2990 isl_assert(map->ctx, n >= 0, goto error);
2991 if (map->n + n <= map->size)
2992 return map;
2993 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
2994 if (!grown)
2995 goto error;
2996 for (i = 0; i < map->n; ++i) {
2997 grown->p[i] = isl_basic_map_copy(map->p[i]);
2998 if (!grown->p[i])
2999 goto error;
3000 grown->n++;
3002 isl_map_free(map);
3003 return grown;
3004 error:
3005 isl_map_free(grown);
3006 isl_map_free(map);
3007 return NULL;
3010 /* Make sure "set" has room for at least "n" more basic sets.
3012 struct isl_set *isl_set_grow(struct isl_set *set, int n)
3014 return set_from_map(isl_map_grow(set_to_map(set), n));
3017 struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset)
3019 return isl_map_from_basic_map(bset);
3022 struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap)
3024 struct isl_map *map;
3026 if (!bmap)
3027 return NULL;
3029 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3030 return isl_map_add_basic_map(map, bmap);
3033 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3034 __isl_take isl_basic_set *bset)
3036 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3037 bset_to_bmap(bset)));
3040 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3042 return isl_map_free(set);
3045 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3047 int i;
3049 if (!set) {
3050 fprintf(out, "null set\n");
3051 return;
3054 fprintf(out, "%*s", indent, "");
3055 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3056 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3057 set->flags);
3058 for (i = 0; i < set->n; ++i) {
3059 fprintf(out, "%*s", indent, "");
3060 fprintf(out, "basic set %d:\n", i);
3061 isl_basic_set_print_internal(set->p[i], out, indent+4);
3065 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3067 int i;
3069 if (!map) {
3070 fprintf(out, "null map\n");
3071 return;
3074 fprintf(out, "%*s", indent, "");
3075 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3076 "flags: %x, n_name: %d\n",
3077 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3078 map->dim->n_out, map->flags, map->dim->n_id);
3079 for (i = 0; i < map->n; ++i) {
3080 fprintf(out, "%*s", indent, "");
3081 fprintf(out, "basic map %d:\n", i);
3082 isl_basic_map_print_internal(map->p[i], out, indent+4);
3086 struct isl_basic_map *isl_basic_map_intersect_domain(
3087 struct isl_basic_map *bmap, struct isl_basic_set *bset)
3089 struct isl_basic_map *bmap_domain;
3091 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3092 goto error;
3094 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
3095 isl_assert(bset->ctx,
3096 isl_basic_map_compatible_domain(bmap, bset), goto error);
3098 bmap = isl_basic_map_cow(bmap);
3099 if (!bmap)
3100 goto error;
3101 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3102 bset->n_div, bset->n_eq, bset->n_ineq);
3103 bmap_domain = isl_basic_map_from_domain(bset);
3104 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3106 bmap = isl_basic_map_simplify(bmap);
3107 return isl_basic_map_finalize(bmap);
3108 error:
3109 isl_basic_map_free(bmap);
3110 isl_basic_set_free(bset);
3111 return NULL;
3114 /* Check that the space of "bset" is the same as that of the range of "bmap".
3116 static isl_stat isl_basic_map_check_compatible_range(
3117 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3119 isl_bool ok;
3121 ok = isl_basic_map_compatible_range(bmap, bset);
3122 if (ok < 0)
3123 return isl_stat_error;
3124 if (!ok)
3125 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3126 "incompatible spaces", return isl_stat_error);
3128 return isl_stat_ok;
3131 struct isl_basic_map *isl_basic_map_intersect_range(
3132 struct isl_basic_map *bmap, struct isl_basic_set *bset)
3134 struct isl_basic_map *bmap_range;
3136 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3137 goto error;
3139 if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
3140 isl_basic_map_check_compatible_range(bmap, bset) < 0)
3141 goto error;
3143 if (isl_basic_set_plain_is_universe(bset)) {
3144 isl_basic_set_free(bset);
3145 return bmap;
3148 bmap = isl_basic_map_cow(bmap);
3149 if (!bmap)
3150 goto error;
3151 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3152 bset->n_div, bset->n_eq, bset->n_ineq);
3153 bmap_range = bset_to_bmap(bset);
3154 bmap = add_constraints(bmap, bmap_range, 0, 0);
3156 bmap = isl_basic_map_simplify(bmap);
3157 return isl_basic_map_finalize(bmap);
3158 error:
3159 isl_basic_map_free(bmap);
3160 isl_basic_set_free(bset);
3161 return NULL;
3164 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3165 __isl_keep isl_vec *vec)
3167 int i;
3168 unsigned total;
3169 isl_int s;
3171 if (!bmap || !vec)
3172 return isl_bool_error;
3174 total = 1 + isl_basic_map_total_dim(bmap);
3175 if (total != vec->size)
3176 return isl_bool_false;
3178 isl_int_init(s);
3180 for (i = 0; i < bmap->n_eq; ++i) {
3181 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3182 if (!isl_int_is_zero(s)) {
3183 isl_int_clear(s);
3184 return isl_bool_false;
3188 for (i = 0; i < bmap->n_ineq; ++i) {
3189 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3190 if (isl_int_is_neg(s)) {
3191 isl_int_clear(s);
3192 return isl_bool_false;
3196 isl_int_clear(s);
3198 return isl_bool_true;
3201 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3202 __isl_keep isl_vec *vec)
3204 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3207 struct isl_basic_map *isl_basic_map_intersect(
3208 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3210 struct isl_vec *sample = NULL;
3212 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3213 goto error;
3214 if (isl_space_dim(bmap1->dim, isl_dim_all) ==
3215 isl_space_dim(bmap1->dim, isl_dim_param) &&
3216 isl_space_dim(bmap2->dim, isl_dim_all) !=
3217 isl_space_dim(bmap2->dim, isl_dim_param))
3218 return isl_basic_map_intersect(bmap2, bmap1);
3220 if (isl_space_dim(bmap2->dim, isl_dim_all) !=
3221 isl_space_dim(bmap2->dim, isl_dim_param))
3222 isl_assert(bmap1->ctx,
3223 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3225 if (isl_basic_map_plain_is_empty(bmap1)) {
3226 isl_basic_map_free(bmap2);
3227 return bmap1;
3229 if (isl_basic_map_plain_is_empty(bmap2)) {
3230 isl_basic_map_free(bmap1);
3231 return bmap2;
3234 if (bmap1->sample &&
3235 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3236 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3237 sample = isl_vec_copy(bmap1->sample);
3238 else if (bmap2->sample &&
3239 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3240 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3241 sample = isl_vec_copy(bmap2->sample);
3243 bmap1 = isl_basic_map_cow(bmap1);
3244 if (!bmap1)
3245 goto error;
3246 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3247 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3248 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3250 if (!bmap1)
3251 isl_vec_free(sample);
3252 else if (sample) {
3253 isl_vec_free(bmap1->sample);
3254 bmap1->sample = sample;
3257 bmap1 = isl_basic_map_simplify(bmap1);
3258 return isl_basic_map_finalize(bmap1);
3259 error:
3260 if (sample)
3261 isl_vec_free(sample);
3262 isl_basic_map_free(bmap1);
3263 isl_basic_map_free(bmap2);
3264 return NULL;
3267 struct isl_basic_set *isl_basic_set_intersect(
3268 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3270 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3271 bset_to_bmap(bset2)));
3274 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3275 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3277 return isl_basic_set_intersect(bset1, bset2);
3280 /* Special case of isl_map_intersect, where both map1 and map2
3281 * are convex, without any divs and such that either map1 or map2
3282 * contains a single constraint. This constraint is then simply
3283 * added to the other map.
3285 static __isl_give isl_map *map_intersect_add_constraint(
3286 __isl_take isl_map *map1, __isl_take isl_map *map2)
3288 isl_assert(map1->ctx, map1->n == 1, goto error);
3289 isl_assert(map2->ctx, map1->n == 1, goto error);
3290 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3291 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3293 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3294 return isl_map_intersect(map2, map1);
3296 map1 = isl_map_cow(map1);
3297 if (!map1)
3298 goto error;
3299 if (isl_map_plain_is_empty(map1)) {
3300 isl_map_free(map2);
3301 return map1;
3303 map1->p[0] = isl_basic_map_cow(map1->p[0]);
3304 if (map2->p[0]->n_eq == 1)
3305 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3306 else
3307 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3308 map2->p[0]->ineq[0]);
3310 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3311 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3312 if (!map1->p[0])
3313 goto error;
3315 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3316 isl_basic_map_free(map1->p[0]);
3317 map1->n = 0;
3320 isl_map_free(map2);
3322 return map1;
3323 error:
3324 isl_map_free(map1);
3325 isl_map_free(map2);
3326 return NULL;
3329 /* map2 may be either a parameter domain or a map living in the same
3330 * space as map1.
3332 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3333 __isl_take isl_map *map2)
3335 unsigned flags = 0;
3336 isl_map *result;
3337 int i, j;
3339 if (!map1 || !map2)
3340 goto error;
3342 if ((isl_map_plain_is_empty(map1) ||
3343 isl_map_plain_is_universe(map2)) &&
3344 isl_space_is_equal(map1->dim, map2->dim)) {
3345 isl_map_free(map2);
3346 return map1;
3348 if ((isl_map_plain_is_empty(map2) ||
3349 isl_map_plain_is_universe(map1)) &&
3350 isl_space_is_equal(map1->dim, map2->dim)) {
3351 isl_map_free(map1);
3352 return map2;
3355 if (map1->n == 1 && map2->n == 1 &&
3356 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3357 isl_space_is_equal(map1->dim, map2->dim) &&
3358 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3359 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3360 return map_intersect_add_constraint(map1, map2);
3362 if (isl_space_dim(map2->dim, isl_dim_all) !=
3363 isl_space_dim(map2->dim, isl_dim_param))
3364 isl_assert(map1->ctx,
3365 isl_space_is_equal(map1->dim, map2->dim), goto error);
3367 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3368 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3369 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3371 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3372 map1->n * map2->n, flags);
3373 if (!result)
3374 goto error;
3375 for (i = 0; i < map1->n; ++i)
3376 for (j = 0; j < map2->n; ++j) {
3377 struct isl_basic_map *part;
3378 part = isl_basic_map_intersect(
3379 isl_basic_map_copy(map1->p[i]),
3380 isl_basic_map_copy(map2->p[j]));
3381 if (isl_basic_map_is_empty(part) < 0)
3382 part = isl_basic_map_free(part);
3383 result = isl_map_add_basic_map(result, part);
3384 if (!result)
3385 goto error;
3387 isl_map_free(map1);
3388 isl_map_free(map2);
3389 return result;
3390 error:
3391 isl_map_free(map1);
3392 isl_map_free(map2);
3393 return NULL;
3396 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3397 __isl_take isl_map *map2)
3399 if (!map1 || !map2)
3400 goto error;
3401 if (!isl_space_is_equal(map1->dim, map2->dim))
3402 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3403 "spaces don't match", goto error);
3404 return map_intersect_internal(map1, map2);
3405 error:
3406 isl_map_free(map1);
3407 isl_map_free(map2);
3408 return NULL;
3411 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3412 __isl_take isl_map *map2)
3414 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3417 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3419 return set_from_map(isl_map_intersect(set_to_map(set1),
3420 set_to_map(set2)));
3423 /* map_intersect_internal accepts intersections
3424 * with parameter domains, so we can just call that function.
3426 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3427 __isl_take isl_set *params)
3429 return map_intersect_internal(map, params);
3432 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3433 __isl_take isl_map *map2)
3435 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3438 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3439 __isl_take isl_set *params)
3441 return isl_map_intersect_params(set, params);
3444 struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap)
3446 isl_space *space;
3447 unsigned pos, n1, n2;
3449 if (!bmap)
3450 return NULL;
3451 bmap = isl_basic_map_cow(bmap);
3452 if (!bmap)
3453 return NULL;
3454 space = isl_space_reverse(isl_space_copy(bmap->dim));
3455 pos = isl_basic_map_offset(bmap, isl_dim_in);
3456 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3457 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3458 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3459 return isl_basic_map_reset_space(bmap, space);
3462 static __isl_give isl_basic_map *basic_map_space_reset(
3463 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3465 isl_space *space;
3467 if (!bmap)
3468 return NULL;
3469 if (!isl_space_is_named_or_nested(bmap->dim, type))
3470 return bmap;
3472 space = isl_basic_map_get_space(bmap);
3473 space = isl_space_reset(space, type);
3474 bmap = isl_basic_map_reset_space(bmap, space);
3475 return bmap;
3478 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3479 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3480 unsigned pos, unsigned n)
3482 isl_bool rational;
3483 isl_space *res_dim;
3484 struct isl_basic_map *res;
3485 struct isl_dim_map *dim_map;
3486 unsigned total, off;
3487 enum isl_dim_type t;
3489 if (n == 0)
3490 return basic_map_space_reset(bmap, type);
3492 if (!bmap)
3493 return NULL;
3495 res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n);
3497 total = isl_basic_map_total_dim(bmap) + n;
3498 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3499 off = 0;
3500 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3501 if (t != type) {
3502 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3503 } else {
3504 unsigned size = isl_basic_map_dim(bmap, t);
3505 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3506 0, pos, off);
3507 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3508 pos, size - pos, off + pos + n);
3510 off += isl_space_dim(res_dim, t);
3512 isl_dim_map_div(dim_map, bmap, off);
3514 res = isl_basic_map_alloc_space(res_dim,
3515 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3516 rational = isl_basic_map_is_rational(bmap);
3517 if (rational < 0)
3518 res = isl_basic_map_free(res);
3519 if (rational)
3520 res = isl_basic_map_set_rational(res);
3521 if (isl_basic_map_plain_is_empty(bmap)) {
3522 isl_basic_map_free(bmap);
3523 free(dim_map);
3524 return isl_basic_map_set_to_empty(res);
3526 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3527 return isl_basic_map_finalize(res);
3530 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3531 __isl_take isl_basic_set *bset,
3532 enum isl_dim_type type, unsigned pos, unsigned n)
3534 return isl_basic_map_insert_dims(bset, type, pos, n);
3537 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3538 enum isl_dim_type type, unsigned n)
3540 if (!bmap)
3541 return NULL;
3542 return isl_basic_map_insert_dims(bmap, type,
3543 isl_basic_map_dim(bmap, type), n);
3546 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3547 enum isl_dim_type type, unsigned n)
3549 if (!bset)
3550 return NULL;
3551 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3552 return isl_basic_map_add_dims(bset, type, n);
3553 error:
3554 isl_basic_set_free(bset);
3555 return NULL;
3558 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3559 enum isl_dim_type type)
3561 isl_space *space;
3563 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3564 return map;
3566 space = isl_map_get_space(map);
3567 space = isl_space_reset(space, type);
3568 map = isl_map_reset_space(map, space);
3569 return map;
3572 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3573 enum isl_dim_type type, unsigned pos, unsigned n)
3575 int i;
3577 if (n == 0)
3578 return map_space_reset(map, type);
3580 map = isl_map_cow(map);
3581 if (!map)
3582 return NULL;
3584 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3585 if (!map->dim)
3586 goto error;
3588 for (i = 0; i < map->n; ++i) {
3589 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3590 if (!map->p[i])
3591 goto error;
3594 return map;
3595 error:
3596 isl_map_free(map);
3597 return NULL;
3600 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3601 enum isl_dim_type type, unsigned pos, unsigned n)
3603 return isl_map_insert_dims(set, type, pos, n);
3606 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3607 enum isl_dim_type type, unsigned n)
3609 if (!map)
3610 return NULL;
3611 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3614 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3615 enum isl_dim_type type, unsigned n)
3617 if (!set)
3618 return NULL;
3619 isl_assert(set->ctx, type != isl_dim_in, goto error);
3620 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
3621 error:
3622 isl_set_free(set);
3623 return NULL;
3626 __isl_give isl_basic_map *isl_basic_map_move_dims(
3627 __isl_take isl_basic_map *bmap,
3628 enum isl_dim_type dst_type, unsigned dst_pos,
3629 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3631 struct isl_dim_map *dim_map;
3632 struct isl_basic_map *res;
3633 enum isl_dim_type t;
3634 unsigned total, off;
3636 if (!bmap)
3637 return NULL;
3638 if (n == 0)
3639 return bmap;
3641 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
3642 return isl_basic_map_free(bmap);
3644 if (dst_type == src_type && dst_pos == src_pos)
3645 return bmap;
3647 isl_assert(bmap->ctx, dst_type != src_type, goto error);
3649 if (pos(bmap->dim, dst_type) + dst_pos ==
3650 pos(bmap->dim, src_type) + src_pos +
3651 ((src_type < dst_type) ? n : 0)) {
3652 bmap = isl_basic_map_cow(bmap);
3653 if (!bmap)
3654 return NULL;
3656 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3657 src_type, src_pos, n);
3658 if (!bmap->dim)
3659 goto error;
3661 bmap = isl_basic_map_finalize(bmap);
3663 return bmap;
3666 total = isl_basic_map_total_dim(bmap);
3667 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3669 off = 0;
3670 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3671 unsigned size = isl_space_dim(bmap->dim, t);
3672 if (t == dst_type) {
3673 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3674 0, dst_pos, off);
3675 off += dst_pos;
3676 isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
3677 src_pos, n, off);
3678 off += n;
3679 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3680 dst_pos, size - dst_pos, off);
3681 off += size - dst_pos;
3682 } else if (t == src_type) {
3683 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3684 0, src_pos, off);
3685 off += src_pos;
3686 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3687 src_pos + n, size - src_pos - n, off);
3688 off += size - src_pos - n;
3689 } else {
3690 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3691 off += size;
3694 isl_dim_map_div(dim_map, bmap, off);
3696 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3697 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3698 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3699 if (!bmap)
3700 goto error;
3702 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3703 src_type, src_pos, n);
3704 if (!bmap->dim)
3705 goto error;
3707 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
3708 bmap = isl_basic_map_gauss(bmap, NULL);
3709 bmap = isl_basic_map_finalize(bmap);
3711 return bmap;
3712 error:
3713 isl_basic_map_free(bmap);
3714 return NULL;
3717 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
3718 enum isl_dim_type dst_type, unsigned dst_pos,
3719 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3721 isl_basic_map *bmap = bset_to_bmap(bset);
3722 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
3723 src_type, src_pos, n);
3724 return bset_from_bmap(bmap);
3727 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
3728 enum isl_dim_type dst_type, unsigned dst_pos,
3729 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3731 if (!set)
3732 return NULL;
3733 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
3734 return set_from_map(isl_map_move_dims(set_to_map(set),
3735 dst_type, dst_pos, src_type, src_pos, n));
3736 error:
3737 isl_set_free(set);
3738 return NULL;
3741 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
3742 enum isl_dim_type dst_type, unsigned dst_pos,
3743 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3745 int i;
3747 if (!map)
3748 return NULL;
3749 if (n == 0)
3750 return map;
3752 isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type),
3753 goto error);
3755 if (dst_type == src_type && dst_pos == src_pos)
3756 return map;
3758 isl_assert(map->ctx, dst_type != src_type, goto error);
3760 map = isl_map_cow(map);
3761 if (!map)
3762 return NULL;
3764 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
3765 if (!map->dim)
3766 goto error;
3768 for (i = 0; i < map->n; ++i) {
3769 map->p[i] = isl_basic_map_move_dims(map->p[i],
3770 dst_type, dst_pos,
3771 src_type, src_pos, n);
3772 if (!map->p[i])
3773 goto error;
3776 return map;
3777 error:
3778 isl_map_free(map);
3779 return NULL;
3782 /* Move the specified dimensions to the last columns right before
3783 * the divs. Don't change the dimension specification of bmap.
3784 * That's the responsibility of the caller.
3786 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
3787 enum isl_dim_type type, unsigned first, unsigned n)
3789 struct isl_dim_map *dim_map;
3790 struct isl_basic_map *res;
3791 enum isl_dim_type t;
3792 unsigned total, off;
3794 if (!bmap)
3795 return NULL;
3796 if (pos(bmap->dim, type) + first + n ==
3797 1 + isl_space_dim(bmap->dim, isl_dim_all))
3798 return bmap;
3800 total = isl_basic_map_total_dim(bmap);
3801 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3803 off = 0;
3804 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3805 unsigned size = isl_space_dim(bmap->dim, t);
3806 if (t == type) {
3807 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3808 0, first, off);
3809 off += first;
3810 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3811 first, n, total - bmap->n_div - n);
3812 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3813 first + n, size - (first + n), off);
3814 off += size - (first + n);
3815 } else {
3816 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3817 off += size;
3820 isl_dim_map_div(dim_map, bmap, off + n);
3822 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3823 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3824 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3825 return res;
3828 /* Insert "n" rows in the divs of "bmap".
3830 * The number of columns is not changed, which means that the last
3831 * dimensions of "bmap" are being reintepreted as the new divs.
3832 * The space of "bmap" is not adjusted, however, which means
3833 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
3834 * from the space of "bmap" is the responsibility of the caller.
3836 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
3837 int n)
3839 int i;
3840 size_t row_size;
3841 isl_int **new_div;
3842 isl_int *old;
3844 bmap = isl_basic_map_cow(bmap);
3845 if (!bmap)
3846 return NULL;
3848 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
3849 old = bmap->block2.data;
3850 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
3851 (bmap->extra + n) * (1 + row_size));
3852 if (!bmap->block2.data)
3853 return isl_basic_map_free(bmap);
3854 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
3855 if (!new_div)
3856 return isl_basic_map_free(bmap);
3857 for (i = 0; i < n; ++i) {
3858 new_div[i] = bmap->block2.data +
3859 (bmap->extra + i) * (1 + row_size);
3860 isl_seq_clr(new_div[i], 1 + row_size);
3862 for (i = 0; i < bmap->extra; ++i)
3863 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
3864 free(bmap->div);
3865 bmap->div = new_div;
3866 bmap->n_div += n;
3867 bmap->extra += n;
3869 return bmap;
3872 /* Drop constraints from "bmap" that only involve the variables
3873 * of "type" in the range [first, first + n] that are not related
3874 * to any of the variables outside that interval.
3875 * These constraints cannot influence the values for the variables
3876 * outside the interval, except in case they cause "bmap" to be empty.
3877 * Only drop the constraints if "bmap" is known to be non-empty.
3879 static __isl_give isl_basic_map *drop_irrelevant_constraints(
3880 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3881 unsigned first, unsigned n)
3883 int i;
3884 int *groups;
3885 unsigned dim, n_div;
3886 isl_bool non_empty;
3888 non_empty = isl_basic_map_plain_is_non_empty(bmap);
3889 if (non_empty < 0)
3890 return isl_basic_map_free(bmap);
3891 if (!non_empty)
3892 return bmap;
3894 dim = isl_basic_map_dim(bmap, isl_dim_all);
3895 n_div = isl_basic_map_dim(bmap, isl_dim_div);
3896 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
3897 if (!groups)
3898 return isl_basic_map_free(bmap);
3899 first += isl_basic_map_offset(bmap, type) - 1;
3900 for (i = 0; i < first; ++i)
3901 groups[i] = -1;
3902 for (i = first + n; i < dim - n_div; ++i)
3903 groups[i] = -1;
3905 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
3907 return bmap;
3910 /* Turn the n dimensions of type type, starting at first
3911 * into existentially quantified variables.
3913 * If a subset of the projected out variables are unrelated
3914 * to any of the variables that remain, then the constraints
3915 * involving this subset are simply dropped first.
3917 __isl_give isl_basic_map *isl_basic_map_project_out(
3918 __isl_take isl_basic_map *bmap,
3919 enum isl_dim_type type, unsigned first, unsigned n)
3921 if (n == 0)
3922 return basic_map_space_reset(bmap, type);
3923 if (type == isl_dim_div)
3924 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3925 "cannot project out existentially quantified variables",
3926 return isl_basic_map_free(bmap));
3928 bmap = drop_irrelevant_constraints(bmap, type, first, n);
3929 if (!bmap)
3930 return NULL;
3932 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
3933 return isl_basic_map_remove_dims(bmap, type, first, n);
3935 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3936 return isl_basic_map_free(bmap);
3938 bmap = move_last(bmap, type, first, n);
3939 bmap = isl_basic_map_cow(bmap);
3940 bmap = insert_div_rows(bmap, n);
3941 if (!bmap)
3942 return NULL;
3944 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
3945 if (!bmap->dim)
3946 goto error;
3947 bmap = isl_basic_map_simplify(bmap);
3948 bmap = isl_basic_map_drop_redundant_divs(bmap);
3949 return isl_basic_map_finalize(bmap);
3950 error:
3951 isl_basic_map_free(bmap);
3952 return NULL;
3955 /* Turn the n dimensions of type type, starting at first
3956 * into existentially quantified variables.
3958 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
3959 enum isl_dim_type type, unsigned first, unsigned n)
3961 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
3962 type, first, n));
3965 /* Turn the n dimensions of type type, starting at first
3966 * into existentially quantified variables.
3968 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
3969 enum isl_dim_type type, unsigned first, unsigned n)
3971 int i;
3973 if (!map)
3974 return NULL;
3976 if (n == 0)
3977 return map_space_reset(map, type);
3979 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
3981 map = isl_map_cow(map);
3982 if (!map)
3983 return NULL;
3985 map->dim = isl_space_drop_dims(map->dim, type, first, n);
3986 if (!map->dim)
3987 goto error;
3989 for (i = 0; i < map->n; ++i) {
3990 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
3991 if (!map->p[i])
3992 goto error;
3995 return map;
3996 error:
3997 isl_map_free(map);
3998 return NULL;
4001 /* Turn the n dimensions of type type, starting at first
4002 * into existentially quantified variables.
4004 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4005 enum isl_dim_type type, unsigned first, unsigned n)
4007 return set_from_map(isl_map_project_out(set_to_map(set),
4008 type, first, n));
4011 /* Return a map that projects the elements in "set" onto their
4012 * "n" set dimensions starting at "first".
4013 * "type" should be equal to isl_dim_set.
4015 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4016 enum isl_dim_type type, unsigned first, unsigned n)
4018 int i;
4019 int dim;
4020 isl_map *map;
4022 if (!set)
4023 return NULL;
4024 if (type != isl_dim_set)
4025 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4026 "only set dimensions can be projected out", goto error);
4027 dim = isl_set_dim(set, isl_dim_set);
4028 if (first + n > dim || first + n < first)
4029 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4030 "index out of bounds", goto error);
4032 map = isl_map_from_domain(set);
4033 map = isl_map_add_dims(map, isl_dim_out, n);
4034 for (i = 0; i < n; ++i)
4035 map = isl_map_equate(map, isl_dim_in, first + i,
4036 isl_dim_out, i);
4037 return map;
4038 error:
4039 isl_set_free(set);
4040 return NULL;
4043 static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
4045 int i, j;
4047 for (i = 0; i < n; ++i) {
4048 j = isl_basic_map_alloc_div(bmap);
4049 if (j < 0)
4050 goto error;
4051 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4053 return bmap;
4054 error:
4055 isl_basic_map_free(bmap);
4056 return NULL;
4059 struct isl_basic_map *isl_basic_map_apply_range(
4060 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4062 isl_space *dim_result = NULL;
4063 struct isl_basic_map *bmap;
4064 unsigned n_in, n_out, n, nparam, total, pos;
4065 struct isl_dim_map *dim_map1, *dim_map2;
4067 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4068 goto error;
4069 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4070 bmap2->dim, isl_dim_in))
4071 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4072 "spaces don't match", goto error);
4074 dim_result = isl_space_join(isl_space_copy(bmap1->dim),
4075 isl_space_copy(bmap2->dim));
4077 n_in = isl_basic_map_n_in(bmap1);
4078 n_out = isl_basic_map_n_out(bmap2);
4079 n = isl_basic_map_n_out(bmap1);
4080 nparam = isl_basic_map_n_param(bmap1);
4082 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4083 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4084 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4085 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4086 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4087 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4088 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4089 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4090 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4091 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4092 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4094 bmap = isl_basic_map_alloc_space(dim_result,
4095 bmap1->n_div + bmap2->n_div + n,
4096 bmap1->n_eq + bmap2->n_eq,
4097 bmap1->n_ineq + bmap2->n_ineq);
4098 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4099 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4100 bmap = add_divs(bmap, n);
4101 bmap = isl_basic_map_simplify(bmap);
4102 bmap = isl_basic_map_drop_redundant_divs(bmap);
4103 return isl_basic_map_finalize(bmap);
4104 error:
4105 isl_basic_map_free(bmap1);
4106 isl_basic_map_free(bmap2);
4107 return NULL;
4110 struct isl_basic_set *isl_basic_set_apply(
4111 struct isl_basic_set *bset, struct isl_basic_map *bmap)
4113 if (!bset || !bmap)
4114 goto error;
4116 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4117 goto error);
4119 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4120 bmap));
4121 error:
4122 isl_basic_set_free(bset);
4123 isl_basic_map_free(bmap);
4124 return NULL;
4127 struct isl_basic_map *isl_basic_map_apply_domain(
4128 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4130 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4131 goto error;
4132 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4133 bmap2->dim, isl_dim_in))
4134 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4135 "spaces don't match", goto error);
4137 bmap1 = isl_basic_map_reverse(bmap1);
4138 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4139 return isl_basic_map_reverse(bmap1);
4140 error:
4141 isl_basic_map_free(bmap1);
4142 isl_basic_map_free(bmap2);
4143 return NULL;
4146 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4147 * A \cap B -> f(A) + f(B)
4149 struct isl_basic_map *isl_basic_map_sum(
4150 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4152 unsigned n_in, n_out, nparam, total, pos;
4153 struct isl_basic_map *bmap = NULL;
4154 struct isl_dim_map *dim_map1, *dim_map2;
4155 int i;
4157 if (!bmap1 || !bmap2)
4158 goto error;
4160 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4161 goto error);
4163 nparam = isl_basic_map_n_param(bmap1);
4164 n_in = isl_basic_map_n_in(bmap1);
4165 n_out = isl_basic_map_n_out(bmap1);
4167 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4168 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4169 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4170 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4171 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4172 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4173 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4174 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4175 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4176 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4177 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4179 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4180 bmap1->n_div + bmap2->n_div + 2 * n_out,
4181 bmap1->n_eq + bmap2->n_eq + n_out,
4182 bmap1->n_ineq + bmap2->n_ineq);
4183 for (i = 0; i < n_out; ++i) {
4184 int j = isl_basic_map_alloc_equality(bmap);
4185 if (j < 0)
4186 goto error;
4187 isl_seq_clr(bmap->eq[j], 1+total);
4188 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4189 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4190 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4192 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4193 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4194 bmap = add_divs(bmap, 2 * n_out);
4196 bmap = isl_basic_map_simplify(bmap);
4197 return isl_basic_map_finalize(bmap);
4198 error:
4199 isl_basic_map_free(bmap);
4200 isl_basic_map_free(bmap1);
4201 isl_basic_map_free(bmap2);
4202 return NULL;
4205 /* Given two maps A -> f(A) and B -> g(B), construct a map
4206 * A \cap B -> f(A) + f(B)
4208 struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2)
4210 struct isl_map *result;
4211 int i, j;
4213 if (!map1 || !map2)
4214 goto error;
4216 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4218 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4219 map1->n * map2->n, 0);
4220 if (!result)
4221 goto error;
4222 for (i = 0; i < map1->n; ++i)
4223 for (j = 0; j < map2->n; ++j) {
4224 struct isl_basic_map *part;
4225 part = isl_basic_map_sum(
4226 isl_basic_map_copy(map1->p[i]),
4227 isl_basic_map_copy(map2->p[j]));
4228 if (isl_basic_map_is_empty(part))
4229 isl_basic_map_free(part);
4230 else
4231 result = isl_map_add_basic_map(result, part);
4232 if (!result)
4233 goto error;
4235 isl_map_free(map1);
4236 isl_map_free(map2);
4237 return result;
4238 error:
4239 isl_map_free(map1);
4240 isl_map_free(map2);
4241 return NULL;
4244 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4245 __isl_take isl_set *set2)
4247 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4250 /* Given a basic map A -> f(A), construct A -> -f(A).
4252 struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap)
4254 int i, j;
4255 unsigned off, n;
4257 bmap = isl_basic_map_cow(bmap);
4258 if (!bmap)
4259 return NULL;
4261 n = isl_basic_map_dim(bmap, isl_dim_out);
4262 off = isl_basic_map_offset(bmap, isl_dim_out);
4263 for (i = 0; i < bmap->n_eq; ++i)
4264 for (j = 0; j < n; ++j)
4265 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4266 for (i = 0; i < bmap->n_ineq; ++i)
4267 for (j = 0; j < n; ++j)
4268 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4269 for (i = 0; i < bmap->n_div; ++i)
4270 for (j = 0; j < n; ++j)
4271 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4272 bmap = isl_basic_map_gauss(bmap, NULL);
4273 return isl_basic_map_finalize(bmap);
4276 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4278 return isl_basic_map_neg(bset);
4281 /* Given a map A -> f(A), construct A -> -f(A).
4283 struct isl_map *isl_map_neg(struct isl_map *map)
4285 int i;
4287 map = isl_map_cow(map);
4288 if (!map)
4289 return NULL;
4291 for (i = 0; i < map->n; ++i) {
4292 map->p[i] = isl_basic_map_neg(map->p[i]);
4293 if (!map->p[i])
4294 goto error;
4297 return map;
4298 error:
4299 isl_map_free(map);
4300 return NULL;
4303 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4305 return set_from_map(isl_map_neg(set_to_map(set)));
4308 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4309 * A -> floor(f(A)/d).
4311 struct isl_basic_map *isl_basic_map_floordiv(struct isl_basic_map *bmap,
4312 isl_int d)
4314 unsigned n_in, n_out, nparam, total, pos;
4315 struct isl_basic_map *result = NULL;
4316 struct isl_dim_map *dim_map;
4317 int i;
4319 if (!bmap)
4320 return NULL;
4322 nparam = isl_basic_map_n_param(bmap);
4323 n_in = isl_basic_map_n_in(bmap);
4324 n_out = isl_basic_map_n_out(bmap);
4326 total = nparam + n_in + n_out + bmap->n_div + n_out;
4327 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4328 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4329 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4330 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4331 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4333 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4334 bmap->n_div + n_out,
4335 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4336 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4337 result = add_divs(result, n_out);
4338 for (i = 0; i < n_out; ++i) {
4339 int j;
4340 j = isl_basic_map_alloc_inequality(result);
4341 if (j < 0)
4342 goto error;
4343 isl_seq_clr(result->ineq[j], 1+total);
4344 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4345 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4346 j = isl_basic_map_alloc_inequality(result);
4347 if (j < 0)
4348 goto error;
4349 isl_seq_clr(result->ineq[j], 1+total);
4350 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4351 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4352 isl_int_sub_ui(result->ineq[j][0], d, 1);
4355 result = isl_basic_map_simplify(result);
4356 return isl_basic_map_finalize(result);
4357 error:
4358 isl_basic_map_free(result);
4359 return NULL;
4362 /* Given a map A -> f(A) and an integer d, construct a map
4363 * A -> floor(f(A)/d).
4365 struct isl_map *isl_map_floordiv(struct isl_map *map, isl_int d)
4367 int i;
4369 map = isl_map_cow(map);
4370 if (!map)
4371 return NULL;
4373 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4374 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
4375 for (i = 0; i < map->n; ++i) {
4376 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4377 if (!map->p[i])
4378 goto error;
4381 return map;
4382 error:
4383 isl_map_free(map);
4384 return NULL;
4387 /* Given a map A -> f(A) and an integer d, construct a map
4388 * A -> floor(f(A)/d).
4390 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4391 __isl_take isl_val *d)
4393 if (!map || !d)
4394 goto error;
4395 if (!isl_val_is_int(d))
4396 isl_die(isl_val_get_ctx(d), isl_error_invalid,
4397 "expecting integer denominator", goto error);
4398 map = isl_map_floordiv(map, d->n);
4399 isl_val_free(d);
4400 return map;
4401 error:
4402 isl_map_free(map);
4403 isl_val_free(d);
4404 return NULL;
4407 static struct isl_basic_map *var_equal(struct isl_basic_map *bmap, unsigned pos)
4409 int i;
4410 unsigned nparam;
4411 unsigned n_in;
4413 i = isl_basic_map_alloc_equality(bmap);
4414 if (i < 0)
4415 goto error;
4416 nparam = isl_basic_map_n_param(bmap);
4417 n_in = isl_basic_map_n_in(bmap);
4418 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4419 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4420 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4421 return isl_basic_map_finalize(bmap);
4422 error:
4423 isl_basic_map_free(bmap);
4424 return NULL;
4427 /* Add a constraint to "bmap" expressing i_pos < o_pos
4429 static struct isl_basic_map *var_less(struct isl_basic_map *bmap, unsigned pos)
4431 int i;
4432 unsigned nparam;
4433 unsigned n_in;
4435 i = isl_basic_map_alloc_inequality(bmap);
4436 if (i < 0)
4437 goto error;
4438 nparam = isl_basic_map_n_param(bmap);
4439 n_in = isl_basic_map_n_in(bmap);
4440 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4441 isl_int_set_si(bmap->ineq[i][0], -1);
4442 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4443 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4444 return isl_basic_map_finalize(bmap);
4445 error:
4446 isl_basic_map_free(bmap);
4447 return NULL;
4450 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4452 static __isl_give isl_basic_map *var_less_or_equal(
4453 __isl_take isl_basic_map *bmap, unsigned pos)
4455 int i;
4456 unsigned nparam;
4457 unsigned n_in;
4459 i = isl_basic_map_alloc_inequality(bmap);
4460 if (i < 0)
4461 goto error;
4462 nparam = isl_basic_map_n_param(bmap);
4463 n_in = isl_basic_map_n_in(bmap);
4464 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4465 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4466 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4467 return isl_basic_map_finalize(bmap);
4468 error:
4469 isl_basic_map_free(bmap);
4470 return NULL;
4473 /* Add a constraint to "bmap" expressing i_pos > o_pos
4475 static struct isl_basic_map *var_more(struct isl_basic_map *bmap, unsigned pos)
4477 int i;
4478 unsigned nparam;
4479 unsigned n_in;
4481 i = isl_basic_map_alloc_inequality(bmap);
4482 if (i < 0)
4483 goto error;
4484 nparam = isl_basic_map_n_param(bmap);
4485 n_in = isl_basic_map_n_in(bmap);
4486 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4487 isl_int_set_si(bmap->ineq[i][0], -1);
4488 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4489 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4490 return isl_basic_map_finalize(bmap);
4491 error:
4492 isl_basic_map_free(bmap);
4493 return NULL;
4496 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4498 static __isl_give isl_basic_map *var_more_or_equal(
4499 __isl_take isl_basic_map *bmap, unsigned pos)
4501 int i;
4502 unsigned nparam;
4503 unsigned n_in;
4505 i = isl_basic_map_alloc_inequality(bmap);
4506 if (i < 0)
4507 goto error;
4508 nparam = isl_basic_map_n_param(bmap);
4509 n_in = isl_basic_map_n_in(bmap);
4510 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4511 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4512 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4513 return isl_basic_map_finalize(bmap);
4514 error:
4515 isl_basic_map_free(bmap);
4516 return NULL;
4519 __isl_give isl_basic_map *isl_basic_map_equal(
4520 __isl_take isl_space *dim, unsigned n_equal)
4522 int i;
4523 struct isl_basic_map *bmap;
4524 bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
4525 if (!bmap)
4526 return NULL;
4527 for (i = 0; i < n_equal && bmap; ++i)
4528 bmap = var_equal(bmap, i);
4529 return isl_basic_map_finalize(bmap);
4532 /* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
4534 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
4535 unsigned pos)
4537 int i;
4538 struct isl_basic_map *bmap;
4539 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4540 if (!bmap)
4541 return NULL;
4542 for (i = 0; i < pos && bmap; ++i)
4543 bmap = var_equal(bmap, i);
4544 if (bmap)
4545 bmap = var_less(bmap, pos);
4546 return isl_basic_map_finalize(bmap);
4549 /* Return a relation on "dim" expressing i_[0..pos] <<= o_[0..pos]
4551 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4552 __isl_take isl_space *dim, unsigned pos)
4554 int i;
4555 isl_basic_map *bmap;
4557 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4558 for (i = 0; i < pos; ++i)
4559 bmap = var_equal(bmap, i);
4560 bmap = var_less_or_equal(bmap, pos);
4561 return isl_basic_map_finalize(bmap);
4564 /* Return a relation on "dim" expressing i_pos > o_pos
4566 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
4567 unsigned pos)
4569 int i;
4570 struct isl_basic_map *bmap;
4571 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4572 if (!bmap)
4573 return NULL;
4574 for (i = 0; i < pos && bmap; ++i)
4575 bmap = var_equal(bmap, i);
4576 if (bmap)
4577 bmap = var_more(bmap, pos);
4578 return isl_basic_map_finalize(bmap);
4581 /* Return a relation on "dim" expressing i_[0..pos] >>= o_[0..pos]
4583 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4584 __isl_take isl_space *dim, unsigned pos)
4586 int i;
4587 isl_basic_map *bmap;
4589 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4590 for (i = 0; i < pos; ++i)
4591 bmap = var_equal(bmap, i);
4592 bmap = var_more_or_equal(bmap, pos);
4593 return isl_basic_map_finalize(bmap);
4596 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
4597 unsigned n, int equal)
4599 struct isl_map *map;
4600 int i;
4602 if (n == 0 && equal)
4603 return isl_map_universe(dims);
4605 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4607 for (i = 0; i + 1 < n; ++i)
4608 map = isl_map_add_basic_map(map,
4609 isl_basic_map_less_at(isl_space_copy(dims), i));
4610 if (n > 0) {
4611 if (equal)
4612 map = isl_map_add_basic_map(map,
4613 isl_basic_map_less_or_equal_at(dims, n - 1));
4614 else
4615 map = isl_map_add_basic_map(map,
4616 isl_basic_map_less_at(dims, n - 1));
4617 } else
4618 isl_space_free(dims);
4620 return map;
4623 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
4625 if (!dims)
4626 return NULL;
4627 return map_lex_lte_first(dims, dims->n_out, equal);
4630 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
4632 return map_lex_lte_first(dim, n, 0);
4635 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
4637 return map_lex_lte_first(dim, n, 1);
4640 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
4642 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
4645 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
4647 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
4650 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
4651 unsigned n, int equal)
4653 struct isl_map *map;
4654 int i;
4656 if (n == 0 && equal)
4657 return isl_map_universe(dims);
4659 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4661 for (i = 0; i + 1 < n; ++i)
4662 map = isl_map_add_basic_map(map,
4663 isl_basic_map_more_at(isl_space_copy(dims), i));
4664 if (n > 0) {
4665 if (equal)
4666 map = isl_map_add_basic_map(map,
4667 isl_basic_map_more_or_equal_at(dims, n - 1));
4668 else
4669 map = isl_map_add_basic_map(map,
4670 isl_basic_map_more_at(dims, n - 1));
4671 } else
4672 isl_space_free(dims);
4674 return map;
4677 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
4679 if (!dims)
4680 return NULL;
4681 return map_lex_gte_first(dims, dims->n_out, equal);
4684 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
4686 return map_lex_gte_first(dim, n, 0);
4689 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
4691 return map_lex_gte_first(dim, n, 1);
4694 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
4696 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
4699 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
4701 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
4704 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
4705 __isl_take isl_set *set2)
4707 isl_map *map;
4708 map = isl_map_lex_le(isl_set_get_space(set1));
4709 map = isl_map_intersect_domain(map, set1);
4710 map = isl_map_intersect_range(map, set2);
4711 return map;
4714 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
4715 __isl_take isl_set *set2)
4717 isl_map *map;
4718 map = isl_map_lex_lt(isl_set_get_space(set1));
4719 map = isl_map_intersect_domain(map, set1);
4720 map = isl_map_intersect_range(map, set2);
4721 return map;
4724 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
4725 __isl_take isl_set *set2)
4727 isl_map *map;
4728 map = isl_map_lex_ge(isl_set_get_space(set1));
4729 map = isl_map_intersect_domain(map, set1);
4730 map = isl_map_intersect_range(map, set2);
4731 return map;
4734 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
4735 __isl_take isl_set *set2)
4737 isl_map *map;
4738 map = isl_map_lex_gt(isl_set_get_space(set1));
4739 map = isl_map_intersect_domain(map, set1);
4740 map = isl_map_intersect_range(map, set2);
4741 return map;
4744 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
4745 __isl_take isl_map *map2)
4747 isl_map *map;
4748 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
4749 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4750 map = isl_map_apply_range(map, isl_map_reverse(map2));
4751 return map;
4754 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
4755 __isl_take isl_map *map2)
4757 isl_map *map;
4758 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
4759 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4760 map = isl_map_apply_range(map, isl_map_reverse(map2));
4761 return map;
4764 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
4765 __isl_take isl_map *map2)
4767 isl_map *map;
4768 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
4769 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4770 map = isl_map_apply_range(map, isl_map_reverse(map2));
4771 return map;
4774 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
4775 __isl_take isl_map *map2)
4777 isl_map *map;
4778 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
4779 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4780 map = isl_map_apply_range(map, isl_map_reverse(map2));
4781 return map;
4784 /* For a div d = floor(f/m), add the constraint
4786 * f - m d >= 0
4788 static isl_stat add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
4789 unsigned pos, isl_int *div)
4791 int i;
4792 unsigned total = isl_basic_map_total_dim(bmap);
4794 i = isl_basic_map_alloc_inequality(bmap);
4795 if (i < 0)
4796 return isl_stat_error;
4797 isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
4798 isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
4800 return isl_stat_ok;
4803 /* For a div d = floor(f/m), add the constraint
4805 * -(f-(m-1)) + m d >= 0
4807 static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
4808 unsigned pos, isl_int *div)
4810 int i;
4811 unsigned total = isl_basic_map_total_dim(bmap);
4813 i = isl_basic_map_alloc_inequality(bmap);
4814 if (i < 0)
4815 return isl_stat_error;
4816 isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
4817 isl_int_set(bmap->ineq[i][1 + pos], div[0]);
4818 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
4819 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
4821 return isl_stat_ok;
4824 /* For a div d = floor(f/m), add the constraints
4826 * f - m d >= 0
4827 * -(f-(m-1)) + m d >= 0
4829 * Note that the second constraint is the negation of
4831 * f - m d >= m
4833 int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
4834 unsigned pos, isl_int *div)
4836 if (add_upper_div_constraint(bmap, pos, div) < 0)
4837 return -1;
4838 if (add_lower_div_constraint(bmap, pos, div) < 0)
4839 return -1;
4840 return 0;
4843 int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
4844 unsigned pos, isl_int *div)
4846 return isl_basic_map_add_div_constraints_var(bset_to_bmap(bset),
4847 pos, div);
4850 int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
4852 unsigned total = isl_basic_map_total_dim(bmap);
4853 unsigned div_pos = total - bmap->n_div + div;
4855 return isl_basic_map_add_div_constraints_var(bmap, div_pos,
4856 bmap->div[div]);
4859 /* For each known div d = floor(f/m), add the constraints
4861 * f - m d >= 0
4862 * -(f-(m-1)) + m d >= 0
4864 * Remove duplicate constraints in case of some these div constraints
4865 * already appear in "bmap".
4867 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
4868 __isl_take isl_basic_map *bmap)
4870 unsigned n_div;
4872 if (!bmap)
4873 return NULL;
4874 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4875 if (n_div == 0)
4876 return bmap;
4878 bmap = add_known_div_constraints(bmap);
4879 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
4880 bmap = isl_basic_map_finalize(bmap);
4881 return bmap;
4884 /* Add the div constraint of sign "sign" for div "div" of "bmap".
4886 * In particular, if this div is of the form d = floor(f/m),
4887 * then add the constraint
4889 * f - m d >= 0
4891 * if sign < 0 or the constraint
4893 * -(f-(m-1)) + m d >= 0
4895 * if sign > 0.
4897 int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
4898 unsigned div, int sign)
4900 unsigned total;
4901 unsigned div_pos;
4903 if (!bmap)
4904 return -1;
4906 total = isl_basic_map_total_dim(bmap);
4907 div_pos = total - bmap->n_div + div;
4909 if (sign < 0)
4910 return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
4911 else
4912 return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
4915 struct isl_basic_set *isl_basic_map_underlying_set(
4916 struct isl_basic_map *bmap)
4918 if (!bmap)
4919 goto error;
4920 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
4921 bmap->n_div == 0 &&
4922 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
4923 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
4924 return bset_from_bmap(bmap);
4925 bmap = isl_basic_map_cow(bmap);
4926 if (!bmap)
4927 goto error;
4928 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
4929 if (!bmap->dim)
4930 goto error;
4931 bmap->extra -= bmap->n_div;
4932 bmap->n_div = 0;
4933 bmap = isl_basic_map_finalize(bmap);
4934 return bset_from_bmap(bmap);
4935 error:
4936 isl_basic_map_free(bmap);
4937 return NULL;
4940 __isl_give isl_basic_set *isl_basic_set_underlying_set(
4941 __isl_take isl_basic_set *bset)
4943 return isl_basic_map_underlying_set(bset_to_bmap(bset));
4946 /* Replace each element in "list" by the result of applying
4947 * isl_basic_map_underlying_set to the element.
4949 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
4950 __isl_take isl_basic_map_list *list)
4952 int i, n;
4954 if (!list)
4955 return NULL;
4957 n = isl_basic_map_list_n_basic_map(list);
4958 for (i = 0; i < n; ++i) {
4959 isl_basic_map *bmap;
4960 isl_basic_set *bset;
4962 bmap = isl_basic_map_list_get_basic_map(list, i);
4963 bset = isl_basic_set_underlying_set(bmap);
4964 list = isl_basic_set_list_set_basic_set(list, i, bset);
4967 return list;
4970 struct isl_basic_map *isl_basic_map_overlying_set(
4971 struct isl_basic_set *bset, struct isl_basic_map *like)
4973 struct isl_basic_map *bmap;
4974 struct isl_ctx *ctx;
4975 unsigned total;
4976 int i;
4978 if (!bset || !like)
4979 goto error;
4980 ctx = bset->ctx;
4981 isl_assert(ctx, bset->n_div == 0, goto error);
4982 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
4983 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
4984 goto error);
4985 if (like->n_div == 0) {
4986 isl_space *space = isl_basic_map_get_space(like);
4987 isl_basic_map_free(like);
4988 return isl_basic_map_reset_space(bset, space);
4990 bset = isl_basic_set_cow(bset);
4991 if (!bset)
4992 goto error;
4993 total = bset->dim->n_out + bset->extra;
4994 bmap = bset_to_bmap(bset);
4995 isl_space_free(bmap->dim);
4996 bmap->dim = isl_space_copy(like->dim);
4997 if (!bmap->dim)
4998 goto error;
4999 bmap->n_div = like->n_div;
5000 bmap->extra += like->n_div;
5001 if (bmap->extra) {
5002 unsigned ltotal;
5003 isl_int **div;
5004 ltotal = total - bmap->extra + like->extra;
5005 if (ltotal > total)
5006 ltotal = total;
5007 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5008 bmap->extra * (1 + 1 + total));
5009 if (isl_blk_is_error(bmap->block2))
5010 goto error;
5011 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5012 if (!div)
5013 goto error;
5014 bmap->div = div;
5015 for (i = 0; i < bmap->extra; ++i)
5016 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5017 for (i = 0; i < like->n_div; ++i) {
5018 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5019 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5021 bmap = isl_basic_map_add_known_div_constraints(bmap);
5023 isl_basic_map_free(like);
5024 bmap = isl_basic_map_simplify(bmap);
5025 bmap = isl_basic_map_finalize(bmap);
5026 return bmap;
5027 error:
5028 isl_basic_map_free(like);
5029 isl_basic_set_free(bset);
5030 return NULL;
5033 struct isl_basic_set *isl_basic_set_from_underlying_set(
5034 struct isl_basic_set *bset, struct isl_basic_set *like)
5036 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5037 bset_to_bmap(like)));
5040 struct isl_set *isl_map_underlying_set(struct isl_map *map)
5042 int i;
5044 map = isl_map_cow(map);
5045 if (!map)
5046 return NULL;
5047 map->dim = isl_space_cow(map->dim);
5048 if (!map->dim)
5049 goto error;
5051 for (i = 1; i < map->n; ++i)
5052 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5053 goto error);
5054 for (i = 0; i < map->n; ++i) {
5055 map->p[i] = bset_to_bmap(
5056 isl_basic_map_underlying_set(map->p[i]));
5057 if (!map->p[i])
5058 goto error;
5060 if (map->n == 0)
5061 map->dim = isl_space_underlying(map->dim, 0);
5062 else {
5063 isl_space_free(map->dim);
5064 map->dim = isl_space_copy(map->p[0]->dim);
5066 if (!map->dim)
5067 goto error;
5068 return set_from_map(map);
5069 error:
5070 isl_map_free(map);
5071 return NULL;
5074 /* Replace the space of "bmap" by "space".
5076 * If the space of "bmap" is identical to "space" (including the identifiers
5077 * of the input and output dimensions), then simply return the original input.
5079 __isl_give isl_basic_map *isl_basic_map_reset_space(
5080 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5082 isl_bool equal;
5083 isl_space *bmap_space;
5085 bmap_space = isl_basic_map_peek_space(bmap);
5086 equal = isl_space_is_equal(bmap_space, space);
5087 if (equal >= 0 && equal)
5088 equal = isl_space_match(bmap_space, isl_dim_in,
5089 space, isl_dim_in);
5090 if (equal >= 0 && equal)
5091 equal = isl_space_match(bmap_space, isl_dim_out,
5092 space, isl_dim_out);
5093 if (equal < 0)
5094 goto error;
5095 if (equal) {
5096 isl_space_free(space);
5097 return bmap;
5099 bmap = isl_basic_map_cow(bmap);
5100 if (!bmap || !space)
5101 goto error;
5103 isl_space_free(bmap->dim);
5104 bmap->dim = space;
5106 bmap = isl_basic_map_finalize(bmap);
5108 return bmap;
5109 error:
5110 isl_basic_map_free(bmap);
5111 isl_space_free(space);
5112 return NULL;
5115 __isl_give isl_basic_set *isl_basic_set_reset_space(
5116 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5118 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5119 dim));
5122 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5123 __isl_take isl_space *dim)
5125 int i;
5127 map = isl_map_cow(map);
5128 if (!map || !dim)
5129 goto error;
5131 for (i = 0; i < map->n; ++i) {
5132 map->p[i] = isl_basic_map_reset_space(map->p[i],
5133 isl_space_copy(dim));
5134 if (!map->p[i])
5135 goto error;
5137 isl_space_free(map->dim);
5138 map->dim = dim;
5140 return map;
5141 error:
5142 isl_map_free(map);
5143 isl_space_free(dim);
5144 return NULL;
5147 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5148 __isl_take isl_space *dim)
5150 return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5153 /* Compute the parameter domain of the given basic set.
5155 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5157 isl_bool is_params;
5158 isl_space *space;
5159 unsigned n;
5161 is_params = isl_basic_set_is_params(bset);
5162 if (is_params < 0)
5163 return isl_basic_set_free(bset);
5164 if (is_params)
5165 return bset;
5167 n = isl_basic_set_dim(bset, isl_dim_set);
5168 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5169 space = isl_basic_set_get_space(bset);
5170 space = isl_space_params(space);
5171 bset = isl_basic_set_reset_space(bset, space);
5172 return bset;
5175 /* Construct a zero-dimensional basic set with the given parameter domain.
5177 __isl_give isl_basic_set *isl_basic_set_from_params(
5178 __isl_take isl_basic_set *bset)
5180 isl_space *space;
5181 space = isl_basic_set_get_space(bset);
5182 space = isl_space_set_from_params(space);
5183 bset = isl_basic_set_reset_space(bset, space);
5184 return bset;
5187 /* Compute the parameter domain of the given set.
5189 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5191 isl_space *space;
5192 unsigned n;
5194 if (isl_set_is_params(set))
5195 return set;
5197 n = isl_set_dim(set, isl_dim_set);
5198 set = isl_set_project_out(set, isl_dim_set, 0, n);
5199 space = isl_set_get_space(set);
5200 space = isl_space_params(space);
5201 set = isl_set_reset_space(set, space);
5202 return set;
5205 /* Construct a zero-dimensional set with the given parameter domain.
5207 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5209 isl_space *space;
5210 space = isl_set_get_space(set);
5211 space = isl_space_set_from_params(space);
5212 set = isl_set_reset_space(set, space);
5213 return set;
5216 /* Compute the parameter domain of the given map.
5218 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5220 isl_space *space;
5221 unsigned n;
5223 n = isl_map_dim(map, isl_dim_in);
5224 map = isl_map_project_out(map, isl_dim_in, 0, n);
5225 n = isl_map_dim(map, isl_dim_out);
5226 map = isl_map_project_out(map, isl_dim_out, 0, n);
5227 space = isl_map_get_space(map);
5228 space = isl_space_params(space);
5229 map = isl_map_reset_space(map, space);
5230 return map;
5233 struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
5235 isl_space *space;
5236 unsigned n_out;
5238 if (!bmap)
5239 return NULL;
5240 space = isl_space_domain(isl_basic_map_get_space(bmap));
5242 n_out = isl_basic_map_n_out(bmap);
5243 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5245 return isl_basic_map_reset_space(bmap, space);
5248 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5250 if (!bmap)
5251 return isl_bool_error;
5252 return isl_space_may_be_set(bmap->dim);
5255 /* Is this basic map actually a set?
5256 * Users should never call this function. Outside of isl,
5257 * the type should indicate whether something is a set or a map.
5259 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5261 if (!bmap)
5262 return isl_bool_error;
5263 return isl_space_is_set(bmap->dim);
5266 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5268 isl_bool is_set;
5270 is_set = isl_basic_map_is_set(bmap);
5271 if (is_set < 0)
5272 goto error;
5273 if (is_set)
5274 return bmap;
5275 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5276 error:
5277 isl_basic_map_free(bmap);
5278 return NULL;
5281 __isl_give isl_basic_map *isl_basic_map_domain_map(
5282 __isl_take isl_basic_map *bmap)
5284 int i;
5285 isl_space *dim;
5286 isl_basic_map *domain;
5287 int nparam, n_in, n_out;
5289 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5290 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5291 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5293 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
5294 domain = isl_basic_map_universe(dim);
5296 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5297 bmap = isl_basic_map_apply_range(bmap, domain);
5298 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5300 for (i = 0; i < n_in; ++i)
5301 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5302 isl_dim_out, i);
5304 bmap = isl_basic_map_gauss(bmap, NULL);
5305 return isl_basic_map_finalize(bmap);
5308 __isl_give isl_basic_map *isl_basic_map_range_map(
5309 __isl_take isl_basic_map *bmap)
5311 int i;
5312 isl_space *dim;
5313 isl_basic_map *range;
5314 int nparam, n_in, n_out;
5316 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5317 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5318 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5320 dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
5321 range = isl_basic_map_universe(dim);
5323 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5324 bmap = isl_basic_map_apply_range(bmap, range);
5325 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5327 for (i = 0; i < n_out; ++i)
5328 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5329 isl_dim_out, i);
5331 bmap = isl_basic_map_gauss(bmap, NULL);
5332 return isl_basic_map_finalize(bmap);
5335 int isl_map_may_be_set(__isl_keep isl_map *map)
5337 if (!map)
5338 return -1;
5339 return isl_space_may_be_set(map->dim);
5342 /* Is this map actually a set?
5343 * Users should never call this function. Outside of isl,
5344 * the type should indicate whether something is a set or a map.
5346 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5348 if (!map)
5349 return isl_bool_error;
5350 return isl_space_is_set(map->dim);
5353 struct isl_set *isl_map_range(struct isl_map *map)
5355 int i;
5356 isl_bool is_set;
5357 struct isl_set *set;
5359 is_set = isl_map_is_set(map);
5360 if (is_set < 0)
5361 goto error;
5362 if (is_set)
5363 return set_from_map(map);
5365 map = isl_map_cow(map);
5366 if (!map)
5367 goto error;
5369 set = set_from_map(map);
5370 set->dim = isl_space_range(set->dim);
5371 if (!set->dim)
5372 goto error;
5373 for (i = 0; i < map->n; ++i) {
5374 set->p[i] = isl_basic_map_range(map->p[i]);
5375 if (!set->p[i])
5376 goto error;
5378 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5379 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5380 return set;
5381 error:
5382 isl_map_free(map);
5383 return NULL;
5386 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5388 int i;
5390 map = isl_map_cow(map);
5391 if (!map)
5392 return NULL;
5394 map->dim = isl_space_domain_map(map->dim);
5395 if (!map->dim)
5396 goto error;
5397 for (i = 0; i < map->n; ++i) {
5398 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5399 if (!map->p[i])
5400 goto error;
5402 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5403 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5404 return map;
5405 error:
5406 isl_map_free(map);
5407 return NULL;
5410 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5412 int i;
5413 isl_space *range_dim;
5415 map = isl_map_cow(map);
5416 if (!map)
5417 return NULL;
5419 range_dim = isl_space_range(isl_map_get_space(map));
5420 range_dim = isl_space_from_range(range_dim);
5421 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5422 map->dim = isl_space_join(map->dim, range_dim);
5423 if (!map->dim)
5424 goto error;
5425 for (i = 0; i < map->n; ++i) {
5426 map->p[i] = isl_basic_map_range_map(map->p[i]);
5427 if (!map->p[i])
5428 goto error;
5430 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5431 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5432 return map;
5433 error:
5434 isl_map_free(map);
5435 return NULL;
5438 /* Given a wrapped map of the form A[B -> C],
5439 * return the map A[B -> C] -> B.
5441 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5443 isl_id *id;
5444 isl_map *map;
5446 if (!set)
5447 return NULL;
5448 if (!isl_set_has_tuple_id(set))
5449 return isl_map_domain_map(isl_set_unwrap(set));
5451 id = isl_set_get_tuple_id(set);
5452 map = isl_map_domain_map(isl_set_unwrap(set));
5453 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5455 return map;
5458 __isl_give isl_basic_map *isl_basic_map_from_domain(
5459 __isl_take isl_basic_set *bset)
5461 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5464 __isl_give isl_basic_map *isl_basic_map_from_range(
5465 __isl_take isl_basic_set *bset)
5467 isl_space *space;
5468 space = isl_basic_set_get_space(bset);
5469 space = isl_space_from_range(space);
5470 bset = isl_basic_set_reset_space(bset, space);
5471 return bset_to_bmap(bset);
5474 /* Create a relation with the given set as range.
5475 * The domain of the created relation is a zero-dimensional
5476 * flat anonymous space.
5478 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5480 isl_space *space;
5481 space = isl_set_get_space(set);
5482 space = isl_space_from_range(space);
5483 set = isl_set_reset_space(set, space);
5484 return set_to_map(set);
5487 /* Create a relation with the given set as domain.
5488 * The range of the created relation is a zero-dimensional
5489 * flat anonymous space.
5491 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5493 return isl_map_reverse(isl_map_from_range(set));
5496 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5497 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5499 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5502 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5503 __isl_take isl_set *range)
5505 return isl_map_apply_range(isl_map_reverse(domain), range);
5508 /* Return a newly allocated isl_map with given space and flags and
5509 * room for "n" basic maps.
5510 * Make sure that all cached information is cleared.
5512 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5513 unsigned flags)
5515 struct isl_map *map;
5517 if (!space)
5518 return NULL;
5519 if (n < 0)
5520 isl_die(space->ctx, isl_error_internal,
5521 "negative number of basic maps", goto error);
5522 map = isl_calloc(space->ctx, struct isl_map,
5523 sizeof(struct isl_map) +
5524 (n - 1) * sizeof(struct isl_basic_map *));
5525 if (!map)
5526 goto error;
5528 map->ctx = space->ctx;
5529 isl_ctx_ref(map->ctx);
5530 map->ref = 1;
5531 map->size = n;
5532 map->n = 0;
5533 map->dim = space;
5534 map->flags = flags;
5535 return map;
5536 error:
5537 isl_space_free(space);
5538 return NULL;
5541 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim)
5543 struct isl_basic_map *bmap;
5544 bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
5545 bmap = isl_basic_map_set_to_empty(bmap);
5546 return bmap;
5549 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim)
5551 struct isl_basic_set *bset;
5552 bset = isl_basic_set_alloc_space(dim, 0, 1, 0);
5553 bset = isl_basic_set_set_to_empty(bset);
5554 return bset;
5557 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim)
5559 struct isl_basic_map *bmap;
5560 bmap = isl_basic_map_alloc_space(dim, 0, 0, 0);
5561 bmap = isl_basic_map_finalize(bmap);
5562 return bmap;
5565 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim)
5567 struct isl_basic_set *bset;
5568 bset = isl_basic_set_alloc_space(dim, 0, 0, 0);
5569 bset = isl_basic_set_finalize(bset);
5570 return bset;
5573 __isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
5575 int i;
5576 unsigned total = isl_space_dim(dim, isl_dim_all);
5577 isl_basic_map *bmap;
5579 bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
5580 for (i = 0; i < total; ++i) {
5581 int k = isl_basic_map_alloc_inequality(bmap);
5582 if (k < 0)
5583 goto error;
5584 isl_seq_clr(bmap->ineq[k], 1 + total);
5585 isl_int_set_si(bmap->ineq[k][1 + i], 1);
5587 return bmap;
5588 error:
5589 isl_basic_map_free(bmap);
5590 return NULL;
5593 __isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
5595 return isl_basic_map_nat_universe(dim);
5598 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
5600 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
5603 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
5605 return isl_map_nat_universe(dim);
5608 __isl_give isl_map *isl_map_empty(__isl_take isl_space *dim)
5610 return isl_map_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5613 __isl_give isl_set *isl_set_empty(__isl_take isl_space *dim)
5615 return isl_set_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5618 __isl_give isl_map *isl_map_universe(__isl_take isl_space *dim)
5620 struct isl_map *map;
5621 if (!dim)
5622 return NULL;
5623 map = isl_map_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5624 map = isl_map_add_basic_map(map, isl_basic_map_universe(dim));
5625 return map;
5628 __isl_give isl_set *isl_set_universe(__isl_take isl_space *dim)
5630 struct isl_set *set;
5631 if (!dim)
5632 return NULL;
5633 set = isl_set_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5634 set = isl_set_add_basic_set(set, isl_basic_set_universe(dim));
5635 return set;
5638 struct isl_map *isl_map_dup(struct isl_map *map)
5640 int i;
5641 struct isl_map *dup;
5643 if (!map)
5644 return NULL;
5645 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
5646 for (i = 0; i < map->n; ++i)
5647 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
5648 return dup;
5651 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
5652 __isl_take isl_basic_map *bmap)
5654 if (!bmap || !map)
5655 goto error;
5656 if (isl_basic_map_plain_is_empty(bmap)) {
5657 isl_basic_map_free(bmap);
5658 return map;
5660 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
5661 isl_assert(map->ctx, map->n < map->size, goto error);
5662 map->p[map->n] = bmap;
5663 map->n++;
5664 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5665 return map;
5666 error:
5667 if (map)
5668 isl_map_free(map);
5669 if (bmap)
5670 isl_basic_map_free(bmap);
5671 return NULL;
5674 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
5676 int i;
5678 if (!map)
5679 return NULL;
5681 if (--map->ref > 0)
5682 return NULL;
5684 clear_caches(map);
5685 isl_ctx_deref(map->ctx);
5686 for (i = 0; i < map->n; ++i)
5687 isl_basic_map_free(map->p[i]);
5688 isl_space_free(map->dim);
5689 free(map);
5691 return NULL;
5694 static struct isl_basic_map *isl_basic_map_fix_pos_si(
5695 struct isl_basic_map *bmap, unsigned pos, int value)
5697 int j;
5699 bmap = isl_basic_map_cow(bmap);
5700 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5701 j = isl_basic_map_alloc_equality(bmap);
5702 if (j < 0)
5703 goto error;
5704 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5705 isl_int_set_si(bmap->eq[j][pos], -1);
5706 isl_int_set_si(bmap->eq[j][0], value);
5707 bmap = isl_basic_map_simplify(bmap);
5708 return isl_basic_map_finalize(bmap);
5709 error:
5710 isl_basic_map_free(bmap);
5711 return NULL;
5714 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
5715 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
5717 int j;
5719 bmap = isl_basic_map_cow(bmap);
5720 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5721 j = isl_basic_map_alloc_equality(bmap);
5722 if (j < 0)
5723 goto error;
5724 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5725 isl_int_set_si(bmap->eq[j][pos], -1);
5726 isl_int_set(bmap->eq[j][0], value);
5727 bmap = isl_basic_map_simplify(bmap);
5728 return isl_basic_map_finalize(bmap);
5729 error:
5730 isl_basic_map_free(bmap);
5731 return NULL;
5734 struct isl_basic_map *isl_basic_map_fix_si(struct isl_basic_map *bmap,
5735 enum isl_dim_type type, unsigned pos, int value)
5737 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
5738 return isl_basic_map_free(bmap);
5739 return isl_basic_map_fix_pos_si(bmap,
5740 isl_basic_map_offset(bmap, type) + pos, value);
5743 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
5744 enum isl_dim_type type, unsigned pos, isl_int value)
5746 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
5747 return isl_basic_map_free(bmap);
5748 return isl_basic_map_fix_pos(bmap,
5749 isl_basic_map_offset(bmap, type) + pos, value);
5752 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
5753 * to be equal to "v".
5755 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
5756 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5758 if (!bmap || !v)
5759 goto error;
5760 if (!isl_val_is_int(v))
5761 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
5762 "expecting integer value", goto error);
5763 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
5764 goto error;
5765 pos += isl_basic_map_offset(bmap, type);
5766 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
5767 isl_val_free(v);
5768 return bmap;
5769 error:
5770 isl_basic_map_free(bmap);
5771 isl_val_free(v);
5772 return NULL;
5775 /* Fix the value of the variable at position "pos" of type "type" of "bset"
5776 * to be equal to "v".
5778 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
5779 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5781 return isl_basic_map_fix_val(bset, type, pos, v);
5784 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
5785 enum isl_dim_type type, unsigned pos, int value)
5787 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
5788 type, pos, value));
5791 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
5792 enum isl_dim_type type, unsigned pos, isl_int value)
5794 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
5795 type, pos, value));
5798 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
5799 unsigned input, int value)
5801 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
5804 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
5805 unsigned dim, int value)
5807 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
5808 isl_dim_set, dim, value));
5811 static int remove_if_empty(__isl_keep isl_map *map, int i)
5813 int empty = isl_basic_map_plain_is_empty(map->p[i]);
5815 if (empty < 0)
5816 return -1;
5817 if (!empty)
5818 return 0;
5820 isl_basic_map_free(map->p[i]);
5821 if (i != map->n - 1) {
5822 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5823 map->p[i] = map->p[map->n - 1];
5825 map->n--;
5827 return 0;
5830 /* Perform "fn" on each basic map of "map", where we may not be holding
5831 * the only reference to "map".
5832 * In particular, "fn" should be a semantics preserving operation
5833 * that we want to apply to all copies of "map". We therefore need
5834 * to be careful not to modify "map" in a way that breaks "map"
5835 * in case anything goes wrong.
5837 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
5838 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
5840 struct isl_basic_map *bmap;
5841 int i;
5843 if (!map)
5844 return NULL;
5846 for (i = map->n - 1; i >= 0; --i) {
5847 bmap = isl_basic_map_copy(map->p[i]);
5848 bmap = fn(bmap);
5849 if (!bmap)
5850 goto error;
5851 isl_basic_map_free(map->p[i]);
5852 map->p[i] = bmap;
5853 if (remove_if_empty(map, i) < 0)
5854 goto error;
5857 return map;
5858 error:
5859 isl_map_free(map);
5860 return NULL;
5863 struct isl_map *isl_map_fix_si(struct isl_map *map,
5864 enum isl_dim_type type, unsigned pos, int value)
5866 int i;
5868 map = isl_map_cow(map);
5869 if (!map)
5870 return NULL;
5872 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5873 for (i = map->n - 1; i >= 0; --i) {
5874 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
5875 if (remove_if_empty(map, i) < 0)
5876 goto error;
5878 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5879 return map;
5880 error:
5881 isl_map_free(map);
5882 return NULL;
5885 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
5886 enum isl_dim_type type, unsigned pos, int value)
5888 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
5891 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
5892 enum isl_dim_type type, unsigned pos, isl_int value)
5894 int i;
5896 map = isl_map_cow(map);
5897 if (!map)
5898 return NULL;
5900 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5901 for (i = 0; i < map->n; ++i) {
5902 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
5903 if (!map->p[i])
5904 goto error;
5906 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5907 return map;
5908 error:
5909 isl_map_free(map);
5910 return NULL;
5913 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
5914 enum isl_dim_type type, unsigned pos, isl_int value)
5916 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
5919 /* Fix the value of the variable at position "pos" of type "type" of "map"
5920 * to be equal to "v".
5922 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
5923 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5925 int i;
5927 map = isl_map_cow(map);
5928 if (!map || !v)
5929 goto error;
5931 if (!isl_val_is_int(v))
5932 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5933 "expecting integer value", goto error);
5934 if (pos >= isl_map_dim(map, type))
5935 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5936 "index out of bounds", goto error);
5937 for (i = map->n - 1; i >= 0; --i) {
5938 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
5939 isl_val_copy(v));
5940 if (remove_if_empty(map, i) < 0)
5941 goto error;
5943 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5944 isl_val_free(v);
5945 return map;
5946 error:
5947 isl_map_free(map);
5948 isl_val_free(v);
5949 return NULL;
5952 /* Fix the value of the variable at position "pos" of type "type" of "set"
5953 * to be equal to "v".
5955 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
5956 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5958 return isl_map_fix_val(set, type, pos, v);
5961 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
5962 unsigned input, int value)
5964 return isl_map_fix_si(map, isl_dim_in, input, value);
5967 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
5969 return set_from_map(isl_map_fix_si(set_to_map(set),
5970 isl_dim_set, dim, value));
5973 static __isl_give isl_basic_map *basic_map_bound_si(
5974 __isl_take isl_basic_map *bmap,
5975 enum isl_dim_type type, unsigned pos, int value, int upper)
5977 int j;
5979 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
5980 return isl_basic_map_free(bmap);
5981 pos += isl_basic_map_offset(bmap, type);
5982 bmap = isl_basic_map_cow(bmap);
5983 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
5984 j = isl_basic_map_alloc_inequality(bmap);
5985 if (j < 0)
5986 goto error;
5987 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
5988 if (upper) {
5989 isl_int_set_si(bmap->ineq[j][pos], -1);
5990 isl_int_set_si(bmap->ineq[j][0], value);
5991 } else {
5992 isl_int_set_si(bmap->ineq[j][pos], 1);
5993 isl_int_set_si(bmap->ineq[j][0], -value);
5995 bmap = isl_basic_map_simplify(bmap);
5996 return isl_basic_map_finalize(bmap);
5997 error:
5998 isl_basic_map_free(bmap);
5999 return NULL;
6002 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6003 __isl_take isl_basic_map *bmap,
6004 enum isl_dim_type type, unsigned pos, int value)
6006 return basic_map_bound_si(bmap, type, pos, value, 0);
6009 /* Constrain the values of the given dimension to be no greater than "value".
6011 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6012 __isl_take isl_basic_map *bmap,
6013 enum isl_dim_type type, unsigned pos, int value)
6015 return basic_map_bound_si(bmap, type, pos, value, 1);
6018 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6019 enum isl_dim_type type, unsigned pos, int value, int upper)
6021 int i;
6023 map = isl_map_cow(map);
6024 if (!map)
6025 return NULL;
6027 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6028 for (i = 0; i < map->n; ++i) {
6029 map->p[i] = basic_map_bound_si(map->p[i],
6030 type, pos, value, upper);
6031 if (!map->p[i])
6032 goto error;
6034 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
6035 return map;
6036 error:
6037 isl_map_free(map);
6038 return NULL;
6041 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6042 enum isl_dim_type type, unsigned pos, int value)
6044 return map_bound_si(map, type, pos, value, 0);
6047 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6048 enum isl_dim_type type, unsigned pos, int value)
6050 return map_bound_si(map, type, pos, value, 1);
6053 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6054 enum isl_dim_type type, unsigned pos, int value)
6056 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6057 type, pos, value));
6060 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6061 enum isl_dim_type type, unsigned pos, int value)
6063 return isl_map_upper_bound_si(set, type, pos, value);
6066 /* Bound the given variable of "bmap" from below (or above is "upper"
6067 * is set) to "value".
6069 static __isl_give isl_basic_map *basic_map_bound(
6070 __isl_take isl_basic_map *bmap,
6071 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6073 int j;
6075 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6076 return isl_basic_map_free(bmap);
6077 pos += isl_basic_map_offset(bmap, type);
6078 bmap = isl_basic_map_cow(bmap);
6079 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6080 j = isl_basic_map_alloc_inequality(bmap);
6081 if (j < 0)
6082 goto error;
6083 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6084 if (upper) {
6085 isl_int_set_si(bmap->ineq[j][pos], -1);
6086 isl_int_set(bmap->ineq[j][0], value);
6087 } else {
6088 isl_int_set_si(bmap->ineq[j][pos], 1);
6089 isl_int_neg(bmap->ineq[j][0], value);
6091 bmap = isl_basic_map_simplify(bmap);
6092 return isl_basic_map_finalize(bmap);
6093 error:
6094 isl_basic_map_free(bmap);
6095 return NULL;
6098 /* Bound the given variable of "map" from below (or above is "upper"
6099 * is set) to "value".
6101 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6102 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6104 int i;
6106 map = isl_map_cow(map);
6107 if (!map)
6108 return NULL;
6110 if (pos >= isl_map_dim(map, type))
6111 isl_die(map->ctx, isl_error_invalid,
6112 "index out of bounds", goto error);
6113 for (i = map->n - 1; i >= 0; --i) {
6114 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6115 if (remove_if_empty(map, i) < 0)
6116 goto error;
6118 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
6119 return map;
6120 error:
6121 isl_map_free(map);
6122 return NULL;
6125 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6126 enum isl_dim_type type, unsigned pos, isl_int value)
6128 return map_bound(map, type, pos, value, 0);
6131 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6132 enum isl_dim_type type, unsigned pos, isl_int value)
6134 return map_bound(map, type, pos, value, 1);
6137 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6138 enum isl_dim_type type, unsigned pos, isl_int value)
6140 return isl_map_lower_bound(set, type, pos, value);
6143 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6144 enum isl_dim_type type, unsigned pos, isl_int value)
6146 return isl_map_upper_bound(set, type, pos, value);
6149 /* Force the values of the variable at position "pos" of type "type" of "set"
6150 * to be no smaller than "value".
6152 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6153 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6155 if (!value)
6156 goto error;
6157 if (!isl_val_is_int(value))
6158 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6159 "expecting integer value", goto error);
6160 set = isl_set_lower_bound(set, type, pos, value->n);
6161 isl_val_free(value);
6162 return set;
6163 error:
6164 isl_val_free(value);
6165 isl_set_free(set);
6166 return NULL;
6169 /* Force the values of the variable at position "pos" of type "type" of "set"
6170 * to be no greater than "value".
6172 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6173 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6175 if (!value)
6176 goto error;
6177 if (!isl_val_is_int(value))
6178 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6179 "expecting integer value", goto error);
6180 set = isl_set_upper_bound(set, type, pos, value->n);
6181 isl_val_free(value);
6182 return set;
6183 error:
6184 isl_val_free(value);
6185 isl_set_free(set);
6186 return NULL;
6189 struct isl_map *isl_map_reverse(struct isl_map *map)
6191 int i;
6193 map = isl_map_cow(map);
6194 if (!map)
6195 return NULL;
6197 map->dim = isl_space_reverse(map->dim);
6198 if (!map->dim)
6199 goto error;
6200 for (i = 0; i < map->n; ++i) {
6201 map->p[i] = isl_basic_map_reverse(map->p[i]);
6202 if (!map->p[i])
6203 goto error;
6205 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
6206 return map;
6207 error:
6208 isl_map_free(map);
6209 return NULL;
6212 #undef TYPE
6213 #define TYPE isl_pw_multi_aff
6214 #undef SUFFIX
6215 #define SUFFIX _pw_multi_aff
6216 #undef EMPTY
6217 #define EMPTY isl_pw_multi_aff_empty
6218 #undef ADD
6219 #define ADD isl_pw_multi_aff_union_add
6220 #include "isl_map_lexopt_templ.c"
6222 /* Given a map "map", compute the lexicographically minimal
6223 * (or maximal) image element for each domain element in dom,
6224 * in the form of an isl_pw_multi_aff.
6225 * If "empty" is not NULL, then set *empty to those elements in dom that
6226 * do not have an image element.
6227 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6228 * should be computed over the domain of "map". "empty" is also NULL
6229 * in this case.
6231 * We first compute the lexicographically minimal or maximal element
6232 * in the first basic map. This results in a partial solution "res"
6233 * and a subset "todo" of dom that still need to be handled.
6234 * We then consider each of the remaining maps in "map" and successively
6235 * update both "res" and "todo".
6236 * If "empty" is NULL, then the todo sets are not needed and therefore
6237 * also not computed.
6239 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6240 __isl_take isl_map *map, __isl_take isl_set *dom,
6241 __isl_give isl_set **empty, unsigned flags)
6243 int i;
6244 int full;
6245 isl_pw_multi_aff *res;
6246 isl_set *todo;
6248 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6249 if (!map || (!full && !dom))
6250 goto error;
6252 if (isl_map_plain_is_empty(map)) {
6253 if (empty)
6254 *empty = dom;
6255 else
6256 isl_set_free(dom);
6257 return isl_pw_multi_aff_from_map(map);
6260 res = basic_map_partial_lexopt_pw_multi_aff(
6261 isl_basic_map_copy(map->p[0]),
6262 isl_set_copy(dom), empty, flags);
6264 if (empty)
6265 todo = *empty;
6266 for (i = 1; i < map->n; ++i) {
6267 isl_pw_multi_aff *res_i;
6269 res_i = basic_map_partial_lexopt_pw_multi_aff(
6270 isl_basic_map_copy(map->p[i]),
6271 isl_set_copy(dom), empty, flags);
6273 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6274 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6275 else
6276 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6278 if (empty)
6279 todo = isl_set_intersect(todo, *empty);
6282 isl_set_free(dom);
6283 isl_map_free(map);
6285 if (empty)
6286 *empty = todo;
6288 return res;
6289 error:
6290 if (empty)
6291 *empty = NULL;
6292 isl_set_free(dom);
6293 isl_map_free(map);
6294 return NULL;
6297 #undef TYPE
6298 #define TYPE isl_map
6299 #undef SUFFIX
6300 #define SUFFIX
6301 #undef EMPTY
6302 #define EMPTY isl_map_empty
6303 #undef ADD
6304 #define ADD isl_map_union_disjoint
6305 #include "isl_map_lexopt_templ.c"
6307 /* Given a map "map", compute the lexicographically minimal
6308 * (or maximal) image element for each domain element in "dom",
6309 * in the form of an isl_map.
6310 * If "empty" is not NULL, then set *empty to those elements in "dom" that
6311 * do not have an image element.
6312 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6313 * should be computed over the domain of "map". "empty" is also NULL
6314 * in this case.
6316 * If the input consists of more than one disjunct, then first
6317 * compute the desired result in the form of an isl_pw_multi_aff and
6318 * then convert that into an isl_map.
6320 * This function used to have an explicit implementation in terms
6321 * of isl_maps, but it would continually intersect the domains of
6322 * partial results with the complement of the domain of the next
6323 * partial solution, potentially leading to an explosion in the number
6324 * of disjuncts if there are several disjuncts in the input.
6325 * An even earlier implementation of this function would look for
6326 * better results in the domain of the partial result and for extra
6327 * results in the complement of this domain, which would lead to
6328 * even more splintering.
6330 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6331 __isl_take isl_map *map, __isl_take isl_set *dom,
6332 __isl_give isl_set **empty, unsigned flags)
6334 int full;
6335 struct isl_map *res;
6336 isl_pw_multi_aff *pma;
6338 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6339 if (!map || (!full && !dom))
6340 goto error;
6342 if (isl_map_plain_is_empty(map)) {
6343 if (empty)
6344 *empty = dom;
6345 else
6346 isl_set_free(dom);
6347 return map;
6350 if (map->n == 1) {
6351 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6352 dom, empty, flags);
6353 isl_map_free(map);
6354 return res;
6357 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6358 flags);
6359 return isl_map_from_pw_multi_aff(pma);
6360 error:
6361 if (empty)
6362 *empty = NULL;
6363 isl_set_free(dom);
6364 isl_map_free(map);
6365 return NULL;
6368 __isl_give isl_map *isl_map_partial_lexmax(
6369 __isl_take isl_map *map, __isl_take isl_set *dom,
6370 __isl_give isl_set **empty)
6372 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6375 __isl_give isl_map *isl_map_partial_lexmin(
6376 __isl_take isl_map *map, __isl_take isl_set *dom,
6377 __isl_give isl_set **empty)
6379 return isl_map_partial_lexopt(map, dom, empty, 0);
6382 __isl_give isl_set *isl_set_partial_lexmin(
6383 __isl_take isl_set *set, __isl_take isl_set *dom,
6384 __isl_give isl_set **empty)
6386 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6387 dom, empty));
6390 __isl_give isl_set *isl_set_partial_lexmax(
6391 __isl_take isl_set *set, __isl_take isl_set *dom,
6392 __isl_give isl_set **empty)
6394 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6395 dom, empty));
6398 /* Compute the lexicographic minimum (or maximum if "flags" includes
6399 * ISL_OPT_MAX) of "bset" over its parametric domain.
6401 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6402 unsigned flags)
6404 return isl_basic_map_lexopt(bset, flags);
6407 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6409 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6412 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6414 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6417 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6419 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6422 /* Compute the lexicographic minimum of "bset" over its parametric domain
6423 * for the purpose of quantifier elimination.
6424 * That is, find an explicit representation for all the existentially
6425 * quantified variables in "bset" by computing their lexicographic
6426 * minimum.
6428 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6429 __isl_take isl_basic_set *bset)
6431 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6434 /* Extract the first and only affine expression from list
6435 * and then add it to *pwaff with the given dom.
6436 * This domain is known to be disjoint from other domains
6437 * because of the way isl_basic_map_foreach_lexmax works.
6439 static isl_stat update_dim_opt(__isl_take isl_basic_set *dom,
6440 __isl_take isl_aff_list *list, void *user)
6442 isl_ctx *ctx = isl_basic_set_get_ctx(dom);
6443 isl_aff *aff;
6444 isl_pw_aff **pwaff = user;
6445 isl_pw_aff *pwaff_i;
6447 if (!list)
6448 goto error;
6449 if (isl_aff_list_n_aff(list) != 1)
6450 isl_die(ctx, isl_error_internal,
6451 "expecting single element list", goto error);
6453 aff = isl_aff_list_get_aff(list, 0);
6454 pwaff_i = isl_pw_aff_alloc(isl_set_from_basic_set(dom), aff);
6456 *pwaff = isl_pw_aff_add_disjoint(*pwaff, pwaff_i);
6458 isl_aff_list_free(list);
6460 return isl_stat_ok;
6461 error:
6462 isl_basic_set_free(dom);
6463 isl_aff_list_free(list);
6464 return isl_stat_error;
6467 /* Given a basic map with one output dimension, compute the minimum or
6468 * maximum of that dimension as an isl_pw_aff.
6470 * The isl_pw_aff is constructed by having isl_basic_map_foreach_lexopt
6471 * call update_dim_opt on each leaf of the result.
6473 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6474 int max)
6476 isl_space *dim = isl_basic_map_get_space(bmap);
6477 isl_pw_aff *pwaff;
6478 isl_stat r;
6480 dim = isl_space_from_domain(isl_space_domain(dim));
6481 dim = isl_space_add_dims(dim, isl_dim_out, 1);
6482 pwaff = isl_pw_aff_empty(dim);
6484 r = isl_basic_map_foreach_lexopt(bmap, max, &update_dim_opt, &pwaff);
6485 if (r < 0)
6486 return isl_pw_aff_free(pwaff);
6488 return pwaff;
6491 /* Compute the minimum or maximum of the given output dimension
6492 * as a function of the parameters and the input dimensions,
6493 * but independently of the other output dimensions.
6495 * We first project out the other output dimension and then compute
6496 * the "lexicographic" maximum in each basic map, combining the results
6497 * using isl_pw_aff_union_max.
6499 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6500 int max)
6502 int i;
6503 isl_pw_aff *pwaff;
6504 unsigned n_out;
6506 n_out = isl_map_dim(map, isl_dim_out);
6507 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6508 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6509 if (!map)
6510 return NULL;
6512 if (map->n == 0) {
6513 isl_space *dim = isl_map_get_space(map);
6514 isl_map_free(map);
6515 return isl_pw_aff_empty(dim);
6518 pwaff = basic_map_dim_opt(map->p[0], max);
6519 for (i = 1; i < map->n; ++i) {
6520 isl_pw_aff *pwaff_i;
6522 pwaff_i = basic_map_dim_opt(map->p[i], max);
6523 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6526 isl_map_free(map);
6528 return pwaff;
6531 /* Compute the minimum of the given output dimension as a function of the
6532 * parameters and input dimensions, but independently of
6533 * the other output dimensions.
6535 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
6537 return map_dim_opt(map, pos, 0);
6540 /* Compute the maximum of the given output dimension as a function of the
6541 * parameters and input dimensions, but independently of
6542 * the other output dimensions.
6544 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6546 return map_dim_opt(map, pos, 1);
6549 /* Compute the minimum or maximum of the given set dimension
6550 * as a function of the parameters,
6551 * but independently of the other set dimensions.
6553 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
6554 int max)
6556 return map_dim_opt(set, pos, max);
6559 /* Compute the maximum of the given set dimension as a function of the
6560 * parameters, but independently of the other set dimensions.
6562 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
6564 return set_dim_opt(set, pos, 1);
6567 /* Compute the minimum of the given set dimension as a function of the
6568 * parameters, but independently of the other set dimensions.
6570 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
6572 return set_dim_opt(set, pos, 0);
6575 /* Apply a preimage specified by "mat" on the parameters of "bset".
6576 * bset is assumed to have only parameters and divs.
6578 static struct isl_basic_set *basic_set_parameter_preimage(
6579 struct isl_basic_set *bset, struct isl_mat *mat)
6581 unsigned nparam;
6583 if (!bset || !mat)
6584 goto error;
6586 bset->dim = isl_space_cow(bset->dim);
6587 if (!bset->dim)
6588 goto error;
6590 nparam = isl_basic_set_dim(bset, isl_dim_param);
6592 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
6594 bset->dim->nparam = 0;
6595 bset->dim->n_out = nparam;
6596 bset = isl_basic_set_preimage(bset, mat);
6597 if (bset) {
6598 bset->dim->nparam = bset->dim->n_out;
6599 bset->dim->n_out = 0;
6601 return bset;
6602 error:
6603 isl_mat_free(mat);
6604 isl_basic_set_free(bset);
6605 return NULL;
6608 /* Apply a preimage specified by "mat" on the parameters of "set".
6609 * set is assumed to have only parameters and divs.
6611 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
6612 __isl_take isl_mat *mat)
6614 isl_space *space;
6615 unsigned nparam;
6617 if (!set || !mat)
6618 goto error;
6620 nparam = isl_set_dim(set, isl_dim_param);
6622 if (mat->n_row != 1 + nparam)
6623 isl_die(isl_set_get_ctx(set), isl_error_internal,
6624 "unexpected number of rows", goto error);
6626 space = isl_set_get_space(set);
6627 space = isl_space_move_dims(space, isl_dim_set, 0,
6628 isl_dim_param, 0, nparam);
6629 set = isl_set_reset_space(set, space);
6630 set = isl_set_preimage(set, mat);
6631 nparam = isl_set_dim(set, isl_dim_out);
6632 space = isl_set_get_space(set);
6633 space = isl_space_move_dims(space, isl_dim_param, 0,
6634 isl_dim_out, 0, nparam);
6635 set = isl_set_reset_space(set, space);
6636 return set;
6637 error:
6638 isl_mat_free(mat);
6639 isl_set_free(set);
6640 return NULL;
6643 /* Intersect the basic set "bset" with the affine space specified by the
6644 * equalities in "eq".
6646 static struct isl_basic_set *basic_set_append_equalities(
6647 struct isl_basic_set *bset, struct isl_mat *eq)
6649 int i, k;
6650 unsigned len;
6652 if (!bset || !eq)
6653 goto error;
6655 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
6656 eq->n_row, 0);
6657 if (!bset)
6658 goto error;
6660 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
6661 for (i = 0; i < eq->n_row; ++i) {
6662 k = isl_basic_set_alloc_equality(bset);
6663 if (k < 0)
6664 goto error;
6665 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
6666 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
6668 isl_mat_free(eq);
6670 bset = isl_basic_set_gauss(bset, NULL);
6671 bset = isl_basic_set_finalize(bset);
6673 return bset;
6674 error:
6675 isl_mat_free(eq);
6676 isl_basic_set_free(bset);
6677 return NULL;
6680 /* Intersect the set "set" with the affine space specified by the
6681 * equalities in "eq".
6683 static struct isl_set *set_append_equalities(struct isl_set *set,
6684 struct isl_mat *eq)
6686 int i;
6688 if (!set || !eq)
6689 goto error;
6691 for (i = 0; i < set->n; ++i) {
6692 set->p[i] = basic_set_append_equalities(set->p[i],
6693 isl_mat_copy(eq));
6694 if (!set->p[i])
6695 goto error;
6697 isl_mat_free(eq);
6698 return set;
6699 error:
6700 isl_mat_free(eq);
6701 isl_set_free(set);
6702 return NULL;
6705 /* Given a basic set "bset" that only involves parameters and existentially
6706 * quantified variables, return the index of the first equality
6707 * that only involves parameters. If there is no such equality then
6708 * return bset->n_eq.
6710 * This function assumes that isl_basic_set_gauss has been called on "bset".
6712 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
6714 int i, j;
6715 unsigned nparam, n_div;
6717 if (!bset)
6718 return -1;
6720 nparam = isl_basic_set_dim(bset, isl_dim_param);
6721 n_div = isl_basic_set_dim(bset, isl_dim_div);
6723 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
6724 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
6725 ++i;
6728 return i;
6731 /* Compute an explicit representation for the existentially quantified
6732 * variables in "bset" by computing the "minimal value" of the set
6733 * variables. Since there are no set variables, the computation of
6734 * the minimal value essentially computes an explicit representation
6735 * of the non-empty part(s) of "bset".
6737 * The input only involves parameters and existentially quantified variables.
6738 * All equalities among parameters have been removed.
6740 * Since the existentially quantified variables in the result are in general
6741 * going to be different from those in the input, we first replace
6742 * them by the minimal number of variables based on their equalities.
6743 * This should simplify the parametric integer programming.
6745 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
6747 isl_morph *morph1, *morph2;
6748 isl_set *set;
6749 unsigned n;
6751 if (!bset)
6752 return NULL;
6753 if (bset->n_eq == 0)
6754 return isl_basic_set_lexmin_compute_divs(bset);
6756 morph1 = isl_basic_set_parameter_compression(bset);
6757 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
6758 bset = isl_basic_set_lift(bset);
6759 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
6760 bset = isl_morph_basic_set(morph2, bset);
6761 n = isl_basic_set_dim(bset, isl_dim_set);
6762 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
6764 set = isl_basic_set_lexmin_compute_divs(bset);
6766 set = isl_morph_set(isl_morph_inverse(morph1), set);
6768 return set;
6771 /* Project the given basic set onto its parameter domain, possibly introducing
6772 * new, explicit, existential variables in the constraints.
6773 * The input has parameters and (possibly implicit) existential variables.
6774 * The output has the same parameters, but only
6775 * explicit existentially quantified variables.
6777 * The actual projection is performed by pip, but pip doesn't seem
6778 * to like equalities very much, so we first remove the equalities
6779 * among the parameters by performing a variable compression on
6780 * the parameters. Afterward, an inverse transformation is performed
6781 * and the equalities among the parameters are inserted back in.
6783 * The variable compression on the parameters may uncover additional
6784 * equalities that were only implicit before. We therefore check
6785 * if there are any new parameter equalities in the result and
6786 * if so recurse. The removal of parameter equalities is required
6787 * for the parameter compression performed by base_compute_divs.
6789 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
6791 int i;
6792 struct isl_mat *eq;
6793 struct isl_mat *T, *T2;
6794 struct isl_set *set;
6795 unsigned nparam;
6797 bset = isl_basic_set_cow(bset);
6798 if (!bset)
6799 return NULL;
6801 if (bset->n_eq == 0)
6802 return base_compute_divs(bset);
6804 bset = isl_basic_set_gauss(bset, NULL);
6805 if (!bset)
6806 return NULL;
6807 if (isl_basic_set_plain_is_empty(bset))
6808 return isl_set_from_basic_set(bset);
6810 i = first_parameter_equality(bset);
6811 if (i == bset->n_eq)
6812 return base_compute_divs(bset);
6814 nparam = isl_basic_set_dim(bset, isl_dim_param);
6815 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
6816 0, 1 + nparam);
6817 eq = isl_mat_cow(eq);
6818 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
6819 if (T && T->n_col == 0) {
6820 isl_mat_free(T);
6821 isl_mat_free(T2);
6822 isl_mat_free(eq);
6823 bset = isl_basic_set_set_to_empty(bset);
6824 return isl_set_from_basic_set(bset);
6826 bset = basic_set_parameter_preimage(bset, T);
6828 i = first_parameter_equality(bset);
6829 if (!bset)
6830 set = NULL;
6831 else if (i == bset->n_eq)
6832 set = base_compute_divs(bset);
6833 else
6834 set = parameter_compute_divs(bset);
6835 set = set_parameter_preimage(set, T2);
6836 set = set_append_equalities(set, eq);
6837 return set;
6840 /* Insert the divs from "ls" before those of "bmap".
6842 * The number of columns is not changed, which means that the last
6843 * dimensions of "bmap" are being reintepreted as the divs from "ls".
6844 * The caller is responsible for removing the same number of dimensions
6845 * from the space of "bmap".
6847 static __isl_give isl_basic_map *insert_divs_from_local_space(
6848 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
6850 int i;
6851 int n_div;
6852 int old_n_div;
6854 n_div = isl_local_space_dim(ls, isl_dim_div);
6855 if (n_div == 0)
6856 return bmap;
6858 old_n_div = bmap->n_div;
6859 bmap = insert_div_rows(bmap, n_div);
6860 if (!bmap)
6861 return NULL;
6863 for (i = 0; i < n_div; ++i) {
6864 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
6865 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
6868 return bmap;
6871 /* Replace the space of "bmap" by the space and divs of "ls".
6873 * If "ls" has any divs, then we simplify the result since we may
6874 * have discovered some additional equalities that could simplify
6875 * the div expressions.
6877 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
6878 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
6880 int n_div;
6882 bmap = isl_basic_map_cow(bmap);
6883 if (!bmap || !ls)
6884 goto error;
6886 n_div = isl_local_space_dim(ls, isl_dim_div);
6887 bmap = insert_divs_from_local_space(bmap, ls);
6888 if (!bmap)
6889 goto error;
6891 isl_space_free(bmap->dim);
6892 bmap->dim = isl_local_space_get_space(ls);
6893 if (!bmap->dim)
6894 goto error;
6896 isl_local_space_free(ls);
6897 if (n_div > 0)
6898 bmap = isl_basic_map_simplify(bmap);
6899 bmap = isl_basic_map_finalize(bmap);
6900 return bmap;
6901 error:
6902 isl_basic_map_free(bmap);
6903 isl_local_space_free(ls);
6904 return NULL;
6907 /* Replace the space of "map" by the space and divs of "ls".
6909 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
6910 __isl_take isl_local_space *ls)
6912 int i;
6914 map = isl_map_cow(map);
6915 if (!map || !ls)
6916 goto error;
6918 for (i = 0; i < map->n; ++i) {
6919 map->p[i] = basic_replace_space_by_local_space(map->p[i],
6920 isl_local_space_copy(ls));
6921 if (!map->p[i])
6922 goto error;
6924 isl_space_free(map->dim);
6925 map->dim = isl_local_space_get_space(ls);
6926 if (!map->dim)
6927 goto error;
6929 isl_local_space_free(ls);
6930 return map;
6931 error:
6932 isl_local_space_free(ls);
6933 isl_map_free(map);
6934 return NULL;
6937 /* Compute an explicit representation for the existentially
6938 * quantified variables for which do not know any explicit representation yet.
6940 * We first sort the existentially quantified variables so that the
6941 * existentially quantified variables for which we already have an explicit
6942 * representation are placed before those for which we do not.
6943 * The input dimensions, the output dimensions and the existentially
6944 * quantified variables for which we already have an explicit
6945 * representation are then turned into parameters.
6946 * compute_divs returns a map with the same parameters and
6947 * no input or output dimensions and the dimension specification
6948 * is reset to that of the input, including the existentially quantified
6949 * variables for which we already had an explicit representation.
6951 static struct isl_map *compute_divs(struct isl_basic_map *bmap)
6953 struct isl_basic_set *bset;
6954 struct isl_set *set;
6955 struct isl_map *map;
6956 isl_space *dim;
6957 isl_local_space *ls;
6958 unsigned nparam;
6959 unsigned n_in;
6960 unsigned n_out;
6961 int n_known;
6962 int i;
6964 bmap = isl_basic_map_sort_divs(bmap);
6965 bmap = isl_basic_map_cow(bmap);
6966 if (!bmap)
6967 return NULL;
6969 n_known = isl_basic_map_first_unknown_div(bmap);
6970 if (n_known < 0)
6971 return isl_map_from_basic_map(isl_basic_map_free(bmap));
6973 nparam = isl_basic_map_dim(bmap, isl_dim_param);
6974 n_in = isl_basic_map_dim(bmap, isl_dim_in);
6975 n_out = isl_basic_map_dim(bmap, isl_dim_out);
6976 dim = isl_space_set_alloc(bmap->ctx,
6977 nparam + n_in + n_out + n_known, 0);
6978 if (!dim)
6979 goto error;
6981 ls = isl_basic_map_get_local_space(bmap);
6982 ls = isl_local_space_drop_dims(ls, isl_dim_div,
6983 n_known, bmap->n_div - n_known);
6984 if (n_known > 0) {
6985 for (i = n_known; i < bmap->n_div; ++i)
6986 swap_div(bmap, i - n_known, i);
6987 bmap->n_div -= n_known;
6988 bmap->extra -= n_known;
6990 bmap = isl_basic_map_reset_space(bmap, dim);
6991 bset = bset_from_bmap(bmap);
6993 set = parameter_compute_divs(bset);
6994 map = set_to_map(set);
6995 map = replace_space_by_local_space(map, ls);
6997 return map;
6998 error:
6999 isl_basic_map_free(bmap);
7000 return NULL;
7003 /* Remove the explicit representation of local variable "div",
7004 * if there is any.
7006 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7007 __isl_take isl_basic_map *bmap, int div)
7009 isl_bool unknown;
7011 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7012 if (unknown < 0)
7013 return isl_basic_map_free(bmap);
7014 if (unknown)
7015 return bmap;
7017 bmap = isl_basic_map_cow(bmap);
7018 if (!bmap)
7019 return NULL;
7020 isl_int_set_si(bmap->div[div][0], 0);
7021 return bmap;
7024 /* Is local variable "div" of "bmap" marked as not having an explicit
7025 * representation?
7026 * Note that even if "div" is not marked in this way and therefore
7027 * has an explicit representation, this representation may still
7028 * depend (indirectly) on other local variables that do not
7029 * have an explicit representation.
7031 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7032 int div)
7034 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7035 return isl_bool_error;
7036 return isl_int_is_zero(bmap->div[div][0]);
7039 /* Return the position of the first local variable that does not
7040 * have an explicit representation.
7041 * Return the total number of local variables if they all have
7042 * an explicit representation.
7043 * Return -1 on error.
7045 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7047 int i;
7049 if (!bmap)
7050 return -1;
7052 for (i = 0; i < bmap->n_div; ++i) {
7053 if (!isl_basic_map_div_is_known(bmap, i))
7054 return i;
7056 return bmap->n_div;
7059 /* Return the position of the first local variable that does not
7060 * have an explicit representation.
7061 * Return the total number of local variables if they all have
7062 * an explicit representation.
7063 * Return -1 on error.
7065 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7067 return isl_basic_map_first_unknown_div(bset);
7070 /* Does "bmap" have an explicit representation for all local variables?
7072 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7074 int first, n;
7076 n = isl_basic_map_dim(bmap, isl_dim_div);
7077 first = isl_basic_map_first_unknown_div(bmap);
7078 if (first < 0)
7079 return isl_bool_error;
7080 return first == n;
7083 /* Do all basic maps in "map" have an explicit representation
7084 * for all local variables?
7086 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7088 int i;
7090 if (!map)
7091 return isl_bool_error;
7093 for (i = 0; i < map->n; ++i) {
7094 int known = isl_basic_map_divs_known(map->p[i]);
7095 if (known <= 0)
7096 return known;
7099 return isl_bool_true;
7102 /* If bmap contains any unknown divs, then compute explicit
7103 * expressions for them. However, this computation may be
7104 * quite expensive, so first try to remove divs that aren't
7105 * strictly needed.
7107 struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap)
7109 int known;
7110 struct isl_map *map;
7112 known = isl_basic_map_divs_known(bmap);
7113 if (known < 0)
7114 goto error;
7115 if (known)
7116 return isl_map_from_basic_map(bmap);
7118 bmap = isl_basic_map_drop_redundant_divs(bmap);
7120 known = isl_basic_map_divs_known(bmap);
7121 if (known < 0)
7122 goto error;
7123 if (known)
7124 return isl_map_from_basic_map(bmap);
7126 map = compute_divs(bmap);
7127 return map;
7128 error:
7129 isl_basic_map_free(bmap);
7130 return NULL;
7133 struct isl_map *isl_map_compute_divs(struct isl_map *map)
7135 int i;
7136 int known;
7137 struct isl_map *res;
7139 if (!map)
7140 return NULL;
7141 if (map->n == 0)
7142 return map;
7144 known = isl_map_divs_known(map);
7145 if (known < 0) {
7146 isl_map_free(map);
7147 return NULL;
7149 if (known)
7150 return map;
7152 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7153 for (i = 1 ; i < map->n; ++i) {
7154 struct isl_map *r2;
7155 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7156 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7157 res = isl_map_union_disjoint(res, r2);
7158 else
7159 res = isl_map_union(res, r2);
7161 isl_map_free(map);
7163 return res;
7166 struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset)
7168 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7171 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7173 return set_from_map(isl_map_compute_divs(set_to_map(set)));
7176 struct isl_set *isl_map_domain(struct isl_map *map)
7178 int i;
7179 struct isl_set *set;
7181 if (!map)
7182 goto error;
7184 map = isl_map_cow(map);
7185 if (!map)
7186 return NULL;
7188 set = set_from_map(map);
7189 set->dim = isl_space_domain(set->dim);
7190 if (!set->dim)
7191 goto error;
7192 for (i = 0; i < map->n; ++i) {
7193 set->p[i] = isl_basic_map_domain(map->p[i]);
7194 if (!set->p[i])
7195 goto error;
7197 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7198 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7199 return set;
7200 error:
7201 isl_map_free(map);
7202 return NULL;
7205 /* Return the union of "map1" and "map2", where we assume for now that
7206 * "map1" and "map2" are disjoint. Note that the basic maps inside
7207 * "map1" or "map2" may not be disjoint from each other.
7208 * Also note that this function is also called from isl_map_union,
7209 * which takes care of handling the situation where "map1" and "map2"
7210 * may not be disjoint.
7212 * If one of the inputs is empty, we can simply return the other input.
7213 * Similarly, if one of the inputs is universal, then it is equal to the union.
7215 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7216 __isl_take isl_map *map2)
7218 int i;
7219 unsigned flags = 0;
7220 struct isl_map *map = NULL;
7221 int is_universe;
7223 if (!map1 || !map2)
7224 goto error;
7226 if (!isl_space_is_equal(map1->dim, map2->dim))
7227 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7228 "spaces don't match", goto error);
7230 if (map1->n == 0) {
7231 isl_map_free(map1);
7232 return map2;
7234 if (map2->n == 0) {
7235 isl_map_free(map2);
7236 return map1;
7239 is_universe = isl_map_plain_is_universe(map1);
7240 if (is_universe < 0)
7241 goto error;
7242 if (is_universe) {
7243 isl_map_free(map2);
7244 return map1;
7247 is_universe = isl_map_plain_is_universe(map2);
7248 if (is_universe < 0)
7249 goto error;
7250 if (is_universe) {
7251 isl_map_free(map1);
7252 return map2;
7255 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7256 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7257 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7259 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7260 map1->n + map2->n, flags);
7261 if (!map)
7262 goto error;
7263 for (i = 0; i < map1->n; ++i) {
7264 map = isl_map_add_basic_map(map,
7265 isl_basic_map_copy(map1->p[i]));
7266 if (!map)
7267 goto error;
7269 for (i = 0; i < map2->n; ++i) {
7270 map = isl_map_add_basic_map(map,
7271 isl_basic_map_copy(map2->p[i]));
7272 if (!map)
7273 goto error;
7275 isl_map_free(map1);
7276 isl_map_free(map2);
7277 return map;
7278 error:
7279 isl_map_free(map);
7280 isl_map_free(map1);
7281 isl_map_free(map2);
7282 return NULL;
7285 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7286 * guaranteed to be disjoint by the caller.
7288 * Note that this functions is called from within isl_map_make_disjoint,
7289 * so we have to be careful not to touch the constraints of the inputs
7290 * in any way.
7292 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7293 __isl_take isl_map *map2)
7295 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7298 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7299 * not be disjoint. The parameters are assumed to have been aligned.
7301 * We currently simply call map_union_disjoint, the internal operation
7302 * of which does not really depend on the inputs being disjoint.
7303 * If the result contains more than one basic map, then we clear
7304 * the disjoint flag since the result may contain basic maps from
7305 * both inputs and these are not guaranteed to be disjoint.
7307 * As a special case, if "map1" and "map2" are obviously equal,
7308 * then we simply return "map1".
7310 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7311 __isl_take isl_map *map2)
7313 int equal;
7315 if (!map1 || !map2)
7316 goto error;
7318 equal = isl_map_plain_is_equal(map1, map2);
7319 if (equal < 0)
7320 goto error;
7321 if (equal) {
7322 isl_map_free(map2);
7323 return map1;
7326 map1 = map_union_disjoint(map1, map2);
7327 if (!map1)
7328 return NULL;
7329 if (map1->n > 1)
7330 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7331 return map1;
7332 error:
7333 isl_map_free(map1);
7334 isl_map_free(map2);
7335 return NULL;
7338 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7339 * not be disjoint.
7341 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7342 __isl_take isl_map *map2)
7344 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7347 struct isl_set *isl_set_union_disjoint(
7348 struct isl_set *set1, struct isl_set *set2)
7350 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7351 set_to_map(set2)));
7354 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7356 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7359 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7360 * the results.
7362 * "map" and "set" are assumed to be compatible and non-NULL.
7364 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7365 __isl_take isl_set *set,
7366 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7367 __isl_take isl_basic_set *bset))
7369 unsigned flags = 0;
7370 struct isl_map *result;
7371 int i, j;
7373 if (isl_set_plain_is_universe(set)) {
7374 isl_set_free(set);
7375 return map;
7378 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7379 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7380 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7382 result = isl_map_alloc_space(isl_space_copy(map->dim),
7383 map->n * set->n, flags);
7384 for (i = 0; result && i < map->n; ++i)
7385 for (j = 0; j < set->n; ++j) {
7386 result = isl_map_add_basic_map(result,
7387 fn(isl_basic_map_copy(map->p[i]),
7388 isl_basic_set_copy(set->p[j])));
7389 if (!result)
7390 break;
7393 isl_map_free(map);
7394 isl_set_free(set);
7395 return result;
7398 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7399 __isl_take isl_set *set)
7401 isl_bool ok;
7403 ok = isl_map_compatible_range(map, set);
7404 if (ok < 0)
7405 goto error;
7406 if (!ok)
7407 isl_die(set->ctx, isl_error_invalid,
7408 "incompatible spaces", goto error);
7410 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7411 error:
7412 isl_map_free(map);
7413 isl_set_free(set);
7414 return NULL;
7417 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7418 __isl_take isl_set *set)
7420 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7423 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7424 __isl_take isl_set *set)
7426 isl_bool ok;
7428 ok = isl_map_compatible_domain(map, set);
7429 if (ok < 0)
7430 goto error;
7431 if (!ok)
7432 isl_die(set->ctx, isl_error_invalid,
7433 "incompatible spaces", goto error);
7435 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7436 error:
7437 isl_map_free(map);
7438 isl_set_free(set);
7439 return NULL;
7442 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7443 __isl_take isl_set *set)
7445 return isl_map_align_params_map_map_and(map, set,
7446 &map_intersect_domain);
7449 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7450 __isl_take isl_map *map2)
7452 if (!map1 || !map2)
7453 goto error;
7454 map1 = isl_map_reverse(map1);
7455 map1 = isl_map_apply_range(map1, map2);
7456 return isl_map_reverse(map1);
7457 error:
7458 isl_map_free(map1);
7459 isl_map_free(map2);
7460 return NULL;
7463 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7464 __isl_take isl_map *map2)
7466 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7469 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7470 __isl_take isl_map *map2)
7472 isl_space *dim_result;
7473 struct isl_map *result;
7474 int i, j;
7476 if (!map1 || !map2)
7477 goto error;
7479 dim_result = isl_space_join(isl_space_copy(map1->dim),
7480 isl_space_copy(map2->dim));
7482 result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
7483 if (!result)
7484 goto error;
7485 for (i = 0; i < map1->n; ++i)
7486 for (j = 0; j < map2->n; ++j) {
7487 result = isl_map_add_basic_map(result,
7488 isl_basic_map_apply_range(
7489 isl_basic_map_copy(map1->p[i]),
7490 isl_basic_map_copy(map2->p[j])));
7491 if (!result)
7492 goto error;
7494 isl_map_free(map1);
7495 isl_map_free(map2);
7496 if (result && result->n <= 1)
7497 ISL_F_SET(result, ISL_MAP_DISJOINT);
7498 return result;
7499 error:
7500 isl_map_free(map1);
7501 isl_map_free(map2);
7502 return NULL;
7505 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
7506 __isl_take isl_map *map2)
7508 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
7512 * returns range - domain
7514 struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap)
7516 isl_space *target_space;
7517 struct isl_basic_set *bset;
7518 unsigned dim;
7519 unsigned nparam;
7520 int i;
7522 if (!bmap)
7523 goto error;
7524 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7525 bmap->dim, isl_dim_out),
7526 goto error);
7527 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
7528 dim = isl_basic_map_n_in(bmap);
7529 nparam = isl_basic_map_n_param(bmap);
7530 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
7531 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
7532 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
7533 for (i = 0; i < dim; ++i) {
7534 int j = isl_basic_map_alloc_equality(bmap);
7535 if (j < 0) {
7536 bmap = isl_basic_map_free(bmap);
7537 break;
7539 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7540 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7541 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
7542 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
7544 bset = isl_basic_map_domain(bmap);
7545 bset = isl_basic_set_reset_space(bset, target_space);
7546 return bset;
7547 error:
7548 isl_basic_map_free(bmap);
7549 return NULL;
7553 * returns range - domain
7555 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
7557 int i;
7558 isl_space *dim;
7559 struct isl_set *result;
7561 if (!map)
7562 return NULL;
7564 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
7565 map->dim, isl_dim_out),
7566 goto error);
7567 dim = isl_map_get_space(map);
7568 dim = isl_space_domain(dim);
7569 result = isl_set_alloc_space(dim, map->n, 0);
7570 if (!result)
7571 goto error;
7572 for (i = 0; i < map->n; ++i)
7573 result = isl_set_add_basic_set(result,
7574 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
7575 isl_map_free(map);
7576 return result;
7577 error:
7578 isl_map_free(map);
7579 return NULL;
7583 * returns [domain -> range] -> range - domain
7585 __isl_give isl_basic_map *isl_basic_map_deltas_map(
7586 __isl_take isl_basic_map *bmap)
7588 int i, k;
7589 isl_space *dim;
7590 isl_basic_map *domain;
7591 int nparam, n;
7592 unsigned total;
7594 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7595 bmap->dim, isl_dim_out))
7596 isl_die(bmap->ctx, isl_error_invalid,
7597 "domain and range don't match", goto error);
7599 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7600 n = isl_basic_map_dim(bmap, isl_dim_in);
7602 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
7603 domain = isl_basic_map_universe(dim);
7605 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
7606 bmap = isl_basic_map_apply_range(bmap, domain);
7607 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
7609 total = isl_basic_map_total_dim(bmap);
7611 for (i = 0; i < n; ++i) {
7612 k = isl_basic_map_alloc_equality(bmap);
7613 if (k < 0)
7614 goto error;
7615 isl_seq_clr(bmap->eq[k], 1 + total);
7616 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
7617 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
7618 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
7621 bmap = isl_basic_map_gauss(bmap, NULL);
7622 return isl_basic_map_finalize(bmap);
7623 error:
7624 isl_basic_map_free(bmap);
7625 return NULL;
7629 * returns [domain -> range] -> range - domain
7631 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
7633 int i;
7634 isl_space *domain_dim;
7636 if (!map)
7637 return NULL;
7639 if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
7640 map->dim, isl_dim_out))
7641 isl_die(map->ctx, isl_error_invalid,
7642 "domain and range don't match", goto error);
7644 map = isl_map_cow(map);
7645 if (!map)
7646 return NULL;
7648 domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
7649 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
7650 map->dim = isl_space_join(map->dim, domain_dim);
7651 if (!map->dim)
7652 goto error;
7653 for (i = 0; i < map->n; ++i) {
7654 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
7655 if (!map->p[i])
7656 goto error;
7658 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
7659 return map;
7660 error:
7661 isl_map_free(map);
7662 return NULL;
7665 static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
7667 struct isl_basic_map *bmap;
7668 unsigned nparam;
7669 unsigned dim;
7670 int i;
7672 if (!dims)
7673 return NULL;
7675 nparam = dims->nparam;
7676 dim = dims->n_out;
7677 bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
7678 if (!bmap)
7679 goto error;
7681 for (i = 0; i < dim; ++i) {
7682 int j = isl_basic_map_alloc_equality(bmap);
7683 if (j < 0)
7684 goto error;
7685 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7686 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7687 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
7689 return isl_basic_map_finalize(bmap);
7690 error:
7691 isl_basic_map_free(bmap);
7692 return NULL;
7695 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
7697 if (!dim)
7698 return NULL;
7699 if (dim->n_in != dim->n_out)
7700 isl_die(dim->ctx, isl_error_invalid,
7701 "number of input and output dimensions needs to be "
7702 "the same", goto error);
7703 return basic_map_identity(dim);
7704 error:
7705 isl_space_free(dim);
7706 return NULL;
7709 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
7711 return isl_map_from_basic_map(isl_basic_map_identity(dim));
7714 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
7716 isl_space *dim = isl_set_get_space(set);
7717 isl_map *id;
7718 id = isl_map_identity(isl_space_map_from_set(dim));
7719 return isl_map_intersect_range(id, set);
7722 /* Construct a basic set with all set dimensions having only non-negative
7723 * values.
7725 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
7726 __isl_take isl_space *space)
7728 int i;
7729 unsigned nparam;
7730 unsigned dim;
7731 struct isl_basic_set *bset;
7733 if (!space)
7734 return NULL;
7735 nparam = space->nparam;
7736 dim = space->n_out;
7737 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
7738 if (!bset)
7739 return NULL;
7740 for (i = 0; i < dim; ++i) {
7741 int k = isl_basic_set_alloc_inequality(bset);
7742 if (k < 0)
7743 goto error;
7744 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
7745 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
7747 return bset;
7748 error:
7749 isl_basic_set_free(bset);
7750 return NULL;
7753 /* Construct the half-space x_pos >= 0.
7755 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
7756 int pos)
7758 int k;
7759 isl_basic_set *nonneg;
7761 nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7762 k = isl_basic_set_alloc_inequality(nonneg);
7763 if (k < 0)
7764 goto error;
7765 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
7766 isl_int_set_si(nonneg->ineq[k][pos], 1);
7768 return isl_basic_set_finalize(nonneg);
7769 error:
7770 isl_basic_set_free(nonneg);
7771 return NULL;
7774 /* Construct the half-space x_pos <= -1.
7776 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
7778 int k;
7779 isl_basic_set *neg;
7781 neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7782 k = isl_basic_set_alloc_inequality(neg);
7783 if (k < 0)
7784 goto error;
7785 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
7786 isl_int_set_si(neg->ineq[k][0], -1);
7787 isl_int_set_si(neg->ineq[k][pos], -1);
7789 return isl_basic_set_finalize(neg);
7790 error:
7791 isl_basic_set_free(neg);
7792 return NULL;
7795 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
7796 enum isl_dim_type type, unsigned first, unsigned n)
7798 int i;
7799 unsigned offset;
7800 isl_basic_set *nonneg;
7801 isl_basic_set *neg;
7803 if (!set)
7804 return NULL;
7805 if (n == 0)
7806 return set;
7808 isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
7810 offset = pos(set->dim, type);
7811 for (i = 0; i < n; ++i) {
7812 nonneg = nonneg_halfspace(isl_set_get_space(set),
7813 offset + first + i);
7814 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
7816 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
7819 return set;
7820 error:
7821 isl_set_free(set);
7822 return NULL;
7825 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
7826 int len,
7827 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7828 void *user)
7830 isl_set *half;
7832 if (!set)
7833 return isl_stat_error;
7834 if (isl_set_plain_is_empty(set)) {
7835 isl_set_free(set);
7836 return isl_stat_ok;
7838 if (first == len)
7839 return fn(set, signs, user);
7841 signs[first] = 1;
7842 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
7843 1 + first));
7844 half = isl_set_intersect(half, isl_set_copy(set));
7845 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
7846 goto error;
7848 signs[first] = -1;
7849 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
7850 1 + first));
7851 half = isl_set_intersect(half, set);
7852 return foreach_orthant(half, signs, first + 1, len, fn, user);
7853 error:
7854 isl_set_free(set);
7855 return isl_stat_error;
7858 /* Call "fn" on the intersections of "set" with each of the orthants
7859 * (except for obviously empty intersections). The orthant is identified
7860 * by the signs array, with each entry having value 1 or -1 according
7861 * to the sign of the corresponding variable.
7863 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
7864 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7865 void *user)
7867 unsigned nparam;
7868 unsigned nvar;
7869 int *signs;
7870 isl_stat r;
7872 if (!set)
7873 return isl_stat_error;
7874 if (isl_set_plain_is_empty(set))
7875 return isl_stat_ok;
7877 nparam = isl_set_dim(set, isl_dim_param);
7878 nvar = isl_set_dim(set, isl_dim_set);
7880 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
7882 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
7883 fn, user);
7885 free(signs);
7887 return r;
7890 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
7892 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
7895 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
7896 __isl_keep isl_basic_map *bmap2)
7898 int is_subset;
7899 struct isl_map *map1;
7900 struct isl_map *map2;
7902 if (!bmap1 || !bmap2)
7903 return isl_bool_error;
7905 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
7906 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
7908 is_subset = isl_map_is_subset(map1, map2);
7910 isl_map_free(map1);
7911 isl_map_free(map2);
7913 return is_subset;
7916 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
7917 __isl_keep isl_basic_set *bset2)
7919 return isl_basic_map_is_subset(bset1, bset2);
7922 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
7923 __isl_keep isl_basic_map *bmap2)
7925 isl_bool is_subset;
7927 if (!bmap1 || !bmap2)
7928 return isl_bool_error;
7929 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
7930 if (is_subset != isl_bool_true)
7931 return is_subset;
7932 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
7933 return is_subset;
7936 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
7937 __isl_keep isl_basic_set *bset2)
7939 return isl_basic_map_is_equal(
7940 bset_to_bmap(bset1), bset_to_bmap(bset2));
7943 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
7945 int i;
7946 int is_empty;
7948 if (!map)
7949 return isl_bool_error;
7950 for (i = 0; i < map->n; ++i) {
7951 is_empty = isl_basic_map_is_empty(map->p[i]);
7952 if (is_empty < 0)
7953 return isl_bool_error;
7954 if (!is_empty)
7955 return isl_bool_false;
7957 return isl_bool_true;
7960 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
7962 return map ? map->n == 0 : isl_bool_error;
7965 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
7967 return set ? set->n == 0 : isl_bool_error;
7970 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
7972 return isl_map_is_empty(set_to_map(set));
7975 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
7976 __isl_keep isl_map *map2)
7978 if (!map1 || !map2)
7979 return isl_bool_error;
7981 return isl_space_is_equal(map1->dim, map2->dim);
7984 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
7985 __isl_keep isl_set *set2)
7987 if (!set1 || !set2)
7988 return isl_bool_error;
7990 return isl_space_is_equal(set1->dim, set2->dim);
7993 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7995 isl_bool is_subset;
7997 if (!map1 || !map2)
7998 return isl_bool_error;
7999 is_subset = isl_map_is_subset(map1, map2);
8000 if (is_subset != isl_bool_true)
8001 return is_subset;
8002 is_subset = isl_map_is_subset(map2, map1);
8003 return is_subset;
8006 /* Is "map1" equal to "map2"?
8008 * First check if they are obviously equal.
8009 * If not, then perform a more detailed analysis.
8011 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8013 isl_bool equal;
8015 equal = isl_map_plain_is_equal(map1, map2);
8016 if (equal < 0 || equal)
8017 return equal;
8018 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8021 isl_bool isl_basic_map_is_strict_subset(
8022 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8024 isl_bool is_subset;
8026 if (!bmap1 || !bmap2)
8027 return isl_bool_error;
8028 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8029 if (is_subset != isl_bool_true)
8030 return is_subset;
8031 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8032 if (is_subset == isl_bool_error)
8033 return is_subset;
8034 return !is_subset;
8037 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8038 __isl_keep isl_map *map2)
8040 isl_bool is_subset;
8042 if (!map1 || !map2)
8043 return isl_bool_error;
8044 is_subset = isl_map_is_subset(map1, map2);
8045 if (is_subset != isl_bool_true)
8046 return is_subset;
8047 is_subset = isl_map_is_subset(map2, map1);
8048 if (is_subset == isl_bool_error)
8049 return is_subset;
8050 return !is_subset;
8053 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8054 __isl_keep isl_set *set2)
8056 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8059 /* Is "bmap" obviously equal to the universe with the same space?
8061 * That is, does it not have any constraints?
8063 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8065 if (!bmap)
8066 return isl_bool_error;
8067 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8070 /* Is "bset" obviously equal to the universe with the same space?
8072 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8074 return isl_basic_map_plain_is_universe(bset);
8077 /* If "c" does not involve any existentially quantified variables,
8078 * then set *univ to false and abort
8080 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8082 isl_bool *univ = user;
8083 unsigned n;
8085 n = isl_constraint_dim(c, isl_dim_div);
8086 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8087 isl_constraint_free(c);
8088 if (*univ < 0 || !*univ)
8089 return isl_stat_error;
8090 return isl_stat_ok;
8093 /* Is "bmap" equal to the universe with the same space?
8095 * First check if it is obviously equal to the universe.
8096 * If not and if there are any constraints not involving
8097 * existentially quantified variables, then it is certainly
8098 * not equal to the universe.
8099 * Otherwise, check if the universe is a subset of "bmap".
8101 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8103 isl_bool univ;
8104 isl_basic_map *test;
8106 univ = isl_basic_map_plain_is_universe(bmap);
8107 if (univ < 0 || univ)
8108 return univ;
8109 if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8110 return isl_bool_false;
8111 univ = isl_bool_true;
8112 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8113 univ)
8114 return isl_bool_error;
8115 if (univ < 0 || !univ)
8116 return univ;
8117 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8118 univ = isl_basic_map_is_subset(test, bmap);
8119 isl_basic_map_free(test);
8120 return univ;
8123 /* Is "bset" equal to the universe with the same space?
8125 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8127 return isl_basic_map_is_universe(bset);
8130 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8132 int i;
8134 if (!map)
8135 return isl_bool_error;
8137 for (i = 0; i < map->n; ++i) {
8138 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8139 if (r < 0 || r)
8140 return r;
8143 return isl_bool_false;
8146 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8148 return isl_map_plain_is_universe(set_to_map(set));
8151 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8153 struct isl_basic_set *bset = NULL;
8154 struct isl_vec *sample = NULL;
8155 isl_bool empty, non_empty;
8157 if (!bmap)
8158 return isl_bool_error;
8160 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8161 return isl_bool_true;
8163 if (isl_basic_map_plain_is_universe(bmap))
8164 return isl_bool_false;
8166 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8167 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8168 copy = isl_basic_map_remove_redundancies(copy);
8169 empty = isl_basic_map_plain_is_empty(copy);
8170 isl_basic_map_free(copy);
8171 return empty;
8174 non_empty = isl_basic_map_plain_is_non_empty(bmap);
8175 if (non_empty < 0)
8176 return isl_bool_error;
8177 if (non_empty)
8178 return isl_bool_false;
8179 isl_vec_free(bmap->sample);
8180 bmap->sample = NULL;
8181 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8182 if (!bset)
8183 return isl_bool_error;
8184 sample = isl_basic_set_sample_vec(bset);
8185 if (!sample)
8186 return isl_bool_error;
8187 empty = sample->size == 0;
8188 isl_vec_free(bmap->sample);
8189 bmap->sample = sample;
8190 if (empty)
8191 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8193 return empty;
8196 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8198 if (!bmap)
8199 return isl_bool_error;
8200 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8203 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8205 if (!bset)
8206 return isl_bool_error;
8207 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8210 /* Is "bmap" known to be non-empty?
8212 * That is, is the cached sample still valid?
8214 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8216 unsigned total;
8218 if (!bmap)
8219 return isl_bool_error;
8220 if (!bmap->sample)
8221 return isl_bool_false;
8222 total = 1 + isl_basic_map_total_dim(bmap);
8223 if (bmap->sample->size != total)
8224 return isl_bool_false;
8225 return isl_basic_map_contains(bmap, bmap->sample);
8228 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8230 return isl_basic_map_is_empty(bset_to_bmap(bset));
8233 struct isl_map *isl_basic_map_union(
8234 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8236 struct isl_map *map;
8237 if (!bmap1 || !bmap2)
8238 goto error;
8240 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8242 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8243 if (!map)
8244 goto error;
8245 map = isl_map_add_basic_map(map, bmap1);
8246 map = isl_map_add_basic_map(map, bmap2);
8247 return map;
8248 error:
8249 isl_basic_map_free(bmap1);
8250 isl_basic_map_free(bmap2);
8251 return NULL;
8254 struct isl_set *isl_basic_set_union(
8255 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8257 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8258 bset_to_bmap(bset2)));
8261 /* Order divs such that any div only depends on previous divs */
8262 struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap)
8264 int i;
8265 unsigned off;
8267 if (!bmap)
8268 return NULL;
8270 off = isl_space_dim(bmap->dim, isl_dim_all);
8272 for (i = 0; i < bmap->n_div; ++i) {
8273 int pos;
8274 if (isl_int_is_zero(bmap->div[i][0]))
8275 continue;
8276 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8277 bmap->n_div-i);
8278 if (pos == -1)
8279 continue;
8280 if (pos == 0)
8281 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8282 "integer division depends on itself",
8283 return isl_basic_map_free(bmap));
8284 isl_basic_map_swap_div(bmap, i, i + pos);
8285 --i;
8287 return bmap;
8290 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8292 return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8295 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8297 int i;
8299 if (!map)
8300 return 0;
8302 for (i = 0; i < map->n; ++i) {
8303 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8304 if (!map->p[i])
8305 goto error;
8308 return map;
8309 error:
8310 isl_map_free(map);
8311 return NULL;
8314 /* Sort the local variables of "bset".
8316 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8317 __isl_take isl_basic_set *bset)
8319 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8322 /* Apply the expansion computed by isl_merge_divs.
8323 * The expansion itself is given by "exp" while the resulting
8324 * list of divs is given by "div".
8326 * Move the integer divisions of "bmap" into the right position
8327 * according to "exp" and then introduce the additional integer
8328 * divisions, adding div constraints.
8329 * The moving should be done first to avoid moving coefficients
8330 * in the definitions of the extra integer divisions.
8332 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8333 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8335 int i, j;
8336 int n_div;
8338 bmap = isl_basic_map_cow(bmap);
8339 if (!bmap || !div)
8340 goto error;
8342 if (div->n_row < bmap->n_div)
8343 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8344 "not an expansion", goto error);
8346 n_div = bmap->n_div;
8347 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8348 div->n_row - n_div, 0,
8349 2 * (div->n_row - n_div));
8351 for (i = n_div; i < div->n_row; ++i)
8352 if (isl_basic_map_alloc_div(bmap) < 0)
8353 goto error;
8355 for (j = n_div - 1; j >= 0; --j) {
8356 if (exp[j] == j)
8357 break;
8358 isl_basic_map_swap_div(bmap, j, exp[j]);
8360 j = 0;
8361 for (i = 0; i < div->n_row; ++i) {
8362 if (j < n_div && exp[j] == i) {
8363 j++;
8364 } else {
8365 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8366 if (isl_basic_map_div_is_marked_unknown(bmap, i))
8367 continue;
8368 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
8369 goto error;
8373 isl_mat_free(div);
8374 return bmap;
8375 error:
8376 isl_basic_map_free(bmap);
8377 isl_mat_free(div);
8378 return NULL;
8381 /* Apply the expansion computed by isl_merge_divs.
8382 * The expansion itself is given by "exp" while the resulting
8383 * list of divs is given by "div".
8385 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8386 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8388 return isl_basic_map_expand_divs(bset, div, exp);
8391 /* Look for a div in dst that corresponds to the div "div" in src.
8392 * The divs before "div" in src and dst are assumed to be the same.
8394 * Returns -1 if no corresponding div was found and the position
8395 * of the corresponding div in dst otherwise.
8397 static int find_div(struct isl_basic_map *dst,
8398 struct isl_basic_map *src, unsigned div)
8400 int i;
8402 unsigned total = isl_space_dim(src->dim, isl_dim_all);
8404 isl_assert(dst->ctx, div <= dst->n_div, return -1);
8405 for (i = div; i < dst->n_div; ++i)
8406 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8407 isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8408 dst->n_div - div) == -1)
8409 return i;
8410 return -1;
8413 /* Align the divs of "dst" to those of "src", adding divs from "src"
8414 * if needed. That is, make sure that the first src->n_div divs
8415 * of the result are equal to those of src.
8417 * The result is not finalized as by design it will have redundant
8418 * divs if any divs from "src" were copied.
8420 __isl_give isl_basic_map *isl_basic_map_align_divs(
8421 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8423 int i;
8424 int known, extended;
8425 unsigned total;
8427 if (!dst || !src)
8428 return isl_basic_map_free(dst);
8430 if (src->n_div == 0)
8431 return dst;
8433 known = isl_basic_map_divs_known(src);
8434 if (known < 0)
8435 return isl_basic_map_free(dst);
8436 if (!known)
8437 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8438 "some src divs are unknown",
8439 return isl_basic_map_free(dst));
8441 src = isl_basic_map_order_divs(src);
8443 extended = 0;
8444 total = isl_space_dim(src->dim, isl_dim_all);
8445 for (i = 0; i < src->n_div; ++i) {
8446 int j = find_div(dst, src, i);
8447 if (j < 0) {
8448 if (!extended) {
8449 int extra = src->n_div - i;
8450 dst = isl_basic_map_cow(dst);
8451 if (!dst)
8452 return NULL;
8453 dst = isl_basic_map_extend_space(dst,
8454 isl_space_copy(dst->dim),
8455 extra, 0, 2 * extra);
8456 extended = 1;
8458 j = isl_basic_map_alloc_div(dst);
8459 if (j < 0)
8460 return isl_basic_map_free(dst);
8461 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8462 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8463 if (isl_basic_map_add_div_constraints(dst, j) < 0)
8464 return isl_basic_map_free(dst);
8466 if (j != i)
8467 isl_basic_map_swap_div(dst, i, j);
8469 return dst;
8472 struct isl_map *isl_map_align_divs(struct isl_map *map)
8474 int i;
8476 if (!map)
8477 return NULL;
8478 if (map->n == 0)
8479 return map;
8480 map = isl_map_compute_divs(map);
8481 map = isl_map_cow(map);
8482 if (!map)
8483 return NULL;
8485 for (i = 1; i < map->n; ++i)
8486 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8487 for (i = 1; i < map->n; ++i) {
8488 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8489 if (!map->p[i])
8490 return isl_map_free(map);
8493 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
8494 return map;
8497 struct isl_set *isl_set_align_divs(struct isl_set *set)
8499 return set_from_map(isl_map_align_divs(set_to_map(set)));
8502 /* Align the divs of the basic maps in "map" to those
8503 * of the basic maps in "list", as well as to the other basic maps in "map".
8504 * The elements in "list" are assumed to have known divs.
8506 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
8507 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
8509 int i, n;
8511 map = isl_map_compute_divs(map);
8512 map = isl_map_cow(map);
8513 if (!map || !list)
8514 return isl_map_free(map);
8515 if (map->n == 0)
8516 return map;
8518 n = isl_basic_map_list_n_basic_map(list);
8519 for (i = 0; i < n; ++i) {
8520 isl_basic_map *bmap;
8522 bmap = isl_basic_map_list_get_basic_map(list, i);
8523 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
8524 isl_basic_map_free(bmap);
8526 if (!map->p[0])
8527 return isl_map_free(map);
8529 return isl_map_align_divs(map);
8532 /* Align the divs of each element of "list" to those of "bmap".
8533 * Both "bmap" and the elements of "list" are assumed to have known divs.
8535 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
8536 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
8538 int i, n;
8540 if (!list || !bmap)
8541 return isl_basic_map_list_free(list);
8543 n = isl_basic_map_list_n_basic_map(list);
8544 for (i = 0; i < n; ++i) {
8545 isl_basic_map *bmap_i;
8547 bmap_i = isl_basic_map_list_get_basic_map(list, i);
8548 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
8549 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
8552 return list;
8555 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
8556 __isl_take isl_map *map)
8558 isl_bool ok;
8560 ok = isl_map_compatible_domain(map, set);
8561 if (ok < 0)
8562 goto error;
8563 if (!ok)
8564 isl_die(isl_set_get_ctx(set), isl_error_invalid,
8565 "incompatible spaces", goto error);
8566 map = isl_map_intersect_domain(map, set);
8567 set = isl_map_range(map);
8568 return set;
8569 error:
8570 isl_set_free(set);
8571 isl_map_free(map);
8572 return NULL;
8575 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
8576 __isl_take isl_map *map)
8578 return isl_map_align_params_map_map_and(set, map, &set_apply);
8581 /* There is no need to cow as removing empty parts doesn't change
8582 * the meaning of the set.
8584 struct isl_map *isl_map_remove_empty_parts(struct isl_map *map)
8586 int i;
8588 if (!map)
8589 return NULL;
8591 for (i = map->n - 1; i >= 0; --i)
8592 remove_if_empty(map, i);
8594 return map;
8597 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
8599 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
8602 /* Given two basic sets bset1 and bset2, compute the maximal difference
8603 * between the values of dimension pos in bset1 and those in bset2
8604 * for any common value of the parameters and dimensions preceding pos.
8606 static enum isl_lp_result basic_set_maximal_difference_at(
8607 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
8608 int pos, isl_int *opt)
8610 isl_basic_map *bmap1;
8611 isl_basic_map *bmap2;
8612 struct isl_ctx *ctx;
8613 struct isl_vec *obj;
8614 unsigned total;
8615 unsigned nparam;
8616 unsigned dim1;
8617 enum isl_lp_result res;
8619 if (!bset1 || !bset2)
8620 return isl_lp_error;
8622 nparam = isl_basic_set_n_param(bset1);
8623 dim1 = isl_basic_set_n_dim(bset1);
8625 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
8626 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
8627 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
8628 isl_dim_out, 0, pos);
8629 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
8630 isl_dim_out, 0, pos);
8631 bmap1 = isl_basic_map_range_product(bmap1, bmap2);
8632 if (!bmap1)
8633 return isl_lp_error;
8635 total = isl_basic_map_total_dim(bmap1);
8636 ctx = bmap1->ctx;
8637 obj = isl_vec_alloc(ctx, 1 + total);
8638 if (!obj)
8639 goto error;
8640 isl_seq_clr(obj->block.data, 1 + total);
8641 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
8642 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
8643 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
8644 opt, NULL, NULL);
8645 isl_basic_map_free(bmap1);
8646 isl_vec_free(obj);
8647 return res;
8648 error:
8649 isl_basic_map_free(bmap1);
8650 return isl_lp_error;
8653 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
8654 * for any common value of the parameters and dimensions preceding pos
8655 * in both basic sets, the values of dimension pos in bset1 are
8656 * smaller or larger than those in bset2.
8658 * Returns
8659 * 1 if bset1 follows bset2
8660 * -1 if bset1 precedes bset2
8661 * 0 if bset1 and bset2 are incomparable
8662 * -2 if some error occurred.
8664 int isl_basic_set_compare_at(struct isl_basic_set *bset1,
8665 struct isl_basic_set *bset2, int pos)
8667 isl_int opt;
8668 enum isl_lp_result res;
8669 int cmp;
8671 isl_int_init(opt);
8673 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8675 if (res == isl_lp_empty)
8676 cmp = 0;
8677 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8678 res == isl_lp_unbounded)
8679 cmp = 1;
8680 else if (res == isl_lp_ok && isl_int_is_neg(opt))
8681 cmp = -1;
8682 else
8683 cmp = -2;
8685 isl_int_clear(opt);
8686 return cmp;
8689 /* Given two basic sets bset1 and bset2, check whether
8690 * for any common value of the parameters and dimensions preceding pos
8691 * there is a value of dimension pos in bset1 that is larger
8692 * than a value of the same dimension in bset2.
8694 * Return
8695 * 1 if there exists such a pair
8696 * 0 if there is no such pair, but there is a pair of equal values
8697 * -1 otherwise
8698 * -2 if some error occurred.
8700 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
8701 __isl_keep isl_basic_set *bset2, int pos)
8703 isl_int opt;
8704 enum isl_lp_result res;
8705 int cmp;
8707 isl_int_init(opt);
8709 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8711 if (res == isl_lp_empty)
8712 cmp = -1;
8713 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8714 res == isl_lp_unbounded)
8715 cmp = 1;
8716 else if (res == isl_lp_ok && isl_int_is_neg(opt))
8717 cmp = -1;
8718 else if (res == isl_lp_ok)
8719 cmp = 0;
8720 else
8721 cmp = -2;
8723 isl_int_clear(opt);
8724 return cmp;
8727 /* Given two sets set1 and set2, check whether
8728 * for any common value of the parameters and dimensions preceding pos
8729 * there is a value of dimension pos in set1 that is larger
8730 * than a value of the same dimension in set2.
8732 * Return
8733 * 1 if there exists such a pair
8734 * 0 if there is no such pair, but there is a pair of equal values
8735 * -1 otherwise
8736 * -2 if some error occurred.
8738 int isl_set_follows_at(__isl_keep isl_set *set1,
8739 __isl_keep isl_set *set2, int pos)
8741 int i, j;
8742 int follows = -1;
8744 if (!set1 || !set2)
8745 return -2;
8747 for (i = 0; i < set1->n; ++i)
8748 for (j = 0; j < set2->n; ++j) {
8749 int f;
8750 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
8751 if (f == 1 || f == -2)
8752 return f;
8753 if (f > follows)
8754 follows = f;
8757 return follows;
8760 static isl_bool isl_basic_map_plain_has_fixed_var(
8761 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
8763 int i;
8764 int d;
8765 unsigned total;
8767 if (!bmap)
8768 return isl_bool_error;
8769 total = isl_basic_map_total_dim(bmap);
8770 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
8771 for (; d+1 > pos; --d)
8772 if (!isl_int_is_zero(bmap->eq[i][1+d]))
8773 break;
8774 if (d != pos)
8775 continue;
8776 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
8777 return isl_bool_false;
8778 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
8779 return isl_bool_false;
8780 if (!isl_int_is_one(bmap->eq[i][1+d]))
8781 return isl_bool_false;
8782 if (val)
8783 isl_int_neg(*val, bmap->eq[i][0]);
8784 return isl_bool_true;
8786 return isl_bool_false;
8789 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
8790 unsigned pos, isl_int *val)
8792 int i;
8793 isl_int v;
8794 isl_int tmp;
8795 isl_bool fixed;
8797 if (!map)
8798 return isl_bool_error;
8799 if (map->n == 0)
8800 return isl_bool_false;
8801 if (map->n == 1)
8802 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
8803 isl_int_init(v);
8804 isl_int_init(tmp);
8805 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
8806 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
8807 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
8808 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
8809 fixed = isl_bool_false;
8811 if (val)
8812 isl_int_set(*val, v);
8813 isl_int_clear(tmp);
8814 isl_int_clear(v);
8815 return fixed;
8818 static isl_bool isl_basic_set_plain_has_fixed_var(
8819 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
8821 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
8822 pos, val);
8825 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
8826 enum isl_dim_type type, unsigned pos, isl_int *val)
8828 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
8829 return isl_bool_error;
8830 return isl_basic_map_plain_has_fixed_var(bmap,
8831 isl_basic_map_offset(bmap, type) - 1 + pos, val);
8834 /* If "bmap" obviously lies on a hyperplane where the given dimension
8835 * has a fixed value, then return that value.
8836 * Otherwise return NaN.
8838 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
8839 __isl_keep isl_basic_map *bmap,
8840 enum isl_dim_type type, unsigned pos)
8842 isl_ctx *ctx;
8843 isl_val *v;
8844 isl_bool fixed;
8846 if (!bmap)
8847 return NULL;
8848 ctx = isl_basic_map_get_ctx(bmap);
8849 v = isl_val_alloc(ctx);
8850 if (!v)
8851 return NULL;
8852 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
8853 if (fixed < 0)
8854 return isl_val_free(v);
8855 if (fixed) {
8856 isl_int_set_si(v->d, 1);
8857 return v;
8859 isl_val_free(v);
8860 return isl_val_nan(ctx);
8863 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
8864 enum isl_dim_type type, unsigned pos, isl_int *val)
8866 if (pos >= isl_map_dim(map, type))
8867 isl_die(isl_map_get_ctx(map), isl_error_invalid,
8868 "position out of bounds", return isl_bool_error);
8869 return isl_map_plain_has_fixed_var(map,
8870 map_offset(map, type) - 1 + pos, val);
8873 /* If "map" obviously lies on a hyperplane where the given dimension
8874 * has a fixed value, then return that value.
8875 * Otherwise return NaN.
8877 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
8878 enum isl_dim_type type, unsigned pos)
8880 isl_ctx *ctx;
8881 isl_val *v;
8882 isl_bool fixed;
8884 if (!map)
8885 return NULL;
8886 ctx = isl_map_get_ctx(map);
8887 v = isl_val_alloc(ctx);
8888 if (!v)
8889 return NULL;
8890 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
8891 if (fixed < 0)
8892 return isl_val_free(v);
8893 if (fixed) {
8894 isl_int_set_si(v->d, 1);
8895 return v;
8897 isl_val_free(v);
8898 return isl_val_nan(ctx);
8901 /* If "set" obviously lies on a hyperplane where the given dimension
8902 * has a fixed value, then return that value.
8903 * Otherwise return NaN.
8905 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
8906 enum isl_dim_type type, unsigned pos)
8908 return isl_map_plain_get_val_if_fixed(set, type, pos);
8911 isl_bool isl_set_plain_is_fixed(__isl_keep isl_set *set,
8912 enum isl_dim_type type, unsigned pos, isl_int *val)
8914 return isl_map_plain_is_fixed(set, type, pos, val);
8917 /* Check if dimension dim has fixed value and if so and if val is not NULL,
8918 * then return this fixed value in *val.
8920 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
8921 unsigned dim, isl_int *val)
8923 return isl_basic_set_plain_has_fixed_var(bset,
8924 isl_basic_set_n_param(bset) + dim, val);
8927 /* Return -1 if the constraint "c1" should be sorted before "c2"
8928 * and 1 if it should be sorted after "c2".
8929 * Return 0 if the two constraints are the same (up to the constant term).
8931 * In particular, if a constraint involves later variables than another
8932 * then it is sorted after this other constraint.
8933 * uset_gist depends on constraints without existentially quantified
8934 * variables sorting first.
8936 * For constraints that have the same latest variable, those
8937 * with the same coefficient for this latest variable (first in absolute value
8938 * and then in actual value) are grouped together.
8939 * This is useful for detecting pairs of constraints that can
8940 * be chained in their printed representation.
8942 * Finally, within a group, constraints are sorted according to
8943 * their coefficients (excluding the constant term).
8945 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
8947 isl_int **c1 = (isl_int **) p1;
8948 isl_int **c2 = (isl_int **) p2;
8949 int l1, l2;
8950 unsigned size = *(unsigned *) arg;
8951 int cmp;
8953 l1 = isl_seq_last_non_zero(*c1 + 1, size);
8954 l2 = isl_seq_last_non_zero(*c2 + 1, size);
8956 if (l1 != l2)
8957 return l1 - l2;
8959 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
8960 if (cmp != 0)
8961 return cmp;
8962 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
8963 if (cmp != 0)
8964 return -cmp;
8966 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
8969 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
8970 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
8971 * and 0 if the two constraints are the same (up to the constant term).
8973 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
8974 isl_int *c1, isl_int *c2)
8976 unsigned total;
8978 if (!bmap)
8979 return -2;
8980 total = isl_basic_map_total_dim(bmap);
8981 return sort_constraint_cmp(&c1, &c2, &total);
8984 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
8985 __isl_take isl_basic_map *bmap)
8987 unsigned total;
8989 if (!bmap)
8990 return NULL;
8991 if (bmap->n_ineq == 0)
8992 return bmap;
8993 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
8994 return bmap;
8995 total = isl_basic_map_total_dim(bmap);
8996 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
8997 &sort_constraint_cmp, &total) < 0)
8998 return isl_basic_map_free(bmap);
8999 return bmap;
9002 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9003 __isl_take isl_basic_set *bset)
9005 isl_basic_map *bmap = bset_to_bmap(bset);
9006 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9009 struct isl_basic_map *isl_basic_map_normalize(struct isl_basic_map *bmap)
9011 if (!bmap)
9012 return NULL;
9013 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9014 return bmap;
9015 bmap = isl_basic_map_remove_redundancies(bmap);
9016 bmap = isl_basic_map_sort_constraints(bmap);
9017 if (bmap)
9018 ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
9019 return bmap;
9021 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9022 __isl_keep isl_basic_map *bmap2)
9024 int i, cmp;
9025 unsigned total;
9027 if (!bmap1 || !bmap2)
9028 return -1;
9030 if (bmap1 == bmap2)
9031 return 0;
9032 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9033 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9034 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9035 if (isl_basic_map_n_param(bmap1) != isl_basic_map_n_param(bmap2))
9036 return isl_basic_map_n_param(bmap1) - isl_basic_map_n_param(bmap2);
9037 if (isl_basic_map_n_in(bmap1) != isl_basic_map_n_in(bmap2))
9038 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
9039 if (isl_basic_map_n_out(bmap1) != isl_basic_map_n_out(bmap2))
9040 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
9041 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9042 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9043 return 0;
9044 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9045 return 1;
9046 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9047 return -1;
9048 if (bmap1->n_eq != bmap2->n_eq)
9049 return bmap1->n_eq - bmap2->n_eq;
9050 if (bmap1->n_ineq != bmap2->n_ineq)
9051 return bmap1->n_ineq - bmap2->n_ineq;
9052 if (bmap1->n_div != bmap2->n_div)
9053 return bmap1->n_div - bmap2->n_div;
9054 total = isl_basic_map_total_dim(bmap1);
9055 for (i = 0; i < bmap1->n_eq; ++i) {
9056 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9057 if (cmp)
9058 return cmp;
9060 for (i = 0; i < bmap1->n_ineq; ++i) {
9061 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9062 if (cmp)
9063 return cmp;
9065 for (i = 0; i < bmap1->n_div; ++i) {
9066 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9067 if (cmp)
9068 return cmp;
9070 return 0;
9073 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9074 __isl_keep isl_basic_set *bset2)
9076 return isl_basic_map_plain_cmp(bset1, bset2);
9079 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9081 int i, cmp;
9083 if (set1 == set2)
9084 return 0;
9085 if (set1->n != set2->n)
9086 return set1->n - set2->n;
9088 for (i = 0; i < set1->n; ++i) {
9089 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9090 if (cmp)
9091 return cmp;
9094 return 0;
9097 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9098 __isl_keep isl_basic_map *bmap2)
9100 if (!bmap1 || !bmap2)
9101 return isl_bool_error;
9102 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9105 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9106 __isl_keep isl_basic_set *bset2)
9108 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9109 bset_to_bmap(bset2));
9112 static int qsort_bmap_cmp(const void *p1, const void *p2)
9114 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9115 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9117 return isl_basic_map_plain_cmp(bmap1, bmap2);
9120 /* Sort the basic maps of "map" and remove duplicate basic maps.
9122 * While removing basic maps, we make sure that the basic maps remain
9123 * sorted because isl_map_normalize expects the basic maps of the result
9124 * to be sorted.
9126 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9128 int i, j;
9130 map = isl_map_remove_empty_parts(map);
9131 if (!map)
9132 return NULL;
9133 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9134 for (i = map->n - 1; i >= 1; --i) {
9135 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9136 continue;
9137 isl_basic_map_free(map->p[i-1]);
9138 for (j = i; j < map->n; ++j)
9139 map->p[j - 1] = map->p[j];
9140 map->n--;
9143 return map;
9146 /* Remove obvious duplicates among the basic maps of "map".
9148 * Unlike isl_map_normalize, this function does not remove redundant
9149 * constraints and only removes duplicates that have exactly the same
9150 * constraints in the input. It does sort the constraints and
9151 * the basic maps to ease the detection of duplicates.
9153 * If "map" has already been normalized or if the basic maps are
9154 * disjoint, then there can be no duplicates.
9156 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9158 int i;
9159 isl_basic_map *bmap;
9161 if (!map)
9162 return NULL;
9163 if (map->n <= 1)
9164 return map;
9165 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9166 return map;
9167 for (i = 0; i < map->n; ++i) {
9168 bmap = isl_basic_map_copy(map->p[i]);
9169 bmap = isl_basic_map_sort_constraints(bmap);
9170 if (!bmap)
9171 return isl_map_free(map);
9172 isl_basic_map_free(map->p[i]);
9173 map->p[i] = bmap;
9176 map = sort_and_remove_duplicates(map);
9177 return map;
9180 /* We normalize in place, but if anything goes wrong we need
9181 * to return NULL, so we need to make sure we don't change the
9182 * meaning of any possible other copies of map.
9184 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9186 int i;
9187 struct isl_basic_map *bmap;
9189 if (!map)
9190 return NULL;
9191 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9192 return map;
9193 for (i = 0; i < map->n; ++i) {
9194 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9195 if (!bmap)
9196 goto error;
9197 isl_basic_map_free(map->p[i]);
9198 map->p[i] = bmap;
9201 map = sort_and_remove_duplicates(map);
9202 if (map)
9203 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9204 return map;
9205 error:
9206 isl_map_free(map);
9207 return NULL;
9210 struct isl_set *isl_set_normalize(struct isl_set *set)
9212 return set_from_map(isl_map_normalize(set_to_map(set)));
9215 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9216 __isl_keep isl_map *map2)
9218 int i;
9219 isl_bool equal;
9221 if (!map1 || !map2)
9222 return isl_bool_error;
9224 if (map1 == map2)
9225 return isl_bool_true;
9226 if (!isl_space_is_equal(map1->dim, map2->dim))
9227 return isl_bool_false;
9229 map1 = isl_map_copy(map1);
9230 map2 = isl_map_copy(map2);
9231 map1 = isl_map_normalize(map1);
9232 map2 = isl_map_normalize(map2);
9233 if (!map1 || !map2)
9234 goto error;
9235 equal = map1->n == map2->n;
9236 for (i = 0; equal && i < map1->n; ++i) {
9237 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9238 if (equal < 0)
9239 goto error;
9241 isl_map_free(map1);
9242 isl_map_free(map2);
9243 return equal;
9244 error:
9245 isl_map_free(map1);
9246 isl_map_free(map2);
9247 return isl_bool_error;
9250 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9251 __isl_keep isl_set *set2)
9253 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9256 /* Return the basic maps in "map" as a list.
9258 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9259 __isl_keep isl_map *map)
9261 int i;
9262 isl_ctx *ctx;
9263 isl_basic_map_list *list;
9265 if (!map)
9266 return NULL;
9267 ctx = isl_map_get_ctx(map);
9268 list = isl_basic_map_list_alloc(ctx, map->n);
9270 for (i = 0; i < map->n; ++i) {
9271 isl_basic_map *bmap;
9273 bmap = isl_basic_map_copy(map->p[i]);
9274 list = isl_basic_map_list_add(list, bmap);
9277 return list;
9280 /* Return the intersection of the elements in the non-empty list "list".
9281 * All elements are assumed to live in the same space.
9283 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9284 __isl_take isl_basic_map_list *list)
9286 int i, n;
9287 isl_basic_map *bmap;
9289 if (!list)
9290 return NULL;
9291 n = isl_basic_map_list_n_basic_map(list);
9292 if (n < 1)
9293 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9294 "expecting non-empty list", goto error);
9296 bmap = isl_basic_map_list_get_basic_map(list, 0);
9297 for (i = 1; i < n; ++i) {
9298 isl_basic_map *bmap_i;
9300 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9301 bmap = isl_basic_map_intersect(bmap, bmap_i);
9304 isl_basic_map_list_free(list);
9305 return bmap;
9306 error:
9307 isl_basic_map_list_free(list);
9308 return NULL;
9311 /* Return the intersection of the elements in the non-empty list "list".
9312 * All elements are assumed to live in the same space.
9314 __isl_give isl_basic_set *isl_basic_set_list_intersect(
9315 __isl_take isl_basic_set_list *list)
9317 return isl_basic_map_list_intersect(list);
9320 /* Return the union of the elements of "list".
9321 * The list is required to have at least one element.
9323 __isl_give isl_set *isl_basic_set_list_union(
9324 __isl_take isl_basic_set_list *list)
9326 int i, n;
9327 isl_space *space;
9328 isl_basic_set *bset;
9329 isl_set *set;
9331 if (!list)
9332 return NULL;
9333 n = isl_basic_set_list_n_basic_set(list);
9334 if (n < 1)
9335 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9336 "expecting non-empty list", goto error);
9338 bset = isl_basic_set_list_get_basic_set(list, 0);
9339 space = isl_basic_set_get_space(bset);
9340 isl_basic_set_free(bset);
9342 set = isl_set_alloc_space(space, n, 0);
9343 for (i = 0; i < n; ++i) {
9344 bset = isl_basic_set_list_get_basic_set(list, i);
9345 set = isl_set_add_basic_set(set, bset);
9348 isl_basic_set_list_free(list);
9349 return set;
9350 error:
9351 isl_basic_set_list_free(list);
9352 return NULL;
9355 /* Return the union of the elements in the non-empty list "list".
9356 * All elements are assumed to live in the same space.
9358 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9360 int i, n;
9361 isl_set *set;
9363 if (!list)
9364 return NULL;
9365 n = isl_set_list_n_set(list);
9366 if (n < 1)
9367 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9368 "expecting non-empty list", goto error);
9370 set = isl_set_list_get_set(list, 0);
9371 for (i = 1; i < n; ++i) {
9372 isl_set *set_i;
9374 set_i = isl_set_list_get_set(list, i);
9375 set = isl_set_union(set, set_i);
9378 isl_set_list_free(list);
9379 return set;
9380 error:
9381 isl_set_list_free(list);
9382 return NULL;
9385 struct isl_basic_map *isl_basic_map_product(
9386 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
9388 isl_space *dim_result = NULL;
9389 struct isl_basic_map *bmap;
9390 unsigned in1, in2, out1, out2, nparam, total, pos;
9391 struct isl_dim_map *dim_map1, *dim_map2;
9393 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9394 goto error;
9395 dim_result = isl_space_product(isl_space_copy(bmap1->dim),
9396 isl_space_copy(bmap2->dim));
9398 in1 = isl_basic_map_n_in(bmap1);
9399 in2 = isl_basic_map_n_in(bmap2);
9400 out1 = isl_basic_map_n_out(bmap1);
9401 out2 = isl_basic_map_n_out(bmap2);
9402 nparam = isl_basic_map_n_param(bmap1);
9404 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9405 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9406 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9407 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9408 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9409 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9410 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9411 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9412 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9413 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9414 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9416 bmap = isl_basic_map_alloc_space(dim_result,
9417 bmap1->n_div + bmap2->n_div,
9418 bmap1->n_eq + bmap2->n_eq,
9419 bmap1->n_ineq + bmap2->n_ineq);
9420 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9421 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9422 bmap = isl_basic_map_simplify(bmap);
9423 return isl_basic_map_finalize(bmap);
9424 error:
9425 isl_basic_map_free(bmap1);
9426 isl_basic_map_free(bmap2);
9427 return NULL;
9430 __isl_give isl_basic_map *isl_basic_map_flat_product(
9431 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9433 isl_basic_map *prod;
9435 prod = isl_basic_map_product(bmap1, bmap2);
9436 prod = isl_basic_map_flatten(prod);
9437 return prod;
9440 __isl_give isl_basic_set *isl_basic_set_flat_product(
9441 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9443 return isl_basic_map_flat_range_product(bset1, bset2);
9446 __isl_give isl_basic_map *isl_basic_map_domain_product(
9447 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9449 isl_space *space_result = NULL;
9450 isl_basic_map *bmap;
9451 unsigned in1, in2, out, nparam, total, pos;
9452 struct isl_dim_map *dim_map1, *dim_map2;
9454 if (!bmap1 || !bmap2)
9455 goto error;
9457 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9458 isl_space_copy(bmap2->dim));
9460 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9461 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9462 out = isl_basic_map_dim(bmap1, isl_dim_out);
9463 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9465 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9466 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9467 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9468 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9469 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9470 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9471 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9472 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9473 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9474 isl_dim_map_div(dim_map1, bmap1, pos += out);
9475 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9477 bmap = isl_basic_map_alloc_space(space_result,
9478 bmap1->n_div + bmap2->n_div,
9479 bmap1->n_eq + bmap2->n_eq,
9480 bmap1->n_ineq + bmap2->n_ineq);
9481 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9482 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9483 bmap = isl_basic_map_simplify(bmap);
9484 return isl_basic_map_finalize(bmap);
9485 error:
9486 isl_basic_map_free(bmap1);
9487 isl_basic_map_free(bmap2);
9488 return NULL;
9491 __isl_give isl_basic_map *isl_basic_map_range_product(
9492 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9494 isl_bool rational;
9495 isl_space *dim_result = NULL;
9496 isl_basic_map *bmap;
9497 unsigned in, out1, out2, nparam, total, pos;
9498 struct isl_dim_map *dim_map1, *dim_map2;
9500 rational = isl_basic_map_is_rational(bmap1);
9501 if (rational >= 0 && rational)
9502 rational = isl_basic_map_is_rational(bmap2);
9503 if (!bmap1 || !bmap2 || rational < 0)
9504 goto error;
9506 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9507 goto error;
9509 dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
9510 isl_space_copy(bmap2->dim));
9512 in = isl_basic_map_dim(bmap1, isl_dim_in);
9513 out1 = isl_basic_map_n_out(bmap1);
9514 out2 = isl_basic_map_n_out(bmap2);
9515 nparam = isl_basic_map_n_param(bmap1);
9517 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
9518 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9519 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9520 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9521 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9522 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9523 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
9524 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
9525 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9526 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9527 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9529 bmap = isl_basic_map_alloc_space(dim_result,
9530 bmap1->n_div + bmap2->n_div,
9531 bmap1->n_eq + bmap2->n_eq,
9532 bmap1->n_ineq + bmap2->n_ineq);
9533 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9534 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9535 if (rational)
9536 bmap = isl_basic_map_set_rational(bmap);
9537 bmap = isl_basic_map_simplify(bmap);
9538 return isl_basic_map_finalize(bmap);
9539 error:
9540 isl_basic_map_free(bmap1);
9541 isl_basic_map_free(bmap2);
9542 return NULL;
9545 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
9546 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9548 isl_basic_map *prod;
9550 prod = isl_basic_map_range_product(bmap1, bmap2);
9551 prod = isl_basic_map_flatten_range(prod);
9552 return prod;
9555 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
9556 * and collect the results.
9557 * The result live in the space obtained by calling "space_product"
9558 * on the spaces of "map1" and "map2".
9559 * If "remove_duplicates" is set then the result may contain duplicates
9560 * (even if the inputs do not) and so we try and remove the obvious
9561 * duplicates.
9563 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
9564 __isl_take isl_map *map2,
9565 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
9566 __isl_take isl_space *right),
9567 __isl_give isl_basic_map *(*basic_map_product)(
9568 __isl_take isl_basic_map *left,
9569 __isl_take isl_basic_map *right),
9570 int remove_duplicates)
9572 unsigned flags = 0;
9573 struct isl_map *result;
9574 int i, j;
9576 if (!map1 || !map2)
9577 goto error;
9579 isl_assert(map1->ctx, isl_space_match(map1->dim, isl_dim_param,
9580 map2->dim, isl_dim_param), goto error);
9582 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
9583 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
9584 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
9586 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
9587 isl_space_copy(map2->dim)),
9588 map1->n * map2->n, flags);
9589 if (!result)
9590 goto error;
9591 for (i = 0; i < map1->n; ++i)
9592 for (j = 0; j < map2->n; ++j) {
9593 struct isl_basic_map *part;
9594 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
9595 isl_basic_map_copy(map2->p[j]));
9596 if (isl_basic_map_is_empty(part))
9597 isl_basic_map_free(part);
9598 else
9599 result = isl_map_add_basic_map(result, part);
9600 if (!result)
9601 goto error;
9603 if (remove_duplicates)
9604 result = isl_map_remove_obvious_duplicates(result);
9605 isl_map_free(map1);
9606 isl_map_free(map2);
9607 return result;
9608 error:
9609 isl_map_free(map1);
9610 isl_map_free(map2);
9611 return NULL;
9614 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
9616 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
9617 __isl_take isl_map *map2)
9619 return map_product(map1, map2, &isl_space_product,
9620 &isl_basic_map_product, 0);
9623 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
9624 __isl_take isl_map *map2)
9626 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
9629 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
9631 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
9632 __isl_take isl_map *map2)
9634 isl_map *prod;
9636 prod = isl_map_product(map1, map2);
9637 prod = isl_map_flatten(prod);
9638 return prod;
9641 /* Given two set A and B, construct its Cartesian product A x B.
9643 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
9645 return isl_map_range_product(set1, set2);
9648 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
9649 __isl_take isl_set *set2)
9651 return isl_map_flat_range_product(set1, set2);
9654 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
9656 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
9657 __isl_take isl_map *map2)
9659 return map_product(map1, map2, &isl_space_domain_product,
9660 &isl_basic_map_domain_product, 1);
9663 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
9665 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
9666 __isl_take isl_map *map2)
9668 return map_product(map1, map2, &isl_space_range_product,
9669 &isl_basic_map_range_product, 1);
9672 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
9673 __isl_take isl_map *map2)
9675 return isl_map_align_params_map_map_and(map1, map2,
9676 &map_domain_product_aligned);
9679 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
9680 __isl_take isl_map *map2)
9682 return isl_map_align_params_map_map_and(map1, map2,
9683 &map_range_product_aligned);
9686 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
9688 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
9690 isl_space *space;
9691 int total1, keep1, total2, keep2;
9693 if (!map)
9694 return NULL;
9695 if (!isl_space_domain_is_wrapping(map->dim) ||
9696 !isl_space_range_is_wrapping(map->dim))
9697 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9698 "not a product", return isl_map_free(map));
9700 space = isl_map_get_space(map);
9701 total1 = isl_space_dim(space, isl_dim_in);
9702 total2 = isl_space_dim(space, isl_dim_out);
9703 space = isl_space_factor_domain(space);
9704 keep1 = isl_space_dim(space, isl_dim_in);
9705 keep2 = isl_space_dim(space, isl_dim_out);
9706 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
9707 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
9708 map = isl_map_reset_space(map, space);
9710 return map;
9713 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
9715 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
9717 isl_space *space;
9718 int total1, keep1, total2, keep2;
9720 if (!map)
9721 return NULL;
9722 if (!isl_space_domain_is_wrapping(map->dim) ||
9723 !isl_space_range_is_wrapping(map->dim))
9724 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9725 "not a product", return isl_map_free(map));
9727 space = isl_map_get_space(map);
9728 total1 = isl_space_dim(space, isl_dim_in);
9729 total2 = isl_space_dim(space, isl_dim_out);
9730 space = isl_space_factor_range(space);
9731 keep1 = isl_space_dim(space, isl_dim_in);
9732 keep2 = isl_space_dim(space, isl_dim_out);
9733 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
9734 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
9735 map = isl_map_reset_space(map, space);
9737 return map;
9740 /* Given a map of the form [A -> B] -> C, return the map A -> C.
9742 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
9744 isl_space *space;
9745 int total, keep;
9747 if (!map)
9748 return NULL;
9749 if (!isl_space_domain_is_wrapping(map->dim))
9750 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9751 "domain is not a product", return isl_map_free(map));
9753 space = isl_map_get_space(map);
9754 total = isl_space_dim(space, isl_dim_in);
9755 space = isl_space_domain_factor_domain(space);
9756 keep = isl_space_dim(space, isl_dim_in);
9757 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
9758 map = isl_map_reset_space(map, space);
9760 return map;
9763 /* Given a map of the form [A -> B] -> C, return the map B -> C.
9765 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
9767 isl_space *space;
9768 int total, keep;
9770 if (!map)
9771 return NULL;
9772 if (!isl_space_domain_is_wrapping(map->dim))
9773 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9774 "domain is not a product", return isl_map_free(map));
9776 space = isl_map_get_space(map);
9777 total = isl_space_dim(space, isl_dim_in);
9778 space = isl_space_domain_factor_range(space);
9779 keep = isl_space_dim(space, isl_dim_in);
9780 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
9781 map = isl_map_reset_space(map, space);
9783 return map;
9786 /* Given a map A -> [B -> C], extract the map A -> B.
9788 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
9790 isl_space *space;
9791 int total, keep;
9793 if (!map)
9794 return NULL;
9795 if (!isl_space_range_is_wrapping(map->dim))
9796 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9797 "range is not a product", return isl_map_free(map));
9799 space = isl_map_get_space(map);
9800 total = isl_space_dim(space, isl_dim_out);
9801 space = isl_space_range_factor_domain(space);
9802 keep = isl_space_dim(space, isl_dim_out);
9803 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
9804 map = isl_map_reset_space(map, space);
9806 return map;
9809 /* Given a map A -> [B -> C], extract the map A -> C.
9811 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
9813 isl_space *space;
9814 int total, keep;
9816 if (!map)
9817 return NULL;
9818 if (!isl_space_range_is_wrapping(map->dim))
9819 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9820 "range is not a product", return isl_map_free(map));
9822 space = isl_map_get_space(map);
9823 total = isl_space_dim(space, isl_dim_out);
9824 space = isl_space_range_factor_range(space);
9825 keep = isl_space_dim(space, isl_dim_out);
9826 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
9827 map = isl_map_reset_space(map, space);
9829 return map;
9832 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
9834 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
9835 __isl_take isl_map *map2)
9837 isl_map *prod;
9839 prod = isl_map_domain_product(map1, map2);
9840 prod = isl_map_flatten_domain(prod);
9841 return prod;
9844 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
9846 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
9847 __isl_take isl_map *map2)
9849 isl_map *prod;
9851 prod = isl_map_range_product(map1, map2);
9852 prod = isl_map_flatten_range(prod);
9853 return prod;
9856 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
9858 int i;
9859 uint32_t hash = isl_hash_init();
9860 unsigned total;
9862 if (!bmap)
9863 return 0;
9864 bmap = isl_basic_map_copy(bmap);
9865 bmap = isl_basic_map_normalize(bmap);
9866 if (!bmap)
9867 return 0;
9868 total = isl_basic_map_total_dim(bmap);
9869 isl_hash_byte(hash, bmap->n_eq & 0xFF);
9870 for (i = 0; i < bmap->n_eq; ++i) {
9871 uint32_t c_hash;
9872 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
9873 isl_hash_hash(hash, c_hash);
9875 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
9876 for (i = 0; i < bmap->n_ineq; ++i) {
9877 uint32_t c_hash;
9878 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
9879 isl_hash_hash(hash, c_hash);
9881 isl_hash_byte(hash, bmap->n_div & 0xFF);
9882 for (i = 0; i < bmap->n_div; ++i) {
9883 uint32_t c_hash;
9884 if (isl_int_is_zero(bmap->div[i][0]))
9885 continue;
9886 isl_hash_byte(hash, i & 0xFF);
9887 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
9888 isl_hash_hash(hash, c_hash);
9890 isl_basic_map_free(bmap);
9891 return hash;
9894 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
9896 return isl_basic_map_get_hash(bset_to_bmap(bset));
9899 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
9901 int i;
9902 uint32_t hash;
9904 if (!map)
9905 return 0;
9906 map = isl_map_copy(map);
9907 map = isl_map_normalize(map);
9908 if (!map)
9909 return 0;
9911 hash = isl_hash_init();
9912 for (i = 0; i < map->n; ++i) {
9913 uint32_t bmap_hash;
9914 bmap_hash = isl_basic_map_get_hash(map->p[i]);
9915 isl_hash_hash(hash, bmap_hash);
9918 isl_map_free(map);
9920 return hash;
9923 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
9925 return isl_map_get_hash(set_to_map(set));
9928 /* Return the number of basic maps in the (current) representation of "map".
9930 int isl_map_n_basic_map(__isl_keep isl_map *map)
9932 return map ? map->n : 0;
9935 int isl_set_n_basic_set(__isl_keep isl_set *set)
9937 return set ? set->n : 0;
9940 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
9941 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
9943 int i;
9945 if (!map)
9946 return isl_stat_error;
9948 for (i = 0; i < map->n; ++i)
9949 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
9950 return isl_stat_error;
9952 return isl_stat_ok;
9955 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
9956 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
9958 int i;
9960 if (!set)
9961 return isl_stat_error;
9963 for (i = 0; i < set->n; ++i)
9964 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
9965 return isl_stat_error;
9967 return isl_stat_ok;
9970 /* Return a list of basic sets, the union of which is equal to "set".
9972 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
9973 __isl_keep isl_set *set)
9975 int i;
9976 isl_basic_set_list *list;
9978 if (!set)
9979 return NULL;
9981 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
9982 for (i = 0; i < set->n; ++i) {
9983 isl_basic_set *bset;
9985 bset = isl_basic_set_copy(set->p[i]);
9986 list = isl_basic_set_list_add(list, bset);
9989 return list;
9992 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
9994 isl_space *dim;
9996 if (!bset)
9997 return NULL;
9999 bset = isl_basic_set_cow(bset);
10000 if (!bset)
10001 return NULL;
10003 dim = isl_basic_set_get_space(bset);
10004 dim = isl_space_lift(dim, bset->n_div);
10005 if (!dim)
10006 goto error;
10007 isl_space_free(bset->dim);
10008 bset->dim = dim;
10009 bset->extra -= bset->n_div;
10010 bset->n_div = 0;
10012 bset = isl_basic_set_finalize(bset);
10014 return bset;
10015 error:
10016 isl_basic_set_free(bset);
10017 return NULL;
10020 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10022 int i;
10023 isl_space *dim;
10024 unsigned n_div;
10026 set = isl_set_align_divs(set);
10028 if (!set)
10029 return NULL;
10031 set = isl_set_cow(set);
10032 if (!set)
10033 return NULL;
10035 n_div = set->p[0]->n_div;
10036 dim = isl_set_get_space(set);
10037 dim = isl_space_lift(dim, n_div);
10038 if (!dim)
10039 goto error;
10040 isl_space_free(set->dim);
10041 set->dim = dim;
10043 for (i = 0; i < set->n; ++i) {
10044 set->p[i] = isl_basic_set_lift(set->p[i]);
10045 if (!set->p[i])
10046 goto error;
10049 return set;
10050 error:
10051 isl_set_free(set);
10052 return NULL;
10055 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10057 unsigned dim;
10058 int size = 0;
10060 if (!bset)
10061 return -1;
10063 dim = isl_basic_set_total_dim(bset);
10064 size += bset->n_eq * (1 + dim);
10065 size += bset->n_ineq * (1 + dim);
10066 size += bset->n_div * (2 + dim);
10068 return size;
10071 int isl_set_size(__isl_keep isl_set *set)
10073 int i;
10074 int size = 0;
10076 if (!set)
10077 return -1;
10079 for (i = 0; i < set->n; ++i)
10080 size += isl_basic_set_size(set->p[i]);
10082 return size;
10085 /* Check if there is any lower bound (if lower == 0) and/or upper
10086 * bound (if upper == 0) on the specified dim.
10088 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10089 enum isl_dim_type type, unsigned pos, int lower, int upper)
10091 int i;
10093 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10094 return isl_bool_error;
10096 pos += isl_basic_map_offset(bmap, type);
10098 for (i = 0; i < bmap->n_div; ++i) {
10099 if (isl_int_is_zero(bmap->div[i][0]))
10100 continue;
10101 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10102 return isl_bool_true;
10105 for (i = 0; i < bmap->n_eq; ++i)
10106 if (!isl_int_is_zero(bmap->eq[i][pos]))
10107 return isl_bool_true;
10109 for (i = 0; i < bmap->n_ineq; ++i) {
10110 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10111 if (sgn > 0)
10112 lower = 1;
10113 if (sgn < 0)
10114 upper = 1;
10117 return lower && upper;
10120 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10121 enum isl_dim_type type, unsigned pos)
10123 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10126 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10127 enum isl_dim_type type, unsigned pos)
10129 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10132 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10133 enum isl_dim_type type, unsigned pos)
10135 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10138 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10139 enum isl_dim_type type, unsigned pos)
10141 int i;
10143 if (!map)
10144 return isl_bool_error;
10146 for (i = 0; i < map->n; ++i) {
10147 isl_bool bounded;
10148 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10149 if (bounded < 0 || !bounded)
10150 return bounded;
10153 return isl_bool_true;
10156 /* Return true if the specified dim is involved in both an upper bound
10157 * and a lower bound.
10159 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10160 enum isl_dim_type type, unsigned pos)
10162 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10165 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10167 static isl_bool has_any_bound(__isl_keep isl_map *map,
10168 enum isl_dim_type type, unsigned pos,
10169 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10170 enum isl_dim_type type, unsigned pos))
10172 int i;
10174 if (!map)
10175 return isl_bool_error;
10177 for (i = 0; i < map->n; ++i) {
10178 isl_bool bounded;
10179 bounded = fn(map->p[i], type, pos);
10180 if (bounded < 0 || bounded)
10181 return bounded;
10184 return isl_bool_false;
10187 /* Return 1 if the specified dim is involved in any lower bound.
10189 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10190 enum isl_dim_type type, unsigned pos)
10192 return has_any_bound(set, type, pos,
10193 &isl_basic_map_dim_has_lower_bound);
10196 /* Return 1 if the specified dim is involved in any upper bound.
10198 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10199 enum isl_dim_type type, unsigned pos)
10201 return has_any_bound(set, type, pos,
10202 &isl_basic_map_dim_has_upper_bound);
10205 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10207 static isl_bool has_bound(__isl_keep isl_map *map,
10208 enum isl_dim_type type, unsigned pos,
10209 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10210 enum isl_dim_type type, unsigned pos))
10212 int i;
10214 if (!map)
10215 return isl_bool_error;
10217 for (i = 0; i < map->n; ++i) {
10218 isl_bool bounded;
10219 bounded = fn(map->p[i], type, pos);
10220 if (bounded < 0 || !bounded)
10221 return bounded;
10224 return isl_bool_true;
10227 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10229 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10230 enum isl_dim_type type, unsigned pos)
10232 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10235 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10237 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10238 enum isl_dim_type type, unsigned pos)
10240 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10243 /* For each of the "n" variables starting at "first", determine
10244 * the sign of the variable and put the results in the first "n"
10245 * elements of the array "signs".
10246 * Sign
10247 * 1 means that the variable is non-negative
10248 * -1 means that the variable is non-positive
10249 * 0 means the variable attains both positive and negative values.
10251 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10252 unsigned first, unsigned n, int *signs)
10254 isl_vec *bound = NULL;
10255 struct isl_tab *tab = NULL;
10256 struct isl_tab_undo *snap;
10257 int i;
10259 if (!bset || !signs)
10260 return isl_stat_error;
10262 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10263 tab = isl_tab_from_basic_set(bset, 0);
10264 if (!bound || !tab)
10265 goto error;
10267 isl_seq_clr(bound->el, bound->size);
10268 isl_int_set_si(bound->el[0], -1);
10270 snap = isl_tab_snap(tab);
10271 for (i = 0; i < n; ++i) {
10272 int empty;
10274 isl_int_set_si(bound->el[1 + first + i], -1);
10275 if (isl_tab_add_ineq(tab, bound->el) < 0)
10276 goto error;
10277 empty = tab->empty;
10278 isl_int_set_si(bound->el[1 + first + i], 0);
10279 if (isl_tab_rollback(tab, snap) < 0)
10280 goto error;
10282 if (empty) {
10283 signs[i] = 1;
10284 continue;
10287 isl_int_set_si(bound->el[1 + first + i], 1);
10288 if (isl_tab_add_ineq(tab, bound->el) < 0)
10289 goto error;
10290 empty = tab->empty;
10291 isl_int_set_si(bound->el[1 + first + i], 0);
10292 if (isl_tab_rollback(tab, snap) < 0)
10293 goto error;
10295 signs[i] = empty ? -1 : 0;
10298 isl_tab_free(tab);
10299 isl_vec_free(bound);
10300 return isl_stat_ok;
10301 error:
10302 isl_tab_free(tab);
10303 isl_vec_free(bound);
10304 return isl_stat_error;
10307 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10308 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10310 if (!bset || !signs)
10311 return isl_stat_error;
10312 isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
10313 return isl_stat_error);
10315 first += pos(bset->dim, type) - 1;
10316 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10319 /* Is it possible for the integer division "div" to depend (possibly
10320 * indirectly) on any output dimensions?
10322 * If the div is undefined, then we conservatively assume that it
10323 * may depend on them.
10324 * Otherwise, we check if it actually depends on them or on any integer
10325 * divisions that may depend on them.
10327 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10329 int i;
10330 unsigned n_out, o_out;
10331 unsigned n_div, o_div;
10333 if (isl_int_is_zero(bmap->div[div][0]))
10334 return isl_bool_true;
10336 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10337 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10339 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10340 return isl_bool_true;
10342 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10343 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10345 for (i = 0; i < n_div; ++i) {
10346 isl_bool may_involve;
10348 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10349 continue;
10350 may_involve = div_may_involve_output(bmap, i);
10351 if (may_involve < 0 || may_involve)
10352 return may_involve;
10355 return isl_bool_false;
10358 /* Return the first integer division of "bmap" in the range
10359 * [first, first + n[ that may depend on any output dimensions and
10360 * that has a non-zero coefficient in "c" (where the first coefficient
10361 * in "c" corresponds to integer division "first").
10363 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10364 isl_int *c, int first, int n)
10366 int k;
10368 if (!bmap)
10369 return -1;
10371 for (k = first; k < first + n; ++k) {
10372 isl_bool may_involve;
10374 if (isl_int_is_zero(c[k]))
10375 continue;
10376 may_involve = div_may_involve_output(bmap, k);
10377 if (may_involve < 0)
10378 return -1;
10379 if (may_involve)
10380 return k;
10383 return first + n;
10386 /* Look for a pair of inequality constraints in "bmap" of the form
10388 * -l + i >= 0 or i >= l
10389 * and
10390 * n + l - i >= 0 or i <= l + n
10392 * with n < "m" and i the output dimension at position "pos".
10393 * (Note that n >= 0 as otherwise the two constraints would conflict.)
10394 * Furthermore, "l" is only allowed to involve parameters, input dimensions
10395 * and earlier output dimensions, as well as integer divisions that do
10396 * not involve any of the output dimensions.
10398 * Return the index of the first inequality constraint or bmap->n_ineq
10399 * if no such pair can be found.
10401 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10402 int pos, isl_int m)
10404 int i, j;
10405 isl_ctx *ctx;
10406 unsigned total;
10407 unsigned n_div, o_div;
10408 unsigned n_out, o_out;
10409 int less;
10411 if (!bmap)
10412 return -1;
10414 ctx = isl_basic_map_get_ctx(bmap);
10415 total = isl_basic_map_total_dim(bmap);
10416 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10417 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10418 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10419 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10420 for (i = 0; i < bmap->n_ineq; ++i) {
10421 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
10422 continue;
10423 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
10424 n_out - (pos + 1)) != -1)
10425 continue;
10426 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
10427 0, n_div) < n_div)
10428 continue;
10429 for (j = i + 1; j < bmap->n_ineq; ++j) {
10430 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
10431 ctx->one))
10432 continue;
10433 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
10434 bmap->ineq[j] + 1, total))
10435 continue;
10436 break;
10438 if (j >= bmap->n_ineq)
10439 continue;
10440 isl_int_add(bmap->ineq[i][0],
10441 bmap->ineq[i][0], bmap->ineq[j][0]);
10442 less = isl_int_abs_lt(bmap->ineq[i][0], m);
10443 isl_int_sub(bmap->ineq[i][0],
10444 bmap->ineq[i][0], bmap->ineq[j][0]);
10445 if (!less)
10446 continue;
10447 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
10448 return i;
10449 else
10450 return j;
10453 return bmap->n_ineq;
10456 /* Return the index of the equality of "bmap" that defines
10457 * the output dimension "pos" in terms of earlier dimensions.
10458 * The equality may also involve integer divisions, as long
10459 * as those integer divisions are defined in terms of
10460 * parameters or input dimensions.
10461 * In this case, *div is set to the number of integer divisions and
10462 * *ineq is set to the number of inequality constraints (provided
10463 * div and ineq are not NULL).
10465 * The equality may also involve a single integer division involving
10466 * the output dimensions (typically only output dimension "pos") as
10467 * long as the coefficient of output dimension "pos" is 1 or -1 and
10468 * there is a pair of constraints i >= l and i <= l + n, with i referring
10469 * to output dimension "pos", l an expression involving only earlier
10470 * dimensions and n smaller than the coefficient of the integer division
10471 * in the equality. In this case, the output dimension can be defined
10472 * in terms of a modulo expression that does not involve the integer division.
10473 * *div is then set to this single integer division and
10474 * *ineq is set to the index of constraint i >= l.
10476 * Return bmap->n_eq if there is no such equality.
10477 * Return -1 on error.
10479 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
10480 int pos, int *div, int *ineq)
10482 int j, k, l;
10483 unsigned n_out, o_out;
10484 unsigned n_div, o_div;
10486 if (!bmap)
10487 return -1;
10489 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10490 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10491 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10492 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10494 if (ineq)
10495 *ineq = bmap->n_ineq;
10496 if (div)
10497 *div = n_div;
10498 for (j = 0; j < bmap->n_eq; ++j) {
10499 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
10500 continue;
10501 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
10502 n_out - (pos + 1)) != -1)
10503 continue;
10504 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10505 0, n_div);
10506 if (k >= n_div)
10507 return j;
10508 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
10509 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
10510 continue;
10511 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10512 k + 1, n_div - (k+1)) < n_div)
10513 continue;
10514 l = find_modulo_constraint_pair(bmap, pos,
10515 bmap->eq[j][o_div + k]);
10516 if (l < 0)
10517 return -1;
10518 if (l >= bmap->n_ineq)
10519 continue;
10520 if (div)
10521 *div = k;
10522 if (ineq)
10523 *ineq = l;
10524 return j;
10527 return bmap->n_eq;
10530 /* Check if the given basic map is obviously single-valued.
10531 * In particular, for each output dimension, check that there is
10532 * an equality that defines the output dimension in terms of
10533 * earlier dimensions.
10535 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
10537 int i;
10538 unsigned n_out;
10540 if (!bmap)
10541 return isl_bool_error;
10543 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10545 for (i = 0; i < n_out; ++i) {
10546 int eq;
10548 eq = isl_basic_map_output_defining_equality(bmap, i,
10549 NULL, NULL);
10550 if (eq < 0)
10551 return isl_bool_error;
10552 if (eq >= bmap->n_eq)
10553 return isl_bool_false;
10556 return isl_bool_true;
10559 /* Check if the given basic map is single-valued.
10560 * We simply compute
10562 * M \circ M^-1
10564 * and check if the result is a subset of the identity mapping.
10566 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
10568 isl_space *space;
10569 isl_basic_map *test;
10570 isl_basic_map *id;
10571 isl_bool sv;
10573 sv = isl_basic_map_plain_is_single_valued(bmap);
10574 if (sv < 0 || sv)
10575 return sv;
10577 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
10578 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
10580 space = isl_basic_map_get_space(bmap);
10581 space = isl_space_map_from_set(isl_space_range(space));
10582 id = isl_basic_map_identity(space);
10584 sv = isl_basic_map_is_subset(test, id);
10586 isl_basic_map_free(test);
10587 isl_basic_map_free(id);
10589 return sv;
10592 /* Check if the given map is obviously single-valued.
10594 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
10596 if (!map)
10597 return isl_bool_error;
10598 if (map->n == 0)
10599 return isl_bool_true;
10600 if (map->n >= 2)
10601 return isl_bool_false;
10603 return isl_basic_map_plain_is_single_valued(map->p[0]);
10606 /* Check if the given map is single-valued.
10607 * We simply compute
10609 * M \circ M^-1
10611 * and check if the result is a subset of the identity mapping.
10613 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
10615 isl_space *dim;
10616 isl_map *test;
10617 isl_map *id;
10618 isl_bool sv;
10620 sv = isl_map_plain_is_single_valued(map);
10621 if (sv < 0 || sv)
10622 return sv;
10624 test = isl_map_reverse(isl_map_copy(map));
10625 test = isl_map_apply_range(test, isl_map_copy(map));
10627 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
10628 id = isl_map_identity(dim);
10630 sv = isl_map_is_subset(test, id);
10632 isl_map_free(test);
10633 isl_map_free(id);
10635 return sv;
10638 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
10640 isl_bool in;
10642 map = isl_map_copy(map);
10643 map = isl_map_reverse(map);
10644 in = isl_map_is_single_valued(map);
10645 isl_map_free(map);
10647 return in;
10650 /* Check if the given map is obviously injective.
10652 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
10654 isl_bool in;
10656 map = isl_map_copy(map);
10657 map = isl_map_reverse(map);
10658 in = isl_map_plain_is_single_valued(map);
10659 isl_map_free(map);
10661 return in;
10664 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
10666 isl_bool sv;
10668 sv = isl_map_is_single_valued(map);
10669 if (sv < 0 || !sv)
10670 return sv;
10672 return isl_map_is_injective(map);
10675 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
10677 return isl_map_is_single_valued(set_to_map(set));
10680 /* Does "map" only map elements to themselves?
10682 * If the domain and range spaces are different, then "map"
10683 * is considered not to be an identity relation, even if it is empty.
10684 * Otherwise, construct the maximal identity relation and
10685 * check whether "map" is a subset of this relation.
10687 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
10689 isl_space *space;
10690 isl_map *id;
10691 isl_bool equal, is_identity;
10693 space = isl_map_get_space(map);
10694 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
10695 isl_space_free(space);
10696 if (equal < 0 || !equal)
10697 return equal;
10699 id = isl_map_identity(isl_map_get_space(map));
10700 is_identity = isl_map_is_subset(map, id);
10701 isl_map_free(id);
10703 return is_identity;
10706 int isl_map_is_translation(__isl_keep isl_map *map)
10708 int ok;
10709 isl_set *delta;
10711 delta = isl_map_deltas(isl_map_copy(map));
10712 ok = isl_set_is_singleton(delta);
10713 isl_set_free(delta);
10715 return ok;
10718 static int unique(isl_int *p, unsigned pos, unsigned len)
10720 if (isl_seq_first_non_zero(p, pos) != -1)
10721 return 0;
10722 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
10723 return 0;
10724 return 1;
10727 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
10729 int i, j;
10730 unsigned nvar;
10731 unsigned ovar;
10733 if (!bset)
10734 return isl_bool_error;
10736 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
10737 return isl_bool_false;
10739 nvar = isl_basic_set_dim(bset, isl_dim_set);
10740 ovar = isl_space_offset(bset->dim, isl_dim_set);
10741 for (j = 0; j < nvar; ++j) {
10742 int lower = 0, upper = 0;
10743 for (i = 0; i < bset->n_eq; ++i) {
10744 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
10745 continue;
10746 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
10747 return isl_bool_false;
10748 break;
10750 if (i < bset->n_eq)
10751 continue;
10752 for (i = 0; i < bset->n_ineq; ++i) {
10753 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
10754 continue;
10755 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
10756 return isl_bool_false;
10757 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
10758 lower = 1;
10759 else
10760 upper = 1;
10762 if (!lower || !upper)
10763 return isl_bool_false;
10766 return isl_bool_true;
10769 isl_bool isl_set_is_box(__isl_keep isl_set *set)
10771 if (!set)
10772 return isl_bool_error;
10773 if (set->n != 1)
10774 return isl_bool_false;
10776 return isl_basic_set_is_box(set->p[0]);
10779 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
10781 if (!bset)
10782 return isl_bool_error;
10784 return isl_space_is_wrapping(bset->dim);
10787 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
10789 if (!set)
10790 return isl_bool_error;
10792 return isl_space_is_wrapping(set->dim);
10795 /* Modify the space of "map" through a call to "change".
10796 * If "can_change" is set (not NULL), then first call it to check
10797 * if the modification is allowed, printing the error message "cannot_change"
10798 * if it is not.
10800 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
10801 isl_bool (*can_change)(__isl_keep isl_map *map),
10802 const char *cannot_change,
10803 __isl_give isl_space *(*change)(__isl_take isl_space *space))
10805 isl_bool ok;
10806 isl_space *space;
10808 if (!map)
10809 return NULL;
10811 ok = can_change ? can_change(map) : isl_bool_true;
10812 if (ok < 0)
10813 return isl_map_free(map);
10814 if (!ok)
10815 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
10816 return isl_map_free(map));
10818 space = change(isl_map_get_space(map));
10819 map = isl_map_reset_space(map, space);
10821 return map;
10824 /* Is the domain of "map" a wrapped relation?
10826 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
10828 if (!map)
10829 return isl_bool_error;
10831 return isl_space_domain_is_wrapping(map->dim);
10834 /* Is the range of "map" a wrapped relation?
10836 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
10838 if (!map)
10839 return isl_bool_error;
10841 return isl_space_range_is_wrapping(map->dim);
10844 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
10846 bmap = isl_basic_map_cow(bmap);
10847 if (!bmap)
10848 return NULL;
10850 bmap->dim = isl_space_wrap(bmap->dim);
10851 if (!bmap->dim)
10852 goto error;
10854 bmap = isl_basic_map_finalize(bmap);
10856 return bset_from_bmap(bmap);
10857 error:
10858 isl_basic_map_free(bmap);
10859 return NULL;
10862 /* Given a map A -> B, return the set (A -> B).
10864 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
10866 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
10869 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
10871 bset = isl_basic_set_cow(bset);
10872 if (!bset)
10873 return NULL;
10875 bset->dim = isl_space_unwrap(bset->dim);
10876 if (!bset->dim)
10877 goto error;
10879 bset = isl_basic_set_finalize(bset);
10881 return bset_to_bmap(bset);
10882 error:
10883 isl_basic_set_free(bset);
10884 return NULL;
10887 /* Given a set (A -> B), return the map A -> B.
10888 * Error out if "set" is not of the form (A -> B).
10890 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
10892 return isl_map_change_space(set, &isl_set_is_wrapping,
10893 "not a wrapping set", &isl_space_unwrap);
10896 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
10897 enum isl_dim_type type)
10899 if (!bmap)
10900 return NULL;
10902 if (!isl_space_is_named_or_nested(bmap->dim, type))
10903 return bmap;
10905 bmap = isl_basic_map_cow(bmap);
10906 if (!bmap)
10907 return NULL;
10909 bmap->dim = isl_space_reset(bmap->dim, type);
10910 if (!bmap->dim)
10911 goto error;
10913 bmap = isl_basic_map_finalize(bmap);
10915 return bmap;
10916 error:
10917 isl_basic_map_free(bmap);
10918 return NULL;
10921 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
10922 enum isl_dim_type type)
10924 int i;
10926 if (!map)
10927 return NULL;
10929 if (!isl_space_is_named_or_nested(map->dim, type))
10930 return map;
10932 map = isl_map_cow(map);
10933 if (!map)
10934 return NULL;
10936 for (i = 0; i < map->n; ++i) {
10937 map->p[i] = isl_basic_map_reset(map->p[i], type);
10938 if (!map->p[i])
10939 goto error;
10941 map->dim = isl_space_reset(map->dim, type);
10942 if (!map->dim)
10943 goto error;
10945 return map;
10946 error:
10947 isl_map_free(map);
10948 return NULL;
10951 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
10953 if (!bmap)
10954 return NULL;
10956 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
10957 return bmap;
10959 bmap = isl_basic_map_cow(bmap);
10960 if (!bmap)
10961 return NULL;
10963 bmap->dim = isl_space_flatten(bmap->dim);
10964 if (!bmap->dim)
10965 goto error;
10967 bmap = isl_basic_map_finalize(bmap);
10969 return bmap;
10970 error:
10971 isl_basic_map_free(bmap);
10972 return NULL;
10975 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
10977 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
10980 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
10981 __isl_take isl_basic_map *bmap)
10983 if (!bmap)
10984 return NULL;
10986 if (!bmap->dim->nested[0])
10987 return bmap;
10989 bmap = isl_basic_map_cow(bmap);
10990 if (!bmap)
10991 return NULL;
10993 bmap->dim = isl_space_flatten_domain(bmap->dim);
10994 if (!bmap->dim)
10995 goto error;
10997 bmap = isl_basic_map_finalize(bmap);
10999 return bmap;
11000 error:
11001 isl_basic_map_free(bmap);
11002 return NULL;
11005 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11006 __isl_take isl_basic_map *bmap)
11008 if (!bmap)
11009 return NULL;
11011 if (!bmap->dim->nested[1])
11012 return bmap;
11014 bmap = isl_basic_map_cow(bmap);
11015 if (!bmap)
11016 return NULL;
11018 bmap->dim = isl_space_flatten_range(bmap->dim);
11019 if (!bmap->dim)
11020 goto error;
11022 bmap = isl_basic_map_finalize(bmap);
11024 return bmap;
11025 error:
11026 isl_basic_map_free(bmap);
11027 return NULL;
11030 /* Remove any internal structure from the spaces of domain and range of "map".
11032 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11034 if (!map)
11035 return NULL;
11037 if (!map->dim->nested[0] && !map->dim->nested[1])
11038 return map;
11040 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11043 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11045 return set_from_map(isl_map_flatten(set_to_map(set)));
11048 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11050 isl_space *dim, *flat_dim;
11051 isl_map *map;
11053 dim = isl_set_get_space(set);
11054 flat_dim = isl_space_flatten(isl_space_copy(dim));
11055 map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
11056 map = isl_map_intersect_domain(map, set);
11058 return map;
11061 /* Remove any internal structure from the space of the domain of "map".
11063 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11065 if (!map)
11066 return NULL;
11068 if (!map->dim->nested[0])
11069 return map;
11071 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11074 /* Remove any internal structure from the space of the range of "map".
11076 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11078 if (!map)
11079 return NULL;
11081 if (!map->dim->nested[1])
11082 return map;
11084 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11087 /* Reorder the dimensions of "bmap" according to the given dim_map
11088 * and set the dimension specification to "dim" and
11089 * perform Gaussian elimination on the result.
11091 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11092 __isl_take isl_space *dim, __isl_take struct isl_dim_map *dim_map)
11094 isl_basic_map *res;
11095 unsigned flags;
11097 bmap = isl_basic_map_cow(bmap);
11098 if (!bmap || !dim || !dim_map)
11099 goto error;
11101 flags = bmap->flags;
11102 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11103 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
11104 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11105 res = isl_basic_map_alloc_space(dim,
11106 bmap->n_div, bmap->n_eq, bmap->n_ineq);
11107 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11108 if (res)
11109 res->flags = flags;
11110 res = isl_basic_map_gauss(res, NULL);
11111 res = isl_basic_map_finalize(res);
11112 return res;
11113 error:
11114 free(dim_map);
11115 isl_basic_map_free(bmap);
11116 isl_space_free(dim);
11117 return NULL;
11120 /* Reorder the dimensions of "map" according to given reordering.
11122 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11123 __isl_take isl_reordering *r)
11125 int i;
11126 struct isl_dim_map *dim_map;
11128 map = isl_map_cow(map);
11129 dim_map = isl_dim_map_from_reordering(r);
11130 if (!map || !r || !dim_map)
11131 goto error;
11133 for (i = 0; i < map->n; ++i) {
11134 struct isl_dim_map *dim_map_i;
11136 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11138 map->p[i] = isl_basic_map_realign(map->p[i],
11139 isl_space_copy(r->dim), dim_map_i);
11141 if (!map->p[i])
11142 goto error;
11145 map = isl_map_reset_space(map, isl_space_copy(r->dim));
11147 isl_reordering_free(r);
11148 free(dim_map);
11149 return map;
11150 error:
11151 free(dim_map);
11152 isl_map_free(map);
11153 isl_reordering_free(r);
11154 return NULL;
11157 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11158 __isl_take isl_reordering *r)
11160 return set_from_map(isl_map_realign(set_to_map(set), r));
11163 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11164 __isl_take isl_space *model)
11166 isl_ctx *ctx;
11168 if (!map || !model)
11169 goto error;
11171 ctx = isl_space_get_ctx(model);
11172 if (!isl_space_has_named_params(model))
11173 isl_die(ctx, isl_error_invalid,
11174 "model has unnamed parameters", goto error);
11175 if (isl_map_check_named_params(map) < 0)
11176 goto error;
11177 if (!isl_space_match(map->dim, isl_dim_param, model, isl_dim_param)) {
11178 isl_reordering *exp;
11180 model = isl_space_drop_dims(model, isl_dim_in,
11181 0, isl_space_dim(model, isl_dim_in));
11182 model = isl_space_drop_dims(model, isl_dim_out,
11183 0, isl_space_dim(model, isl_dim_out));
11184 exp = isl_parameter_alignment_reordering(map->dim, model);
11185 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11186 map = isl_map_realign(map, exp);
11189 isl_space_free(model);
11190 return map;
11191 error:
11192 isl_space_free(model);
11193 isl_map_free(map);
11194 return NULL;
11197 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11198 __isl_take isl_space *model)
11200 return isl_map_align_params(set, model);
11203 /* Align the parameters of "bmap" to those of "model", introducing
11204 * additional parameters if needed.
11206 __isl_give isl_basic_map *isl_basic_map_align_params(
11207 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11209 isl_ctx *ctx;
11211 if (!bmap || !model)
11212 goto error;
11214 ctx = isl_space_get_ctx(model);
11215 if (!isl_space_has_named_params(model))
11216 isl_die(ctx, isl_error_invalid,
11217 "model has unnamed parameters", goto error);
11218 if (!isl_space_has_named_params(bmap->dim))
11219 isl_die(ctx, isl_error_invalid,
11220 "relation has unnamed parameters", goto error);
11221 if (!isl_space_match(bmap->dim, isl_dim_param, model, isl_dim_param)) {
11222 isl_reordering *exp;
11223 struct isl_dim_map *dim_map;
11225 model = isl_space_drop_dims(model, isl_dim_in,
11226 0, isl_space_dim(model, isl_dim_in));
11227 model = isl_space_drop_dims(model, isl_dim_out,
11228 0, isl_space_dim(model, isl_dim_out));
11229 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11230 exp = isl_reordering_extend_space(exp,
11231 isl_basic_map_get_space(bmap));
11232 dim_map = isl_dim_map_from_reordering(exp);
11233 bmap = isl_basic_map_realign(bmap,
11234 exp ? isl_space_copy(exp->dim) : NULL,
11235 isl_dim_map_extend(dim_map, bmap));
11236 isl_reordering_free(exp);
11237 free(dim_map);
11240 isl_space_free(model);
11241 return bmap;
11242 error:
11243 isl_space_free(model);
11244 isl_basic_map_free(bmap);
11245 return NULL;
11248 /* Align the parameters of "bset" to those of "model", introducing
11249 * additional parameters if needed.
11251 __isl_give isl_basic_set *isl_basic_set_align_params(
11252 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11254 return isl_basic_map_align_params(bset, model);
11257 __isl_give isl_mat *isl_basic_map_equalities_matrix(
11258 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11259 enum isl_dim_type c2, enum isl_dim_type c3,
11260 enum isl_dim_type c4, enum isl_dim_type c5)
11262 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11263 struct isl_mat *mat;
11264 int i, j, k;
11265 int pos;
11267 if (!bmap)
11268 return NULL;
11269 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11270 isl_basic_map_total_dim(bmap) + 1);
11271 if (!mat)
11272 return NULL;
11273 for (i = 0; i < bmap->n_eq; ++i)
11274 for (j = 0, pos = 0; j < 5; ++j) {
11275 int off = isl_basic_map_offset(bmap, c[j]);
11276 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11277 isl_int_set(mat->row[i][pos],
11278 bmap->eq[i][off + k]);
11279 ++pos;
11283 return mat;
11286 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11287 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11288 enum isl_dim_type c2, enum isl_dim_type c3,
11289 enum isl_dim_type c4, enum isl_dim_type c5)
11291 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11292 struct isl_mat *mat;
11293 int i, j, k;
11294 int pos;
11296 if (!bmap)
11297 return NULL;
11298 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11299 isl_basic_map_total_dim(bmap) + 1);
11300 if (!mat)
11301 return NULL;
11302 for (i = 0; i < bmap->n_ineq; ++i)
11303 for (j = 0, pos = 0; j < 5; ++j) {
11304 int off = isl_basic_map_offset(bmap, c[j]);
11305 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11306 isl_int_set(mat->row[i][pos],
11307 bmap->ineq[i][off + k]);
11308 ++pos;
11312 return mat;
11315 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11316 __isl_take isl_space *dim,
11317 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11318 enum isl_dim_type c2, enum isl_dim_type c3,
11319 enum isl_dim_type c4, enum isl_dim_type c5)
11321 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11322 isl_basic_map *bmap;
11323 unsigned total;
11324 unsigned extra;
11325 int i, j, k, l;
11326 int pos;
11328 if (!dim || !eq || !ineq)
11329 goto error;
11331 if (eq->n_col != ineq->n_col)
11332 isl_die(dim->ctx, isl_error_invalid,
11333 "equalities and inequalities matrices should have "
11334 "same number of columns", goto error);
11336 total = 1 + isl_space_dim(dim, isl_dim_all);
11338 if (eq->n_col < total)
11339 isl_die(dim->ctx, isl_error_invalid,
11340 "number of columns too small", goto error);
11342 extra = eq->n_col - total;
11344 bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
11345 eq->n_row, ineq->n_row);
11346 if (!bmap)
11347 goto error;
11348 for (i = 0; i < extra; ++i) {
11349 k = isl_basic_map_alloc_div(bmap);
11350 if (k < 0)
11351 goto error;
11352 isl_int_set_si(bmap->div[k][0], 0);
11354 for (i = 0; i < eq->n_row; ++i) {
11355 l = isl_basic_map_alloc_equality(bmap);
11356 if (l < 0)
11357 goto error;
11358 for (j = 0, pos = 0; j < 5; ++j) {
11359 int off = isl_basic_map_offset(bmap, c[j]);
11360 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11361 isl_int_set(bmap->eq[l][off + k],
11362 eq->row[i][pos]);
11363 ++pos;
11367 for (i = 0; i < ineq->n_row; ++i) {
11368 l = isl_basic_map_alloc_inequality(bmap);
11369 if (l < 0)
11370 goto error;
11371 for (j = 0, pos = 0; j < 5; ++j) {
11372 int off = isl_basic_map_offset(bmap, c[j]);
11373 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11374 isl_int_set(bmap->ineq[l][off + k],
11375 ineq->row[i][pos]);
11376 ++pos;
11381 isl_space_free(dim);
11382 isl_mat_free(eq);
11383 isl_mat_free(ineq);
11385 bmap = isl_basic_map_simplify(bmap);
11386 return isl_basic_map_finalize(bmap);
11387 error:
11388 isl_space_free(dim);
11389 isl_mat_free(eq);
11390 isl_mat_free(ineq);
11391 return NULL;
11394 __isl_give isl_mat *isl_basic_set_equalities_matrix(
11395 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11396 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11398 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
11399 c1, c2, c3, c4, isl_dim_in);
11402 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
11403 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11404 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11406 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
11407 c1, c2, c3, c4, isl_dim_in);
11410 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
11411 __isl_take isl_space *dim,
11412 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11413 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11415 isl_basic_map *bmap;
11416 bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
11417 c1, c2, c3, c4, isl_dim_in);
11418 return bset_from_bmap(bmap);
11421 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
11423 if (!bmap)
11424 return isl_bool_error;
11426 return isl_space_can_zip(bmap->dim);
11429 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
11431 if (!map)
11432 return isl_bool_error;
11434 return isl_space_can_zip(map->dim);
11437 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
11438 * (A -> C) -> (B -> D).
11440 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
11442 unsigned pos;
11443 unsigned n1;
11444 unsigned n2;
11446 if (!bmap)
11447 return NULL;
11449 if (!isl_basic_map_can_zip(bmap))
11450 isl_die(bmap->ctx, isl_error_invalid,
11451 "basic map cannot be zipped", goto error);
11452 pos = isl_basic_map_offset(bmap, isl_dim_in) +
11453 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
11454 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
11455 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
11456 bmap = isl_basic_map_cow(bmap);
11457 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
11458 if (!bmap)
11459 return NULL;
11460 bmap->dim = isl_space_zip(bmap->dim);
11461 if (!bmap->dim)
11462 goto error;
11463 bmap = isl_basic_map_mark_final(bmap);
11464 return bmap;
11465 error:
11466 isl_basic_map_free(bmap);
11467 return NULL;
11470 /* Given a map (A -> B) -> (C -> D), return the corresponding map
11471 * (A -> C) -> (B -> D).
11473 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
11475 int i;
11477 if (!map)
11478 return NULL;
11480 if (!isl_map_can_zip(map))
11481 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
11482 goto error);
11484 map = isl_map_cow(map);
11485 if (!map)
11486 return NULL;
11488 for (i = 0; i < map->n; ++i) {
11489 map->p[i] = isl_basic_map_zip(map->p[i]);
11490 if (!map->p[i])
11491 goto error;
11494 map->dim = isl_space_zip(map->dim);
11495 if (!map->dim)
11496 goto error;
11498 return map;
11499 error:
11500 isl_map_free(map);
11501 return NULL;
11504 /* Can we apply isl_basic_map_curry to "bmap"?
11505 * That is, does it have a nested relation in its domain?
11507 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
11509 if (!bmap)
11510 return isl_bool_error;
11512 return isl_space_can_curry(bmap->dim);
11515 /* Can we apply isl_map_curry to "map"?
11516 * That is, does it have a nested relation in its domain?
11518 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
11520 if (!map)
11521 return isl_bool_error;
11523 return isl_space_can_curry(map->dim);
11526 /* Given a basic map (A -> B) -> C, return the corresponding basic map
11527 * A -> (B -> C).
11529 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
11532 if (!bmap)
11533 return NULL;
11535 if (!isl_basic_map_can_curry(bmap))
11536 isl_die(bmap->ctx, isl_error_invalid,
11537 "basic map cannot be curried", goto error);
11538 bmap = isl_basic_map_cow(bmap);
11539 if (!bmap)
11540 return NULL;
11541 bmap->dim = isl_space_curry(bmap->dim);
11542 if (!bmap->dim)
11543 goto error;
11544 bmap = isl_basic_map_mark_final(bmap);
11545 return bmap;
11546 error:
11547 isl_basic_map_free(bmap);
11548 return NULL;
11551 /* Given a map (A -> B) -> C, return the corresponding map
11552 * A -> (B -> C).
11554 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
11556 return isl_map_change_space(map, &isl_map_can_curry,
11557 "map cannot be curried", &isl_space_curry);
11560 /* Can isl_map_range_curry be applied to "map"?
11561 * That is, does it have a nested relation in its range,
11562 * the domain of which is itself a nested relation?
11564 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
11566 if (!map)
11567 return isl_bool_error;
11569 return isl_space_can_range_curry(map->dim);
11572 /* Given a map A -> ((B -> C) -> D), return the corresponding map
11573 * A -> (B -> (C -> D)).
11575 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
11577 return isl_map_change_space(map, &isl_map_can_range_curry,
11578 "map range cannot be curried",
11579 &isl_space_range_curry);
11582 /* Can we apply isl_basic_map_uncurry to "bmap"?
11583 * That is, does it have a nested relation in its domain?
11585 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
11587 if (!bmap)
11588 return isl_bool_error;
11590 return isl_space_can_uncurry(bmap->dim);
11593 /* Can we apply isl_map_uncurry to "map"?
11594 * That is, does it have a nested relation in its domain?
11596 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
11598 if (!map)
11599 return isl_bool_error;
11601 return isl_space_can_uncurry(map->dim);
11604 /* Given a basic map A -> (B -> C), return the corresponding basic map
11605 * (A -> B) -> C.
11607 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
11610 if (!bmap)
11611 return NULL;
11613 if (!isl_basic_map_can_uncurry(bmap))
11614 isl_die(bmap->ctx, isl_error_invalid,
11615 "basic map cannot be uncurried",
11616 return isl_basic_map_free(bmap));
11617 bmap = isl_basic_map_cow(bmap);
11618 if (!bmap)
11619 return NULL;
11620 bmap->dim = isl_space_uncurry(bmap->dim);
11621 if (!bmap->dim)
11622 return isl_basic_map_free(bmap);
11623 bmap = isl_basic_map_mark_final(bmap);
11624 return bmap;
11627 /* Given a map A -> (B -> C), return the corresponding map
11628 * (A -> B) -> C.
11630 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
11632 return isl_map_change_space(map, &isl_map_can_uncurry,
11633 "map cannot be uncurried", &isl_space_uncurry);
11636 /* Construct a basic map mapping the domain of the affine expression
11637 * to a one-dimensional range prescribed by the affine expression.
11638 * If "rational" is set, then construct a rational basic map.
11640 * A NaN affine expression cannot be converted to a basic map.
11642 static __isl_give isl_basic_map *isl_basic_map_from_aff2(
11643 __isl_take isl_aff *aff, int rational)
11645 int k;
11646 int pos;
11647 isl_bool is_nan;
11648 isl_local_space *ls;
11649 isl_basic_map *bmap = NULL;
11651 if (!aff)
11652 return NULL;
11653 is_nan = isl_aff_is_nan(aff);
11654 if (is_nan < 0)
11655 goto error;
11656 if (is_nan)
11657 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
11658 "cannot convert NaN", goto error);
11660 ls = isl_aff_get_local_space(aff);
11661 bmap = isl_basic_map_from_local_space(ls);
11662 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
11663 k = isl_basic_map_alloc_equality(bmap);
11664 if (k < 0)
11665 goto error;
11667 pos = isl_basic_map_offset(bmap, isl_dim_out);
11668 isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos);
11669 isl_int_neg(bmap->eq[k][pos], aff->v->el[0]);
11670 isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos,
11671 aff->v->size - (pos + 1));
11673 isl_aff_free(aff);
11674 if (rational)
11675 bmap = isl_basic_map_set_rational(bmap);
11676 bmap = isl_basic_map_finalize(bmap);
11677 return bmap;
11678 error:
11679 isl_aff_free(aff);
11680 isl_basic_map_free(bmap);
11681 return NULL;
11684 /* Construct a basic map mapping the domain of the affine expression
11685 * to a one-dimensional range prescribed by the affine expression.
11687 __isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff)
11689 return isl_basic_map_from_aff2(aff, 0);
11692 /* Construct a map mapping the domain of the affine expression
11693 * to a one-dimensional range prescribed by the affine expression.
11695 __isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff)
11697 isl_basic_map *bmap;
11699 bmap = isl_basic_map_from_aff(aff);
11700 return isl_map_from_basic_map(bmap);
11703 /* Construct a basic map mapping the domain the multi-affine expression
11704 * to its range, with each dimension in the range equated to the
11705 * corresponding affine expression.
11706 * If "rational" is set, then construct a rational basic map.
11708 __isl_give isl_basic_map *isl_basic_map_from_multi_aff2(
11709 __isl_take isl_multi_aff *maff, int rational)
11711 int i;
11712 isl_space *space;
11713 isl_basic_map *bmap;
11715 if (!maff)
11716 return NULL;
11718 if (isl_space_dim(maff->space, isl_dim_out) != maff->n)
11719 isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal,
11720 "invalid space", goto error);
11722 space = isl_space_domain(isl_multi_aff_get_space(maff));
11723 bmap = isl_basic_map_universe(isl_space_from_domain(space));
11724 if (rational)
11725 bmap = isl_basic_map_set_rational(bmap);
11727 for (i = 0; i < maff->n; ++i) {
11728 isl_aff *aff;
11729 isl_basic_map *bmap_i;
11731 aff = isl_aff_copy(maff->p[i]);
11732 bmap_i = isl_basic_map_from_aff2(aff, rational);
11734 bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11737 bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff));
11739 isl_multi_aff_free(maff);
11740 return bmap;
11741 error:
11742 isl_multi_aff_free(maff);
11743 return NULL;
11746 /* Construct a basic map mapping the domain the multi-affine expression
11747 * to its range, with each dimension in the range equated to the
11748 * corresponding affine expression.
11750 __isl_give isl_basic_map *isl_basic_map_from_multi_aff(
11751 __isl_take isl_multi_aff *ma)
11753 return isl_basic_map_from_multi_aff2(ma, 0);
11756 /* Construct a map mapping the domain the multi-affine expression
11757 * to its range, with each dimension in the range equated to the
11758 * corresponding affine expression.
11760 __isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff)
11762 isl_basic_map *bmap;
11764 bmap = isl_basic_map_from_multi_aff(maff);
11765 return isl_map_from_basic_map(bmap);
11768 /* Construct a basic map mapping a domain in the given space to
11769 * to an n-dimensional range, with n the number of elements in the list,
11770 * where each coordinate in the range is prescribed by the
11771 * corresponding affine expression.
11772 * The domains of all affine expressions in the list are assumed to match
11773 * domain_dim.
11775 __isl_give isl_basic_map *isl_basic_map_from_aff_list(
11776 __isl_take isl_space *domain_dim, __isl_take isl_aff_list *list)
11778 int i;
11779 isl_space *dim;
11780 isl_basic_map *bmap;
11782 if (!list)
11783 return NULL;
11785 dim = isl_space_from_domain(domain_dim);
11786 bmap = isl_basic_map_universe(dim);
11788 for (i = 0; i < list->n; ++i) {
11789 isl_aff *aff;
11790 isl_basic_map *bmap_i;
11792 aff = isl_aff_copy(list->p[i]);
11793 bmap_i = isl_basic_map_from_aff(aff);
11795 bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11798 isl_aff_list_free(list);
11799 return bmap;
11802 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
11803 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11805 return isl_map_equate(set, type1, pos1, type2, pos2);
11808 /* Construct a basic map where the given dimensions are equal to each other.
11810 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
11811 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11813 isl_basic_map *bmap = NULL;
11814 int i;
11816 if (!space)
11817 return NULL;
11819 if (pos1 >= isl_space_dim(space, type1))
11820 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11821 "index out of bounds", goto error);
11822 if (pos2 >= isl_space_dim(space, type2))
11823 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11824 "index out of bounds", goto error);
11826 if (type1 == type2 && pos1 == pos2)
11827 return isl_basic_map_universe(space);
11829 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
11830 i = isl_basic_map_alloc_equality(bmap);
11831 if (i < 0)
11832 goto error;
11833 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11834 pos1 += isl_basic_map_offset(bmap, type1);
11835 pos2 += isl_basic_map_offset(bmap, type2);
11836 isl_int_set_si(bmap->eq[i][pos1], -1);
11837 isl_int_set_si(bmap->eq[i][pos2], 1);
11838 bmap = isl_basic_map_finalize(bmap);
11839 isl_space_free(space);
11840 return bmap;
11841 error:
11842 isl_space_free(space);
11843 isl_basic_map_free(bmap);
11844 return NULL;
11847 /* Add a constraint imposing that the given two dimensions are equal.
11849 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
11850 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11852 isl_basic_map *eq;
11854 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
11856 bmap = isl_basic_map_intersect(bmap, eq);
11858 return bmap;
11861 /* Add a constraint imposing that the given two dimensions are equal.
11863 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
11864 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11866 isl_basic_map *bmap;
11868 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
11870 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11872 return map;
11875 /* Add a constraint imposing that the given two dimensions have opposite values.
11877 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
11878 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11880 isl_basic_map *bmap = NULL;
11881 int i;
11883 if (!map)
11884 return NULL;
11886 if (pos1 >= isl_map_dim(map, type1))
11887 isl_die(map->ctx, isl_error_invalid,
11888 "index out of bounds", goto error);
11889 if (pos2 >= isl_map_dim(map, type2))
11890 isl_die(map->ctx, isl_error_invalid,
11891 "index out of bounds", goto error);
11893 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
11894 i = isl_basic_map_alloc_equality(bmap);
11895 if (i < 0)
11896 goto error;
11897 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11898 pos1 += isl_basic_map_offset(bmap, type1);
11899 pos2 += isl_basic_map_offset(bmap, type2);
11900 isl_int_set_si(bmap->eq[i][pos1], 1);
11901 isl_int_set_si(bmap->eq[i][pos2], 1);
11902 bmap = isl_basic_map_finalize(bmap);
11904 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11906 return map;
11907 error:
11908 isl_basic_map_free(bmap);
11909 isl_map_free(map);
11910 return NULL;
11913 /* Construct a constraint imposing that the value of the first dimension is
11914 * greater than or equal to that of the second.
11916 static __isl_give isl_constraint *constraint_order_ge(
11917 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
11918 enum isl_dim_type type2, int pos2)
11920 isl_constraint *c;
11922 if (!space)
11923 return NULL;
11925 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
11927 if (pos1 >= isl_constraint_dim(c, type1))
11928 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
11929 "index out of bounds", return isl_constraint_free(c));
11930 if (pos2 >= isl_constraint_dim(c, type2))
11931 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
11932 "index out of bounds", return isl_constraint_free(c));
11934 if (type1 == type2 && pos1 == pos2)
11935 return c;
11937 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
11938 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
11940 return c;
11943 /* Add a constraint imposing that the value of the first dimension is
11944 * greater than or equal to that of the second.
11946 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
11947 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11949 isl_constraint *c;
11950 isl_space *space;
11952 if (type1 == type2 && pos1 == pos2)
11953 return bmap;
11954 space = isl_basic_map_get_space(bmap);
11955 c = constraint_order_ge(space, type1, pos1, type2, pos2);
11956 bmap = isl_basic_map_add_constraint(bmap, c);
11958 return bmap;
11961 /* Add a constraint imposing that the value of the first dimension is
11962 * greater than or equal to that of the second.
11964 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
11965 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11967 isl_constraint *c;
11968 isl_space *space;
11970 if (type1 == type2 && pos1 == pos2)
11971 return map;
11972 space = isl_map_get_space(map);
11973 c = constraint_order_ge(space, type1, pos1, type2, pos2);
11974 map = isl_map_add_constraint(map, c);
11976 return map;
11979 /* Add a constraint imposing that the value of the first dimension is
11980 * less than or equal to that of the second.
11982 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
11983 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11985 return isl_map_order_ge(map, type2, pos2, type1, pos1);
11988 /* Construct a basic map where the value of the first dimension is
11989 * greater than that of the second.
11991 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
11992 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11994 isl_basic_map *bmap = NULL;
11995 int i;
11997 if (!space)
11998 return NULL;
12000 if (pos1 >= isl_space_dim(space, type1))
12001 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12002 "index out of bounds", goto error);
12003 if (pos2 >= isl_space_dim(space, type2))
12004 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12005 "index out of bounds", goto error);
12007 if (type1 == type2 && pos1 == pos2)
12008 return isl_basic_map_empty(space);
12010 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12011 i = isl_basic_map_alloc_inequality(bmap);
12012 if (i < 0)
12013 return isl_basic_map_free(bmap);
12014 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12015 pos1 += isl_basic_map_offset(bmap, type1);
12016 pos2 += isl_basic_map_offset(bmap, type2);
12017 isl_int_set_si(bmap->ineq[i][pos1], 1);
12018 isl_int_set_si(bmap->ineq[i][pos2], -1);
12019 isl_int_set_si(bmap->ineq[i][0], -1);
12020 bmap = isl_basic_map_finalize(bmap);
12022 return bmap;
12023 error:
12024 isl_space_free(space);
12025 isl_basic_map_free(bmap);
12026 return NULL;
12029 /* Add a constraint imposing that the value of the first dimension is
12030 * greater than that of the second.
12032 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12033 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12035 isl_basic_map *gt;
12037 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12039 bmap = isl_basic_map_intersect(bmap, gt);
12041 return bmap;
12044 /* Add a constraint imposing that the value of the first dimension is
12045 * greater than that of the second.
12047 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12048 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12050 isl_basic_map *bmap;
12052 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12054 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12056 return map;
12059 /* Add a constraint imposing that the value of the first dimension is
12060 * smaller than that of the second.
12062 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12063 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12065 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12068 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12069 int pos)
12071 isl_aff *div;
12072 isl_local_space *ls;
12074 if (!bmap)
12075 return NULL;
12077 if (!isl_basic_map_divs_known(bmap))
12078 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12079 "some divs are unknown", return NULL);
12081 ls = isl_basic_map_get_local_space(bmap);
12082 div = isl_local_space_get_div(ls, pos);
12083 isl_local_space_free(ls);
12085 return div;
12088 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12089 int pos)
12091 return isl_basic_map_get_div(bset, pos);
12094 /* Plug in "subs" for dimension "type", "pos" of "bset".
12096 * Let i be the dimension to replace and let "subs" be of the form
12098 * f/d
12100 * Any integer division with a non-zero coefficient for i,
12102 * floor((a i + g)/m)
12104 * is replaced by
12106 * floor((a f + d g)/(m d))
12108 * Constraints of the form
12110 * a i + g
12112 * are replaced by
12114 * a f + d g
12116 * We currently require that "subs" is an integral expression.
12117 * Handling rational expressions may require us to add stride constraints
12118 * as we do in isl_basic_set_preimage_multi_aff.
12120 __isl_give isl_basic_set *isl_basic_set_substitute(
12121 __isl_take isl_basic_set *bset,
12122 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12124 int i;
12125 isl_int v;
12126 isl_ctx *ctx;
12128 if (bset && isl_basic_set_plain_is_empty(bset))
12129 return bset;
12131 bset = isl_basic_set_cow(bset);
12132 if (!bset || !subs)
12133 goto error;
12135 ctx = isl_basic_set_get_ctx(bset);
12136 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12137 isl_die(ctx, isl_error_invalid,
12138 "spaces don't match", goto error);
12139 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12140 isl_die(ctx, isl_error_unsupported,
12141 "cannot handle divs yet", goto error);
12142 if (!isl_int_is_one(subs->v->el[0]))
12143 isl_die(ctx, isl_error_invalid,
12144 "can only substitute integer expressions", goto error);
12146 pos += isl_basic_set_offset(bset, type);
12148 isl_int_init(v);
12150 for (i = 0; i < bset->n_eq; ++i) {
12151 if (isl_int_is_zero(bset->eq[i][pos]))
12152 continue;
12153 isl_int_set(v, bset->eq[i][pos]);
12154 isl_int_set_si(bset->eq[i][pos], 0);
12155 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12156 v, subs->v->el + 1, subs->v->size - 1);
12159 for (i = 0; i < bset->n_ineq; ++i) {
12160 if (isl_int_is_zero(bset->ineq[i][pos]))
12161 continue;
12162 isl_int_set(v, bset->ineq[i][pos]);
12163 isl_int_set_si(bset->ineq[i][pos], 0);
12164 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12165 v, subs->v->el + 1, subs->v->size - 1);
12168 for (i = 0; i < bset->n_div; ++i) {
12169 if (isl_int_is_zero(bset->div[i][1 + pos]))
12170 continue;
12171 isl_int_set(v, bset->div[i][1 + pos]);
12172 isl_int_set_si(bset->div[i][1 + pos], 0);
12173 isl_seq_combine(bset->div[i] + 1,
12174 subs->v->el[0], bset->div[i] + 1,
12175 v, subs->v->el + 1, subs->v->size - 1);
12176 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12179 isl_int_clear(v);
12181 bset = isl_basic_set_simplify(bset);
12182 return isl_basic_set_finalize(bset);
12183 error:
12184 isl_basic_set_free(bset);
12185 return NULL;
12188 /* Plug in "subs" for dimension "type", "pos" of "set".
12190 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12191 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12193 int i;
12195 if (set && isl_set_plain_is_empty(set))
12196 return set;
12198 set = isl_set_cow(set);
12199 if (!set || !subs)
12200 goto error;
12202 for (i = set->n - 1; i >= 0; --i) {
12203 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12204 if (remove_if_empty(set, i) < 0)
12205 goto error;
12208 return set;
12209 error:
12210 isl_set_free(set);
12211 return NULL;
12214 /* Check if the range of "ma" is compatible with the domain or range
12215 * (depending on "type") of "bmap".
12217 static isl_stat check_basic_map_compatible_range_multi_aff(
12218 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12219 __isl_keep isl_multi_aff *ma)
12221 isl_bool m;
12222 isl_space *ma_space;
12224 ma_space = isl_multi_aff_get_space(ma);
12226 m = isl_space_match(bmap->dim, isl_dim_param, ma_space, isl_dim_param);
12227 if (m < 0)
12228 goto error;
12229 if (!m)
12230 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12231 "parameters don't match", goto error);
12232 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12233 if (m < 0)
12234 goto error;
12235 if (!m)
12236 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12237 "spaces don't match", goto error);
12239 isl_space_free(ma_space);
12240 return isl_stat_ok;
12241 error:
12242 isl_space_free(ma_space);
12243 return isl_stat_error;
12246 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12247 * coefficients before the transformed range of dimensions,
12248 * the "n_after" coefficients after the transformed range of dimensions
12249 * and the coefficients of the other divs in "bmap".
12251 static int set_ma_divs(__isl_keep isl_basic_map *bmap,
12252 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12254 int i;
12255 int n_param;
12256 int n_set;
12257 isl_local_space *ls;
12259 if (n_div == 0)
12260 return 0;
12262 ls = isl_aff_get_domain_local_space(ma->p[0]);
12263 if (!ls)
12264 return -1;
12266 n_param = isl_local_space_dim(ls, isl_dim_param);
12267 n_set = isl_local_space_dim(ls, isl_dim_set);
12268 for (i = 0; i < n_div; ++i) {
12269 int o_bmap = 0, o_ls = 0;
12271 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12272 o_bmap += 1 + 1 + n_param;
12273 o_ls += 1 + 1 + n_param;
12274 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12275 o_bmap += n_before;
12276 isl_seq_cpy(bmap->div[i] + o_bmap,
12277 ls->div->row[i] + o_ls, n_set);
12278 o_bmap += n_set;
12279 o_ls += n_set;
12280 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12281 o_bmap += n_after;
12282 isl_seq_cpy(bmap->div[i] + o_bmap,
12283 ls->div->row[i] + o_ls, n_div);
12284 o_bmap += n_div;
12285 o_ls += n_div;
12286 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12287 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
12288 goto error;
12291 isl_local_space_free(ls);
12292 return 0;
12293 error:
12294 isl_local_space_free(ls);
12295 return -1;
12298 /* How many stride constraints does "ma" enforce?
12299 * That is, how many of the affine expressions have a denominator
12300 * different from one?
12302 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12304 int i;
12305 int strides = 0;
12307 for (i = 0; i < ma->n; ++i)
12308 if (!isl_int_is_one(ma->p[i]->v->el[0]))
12309 strides++;
12311 return strides;
12314 /* For each affine expression in ma of the form
12316 * x_i = (f_i y + h_i)/m_i
12318 * with m_i different from one, add a constraint to "bmap"
12319 * of the form
12321 * f_i y + h_i = m_i alpha_i
12323 * with alpha_i an additional existentially quantified variable.
12325 * The input variables of "ma" correspond to a subset of the variables
12326 * of "bmap". There are "n_before" variables in "bmap" before this
12327 * subset and "n_after" variables after this subset.
12328 * The integer divisions of the affine expressions in "ma" are assumed
12329 * to have been aligned. There are "n_div_ma" of them and
12330 * they appear first in "bmap", straight after the "n_after" variables.
12332 static __isl_give isl_basic_map *add_ma_strides(
12333 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12334 int n_before, int n_after, int n_div_ma)
12336 int i, k;
12337 int div;
12338 int total;
12339 int n_param;
12340 int n_in;
12342 total = isl_basic_map_total_dim(bmap);
12343 n_param = isl_multi_aff_dim(ma, isl_dim_param);
12344 n_in = isl_multi_aff_dim(ma, isl_dim_in);
12345 for (i = 0; i < ma->n; ++i) {
12346 int o_bmap = 0, o_ma = 1;
12348 if (isl_int_is_one(ma->p[i]->v->el[0]))
12349 continue;
12350 div = isl_basic_map_alloc_div(bmap);
12351 k = isl_basic_map_alloc_equality(bmap);
12352 if (div < 0 || k < 0)
12353 goto error;
12354 isl_int_set_si(bmap->div[div][0], 0);
12355 isl_seq_cpy(bmap->eq[k] + o_bmap,
12356 ma->p[i]->v->el + o_ma, 1 + n_param);
12357 o_bmap += 1 + n_param;
12358 o_ma += 1 + n_param;
12359 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12360 o_bmap += n_before;
12361 isl_seq_cpy(bmap->eq[k] + o_bmap,
12362 ma->p[i]->v->el + o_ma, n_in);
12363 o_bmap += n_in;
12364 o_ma += n_in;
12365 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12366 o_bmap += n_after;
12367 isl_seq_cpy(bmap->eq[k] + o_bmap,
12368 ma->p[i]->v->el + o_ma, n_div_ma);
12369 o_bmap += n_div_ma;
12370 o_ma += n_div_ma;
12371 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12372 isl_int_neg(bmap->eq[k][1 + total], ma->p[i]->v->el[0]);
12373 total++;
12376 return bmap;
12377 error:
12378 isl_basic_map_free(bmap);
12379 return NULL;
12382 /* Replace the domain or range space (depending on "type) of "space" by "set".
12384 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12385 enum isl_dim_type type, __isl_take isl_space *set)
12387 if (type == isl_dim_in) {
12388 space = isl_space_range(space);
12389 space = isl_space_map_from_domain_and_range(set, space);
12390 } else {
12391 space = isl_space_domain(space);
12392 space = isl_space_map_from_domain_and_range(space, set);
12395 return space;
12398 /* Compute the preimage of the domain or range (depending on "type")
12399 * of "bmap" under the function represented by "ma".
12400 * In other words, plug in "ma" in the domain or range of "bmap".
12401 * The result is a basic map that lives in the same space as "bmap"
12402 * except that the domain or range has been replaced by
12403 * the domain space of "ma".
12405 * If bmap is represented by
12407 * A(p) + S u + B x + T v + C(divs) >= 0,
12409 * where u and x are input and output dimensions if type == isl_dim_out
12410 * while x and v are input and output dimensions if type == isl_dim_in,
12411 * and ma is represented by
12413 * x = D(p) + F(y) + G(divs')
12415 * then the result is
12417 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12419 * The divs in the input set are similarly adjusted.
12420 * In particular
12422 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12424 * becomes
12426 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12427 * B_i G(divs') + c_i(divs))/n_i)
12429 * If bmap is not a rational map and if F(y) involves any denominators
12431 * x_i = (f_i y + h_i)/m_i
12433 * then additional constraints are added to ensure that we only
12434 * map back integer points. That is we enforce
12436 * f_i y + h_i = m_i alpha_i
12438 * with alpha_i an additional existentially quantified variable.
12440 * We first copy over the divs from "ma".
12441 * Then we add the modified constraints and divs from "bmap".
12442 * Finally, we add the stride constraints, if needed.
12444 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12445 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12446 __isl_take isl_multi_aff *ma)
12448 int i, k;
12449 isl_space *space;
12450 isl_basic_map *res = NULL;
12451 int n_before, n_after, n_div_bmap, n_div_ma;
12452 isl_int f, c1, c2, g;
12453 isl_bool rational;
12454 int strides;
12456 isl_int_init(f);
12457 isl_int_init(c1);
12458 isl_int_init(c2);
12459 isl_int_init(g);
12461 ma = isl_multi_aff_align_divs(ma);
12462 if (!bmap || !ma)
12463 goto error;
12464 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12465 goto error;
12467 if (type == isl_dim_in) {
12468 n_before = 0;
12469 n_after = isl_basic_map_dim(bmap, isl_dim_out);
12470 } else {
12471 n_before = isl_basic_map_dim(bmap, isl_dim_in);
12472 n_after = 0;
12474 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12475 n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
12477 space = isl_multi_aff_get_domain_space(ma);
12478 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12479 rational = isl_basic_map_is_rational(bmap);
12480 strides = rational ? 0 : multi_aff_strides(ma);
12481 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12482 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12483 if (rational)
12484 res = isl_basic_map_set_rational(res);
12486 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12487 if (isl_basic_map_alloc_div(res) < 0)
12488 goto error;
12490 if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
12491 goto error;
12493 for (i = 0; i < bmap->n_eq; ++i) {
12494 k = isl_basic_map_alloc_equality(res);
12495 if (k < 0)
12496 goto error;
12497 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
12498 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12501 for (i = 0; i < bmap->n_ineq; ++i) {
12502 k = isl_basic_map_alloc_inequality(res);
12503 if (k < 0)
12504 goto error;
12505 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
12506 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12509 for (i = 0; i < bmap->n_div; ++i) {
12510 if (isl_int_is_zero(bmap->div[i][0])) {
12511 isl_int_set_si(res->div[n_div_ma + i][0], 0);
12512 continue;
12514 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
12515 n_before, n_after, n_div_ma, n_div_bmap,
12516 f, c1, c2, g, 1);
12519 if (strides)
12520 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
12522 isl_int_clear(f);
12523 isl_int_clear(c1);
12524 isl_int_clear(c2);
12525 isl_int_clear(g);
12526 isl_basic_map_free(bmap);
12527 isl_multi_aff_free(ma);
12528 res = isl_basic_map_simplify(res);
12529 return isl_basic_map_finalize(res);
12530 error:
12531 isl_int_clear(f);
12532 isl_int_clear(c1);
12533 isl_int_clear(c2);
12534 isl_int_clear(g);
12535 isl_basic_map_free(bmap);
12536 isl_multi_aff_free(ma);
12537 isl_basic_map_free(res);
12538 return NULL;
12541 /* Compute the preimage of "bset" under the function represented by "ma".
12542 * In other words, plug in "ma" in "bset". The result is a basic set
12543 * that lives in the domain space of "ma".
12545 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
12546 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
12548 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
12551 /* Compute the preimage of the domain of "bmap" under the function
12552 * represented by "ma".
12553 * In other words, plug in "ma" in the domain of "bmap".
12554 * The result is a basic map that lives in the same space as "bmap"
12555 * except that the domain has been replaced by the domain space of "ma".
12557 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
12558 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12560 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
12563 /* Compute the preimage of the range of "bmap" under the function
12564 * represented by "ma".
12565 * In other words, plug in "ma" in the range of "bmap".
12566 * The result is a basic map that lives in the same space as "bmap"
12567 * except that the range has been replaced by the domain space of "ma".
12569 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
12570 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12572 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
12575 /* Check if the range of "ma" is compatible with the domain or range
12576 * (depending on "type") of "map".
12577 * Return isl_stat_error if anything is wrong.
12579 static isl_stat check_map_compatible_range_multi_aff(
12580 __isl_keep isl_map *map, enum isl_dim_type type,
12581 __isl_keep isl_multi_aff *ma)
12583 isl_bool m;
12584 isl_space *ma_space;
12586 ma_space = isl_multi_aff_get_space(ma);
12587 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
12588 isl_space_free(ma_space);
12589 if (m < 0)
12590 return isl_stat_error;
12591 if (!m)
12592 isl_die(isl_map_get_ctx(map), isl_error_invalid,
12593 "spaces don't match", return isl_stat_error);
12594 return isl_stat_ok;
12597 /* Compute the preimage of the domain or range (depending on "type")
12598 * of "map" under the function represented by "ma".
12599 * In other words, plug in "ma" in the domain or range of "map".
12600 * The result is a map that lives in the same space as "map"
12601 * except that the domain or range has been replaced by
12602 * the domain space of "ma".
12604 * The parameters are assumed to have been aligned.
12606 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
12607 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12609 int i;
12610 isl_space *space;
12612 map = isl_map_cow(map);
12613 ma = isl_multi_aff_align_divs(ma);
12614 if (!map || !ma)
12615 goto error;
12616 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
12617 goto error;
12619 for (i = 0; i < map->n; ++i) {
12620 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
12621 isl_multi_aff_copy(ma));
12622 if (!map->p[i])
12623 goto error;
12626 space = isl_multi_aff_get_domain_space(ma);
12627 space = isl_space_set(isl_map_get_space(map), type, space);
12629 isl_space_free(map->dim);
12630 map->dim = space;
12631 if (!map->dim)
12632 goto error;
12634 isl_multi_aff_free(ma);
12635 if (map->n > 1)
12636 ISL_F_CLR(map, ISL_MAP_DISJOINT);
12637 ISL_F_CLR(map, ISL_SET_NORMALIZED);
12638 return map;
12639 error:
12640 isl_multi_aff_free(ma);
12641 isl_map_free(map);
12642 return NULL;
12645 /* Compute the preimage of the domain or range (depending on "type")
12646 * of "map" under the function represented by "ma".
12647 * In other words, plug in "ma" in the domain or range of "map".
12648 * The result is a map that lives in the same space as "map"
12649 * except that the domain or range has been replaced by
12650 * the domain space of "ma".
12652 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
12653 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12655 if (!map || !ma)
12656 goto error;
12658 if (isl_space_match(map->dim, isl_dim_param, ma->space, isl_dim_param))
12659 return map_preimage_multi_aff(map, type, ma);
12661 if (isl_map_check_named_params(map) < 0)
12662 goto error;
12663 if (!isl_space_has_named_params(ma->space))
12664 isl_die(map->ctx, isl_error_invalid,
12665 "unaligned unnamed parameters", goto error);
12666 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
12667 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
12669 return map_preimage_multi_aff(map, type, ma);
12670 error:
12671 isl_multi_aff_free(ma);
12672 return isl_map_free(map);
12675 /* Compute the preimage of "set" under the function represented by "ma".
12676 * In other words, plug in "ma" in "set". The result is a set
12677 * that lives in the domain space of "ma".
12679 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
12680 __isl_take isl_multi_aff *ma)
12682 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
12685 /* Compute the preimage of the domain of "map" under the function
12686 * represented by "ma".
12687 * In other words, plug in "ma" in the domain of "map".
12688 * The result is a map that lives in the same space as "map"
12689 * except that the domain has been replaced by the domain space of "ma".
12691 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
12692 __isl_take isl_multi_aff *ma)
12694 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
12697 /* Compute the preimage of the range of "map" under the function
12698 * represented by "ma".
12699 * In other words, plug in "ma" in the range of "map".
12700 * The result is a map that lives in the same space as "map"
12701 * except that the range has been replaced by the domain space of "ma".
12703 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
12704 __isl_take isl_multi_aff *ma)
12706 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
12709 /* Compute the preimage of "map" under the function represented by "pma".
12710 * In other words, plug in "pma" in the domain or range of "map".
12711 * The result is a map that lives in the same space as "map",
12712 * except that the space of type "type" has been replaced by
12713 * the domain space of "pma".
12715 * The parameters of "map" and "pma" are assumed to have been aligned.
12717 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
12718 __isl_take isl_map *map, enum isl_dim_type type,
12719 __isl_take isl_pw_multi_aff *pma)
12721 int i;
12722 isl_map *res;
12724 if (!pma)
12725 goto error;
12727 if (pma->n == 0) {
12728 isl_pw_multi_aff_free(pma);
12729 res = isl_map_empty(isl_map_get_space(map));
12730 isl_map_free(map);
12731 return res;
12734 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
12735 isl_multi_aff_copy(pma->p[0].maff));
12736 if (type == isl_dim_in)
12737 res = isl_map_intersect_domain(res,
12738 isl_map_copy(pma->p[0].set));
12739 else
12740 res = isl_map_intersect_range(res,
12741 isl_map_copy(pma->p[0].set));
12743 for (i = 1; i < pma->n; ++i) {
12744 isl_map *res_i;
12746 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
12747 isl_multi_aff_copy(pma->p[i].maff));
12748 if (type == isl_dim_in)
12749 res_i = isl_map_intersect_domain(res_i,
12750 isl_map_copy(pma->p[i].set));
12751 else
12752 res_i = isl_map_intersect_range(res_i,
12753 isl_map_copy(pma->p[i].set));
12754 res = isl_map_union(res, res_i);
12757 isl_pw_multi_aff_free(pma);
12758 isl_map_free(map);
12759 return res;
12760 error:
12761 isl_pw_multi_aff_free(pma);
12762 isl_map_free(map);
12763 return NULL;
12766 /* Compute the preimage of "map" under the function represented by "pma".
12767 * In other words, plug in "pma" in the domain or range of "map".
12768 * The result is a map that lives in the same space as "map",
12769 * except that the space of type "type" has been replaced by
12770 * the domain space of "pma".
12772 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
12773 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
12775 if (!map || !pma)
12776 goto error;
12778 if (isl_space_match(map->dim, isl_dim_param, pma->dim, isl_dim_param))
12779 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
12781 if (isl_map_check_named_params(map) < 0)
12782 goto error;
12783 if (!isl_space_has_named_params(pma->dim))
12784 isl_die(map->ctx, isl_error_invalid,
12785 "unaligned unnamed parameters", goto error);
12786 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
12787 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
12789 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
12790 error:
12791 isl_pw_multi_aff_free(pma);
12792 return isl_map_free(map);
12795 /* Compute the preimage of "set" under the function represented by "pma".
12796 * In other words, plug in "pma" in "set". The result is a set
12797 * that lives in the domain space of "pma".
12799 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
12800 __isl_take isl_pw_multi_aff *pma)
12802 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
12805 /* Compute the preimage of the domain of "map" under the function
12806 * represented by "pma".
12807 * In other words, plug in "pma" in the domain of "map".
12808 * The result is a map that lives in the same space as "map",
12809 * except that domain space has been replaced by the domain space of "pma".
12811 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
12812 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
12814 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
12817 /* Compute the preimage of the range of "map" under the function
12818 * represented by "pma".
12819 * In other words, plug in "pma" in the range of "map".
12820 * The result is a map that lives in the same space as "map",
12821 * except that range space has been replaced by the domain space of "pma".
12823 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
12824 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
12826 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
12829 /* Compute the preimage of "map" under the function represented by "mpa".
12830 * In other words, plug in "mpa" in the domain or range of "map".
12831 * The result is a map that lives in the same space as "map",
12832 * except that the space of type "type" has been replaced by
12833 * the domain space of "mpa".
12835 * If the map does not involve any constraints that refer to the
12836 * dimensions of the substituted space, then the only possible
12837 * effect of "mpa" on the map is to map the space to a different space.
12838 * We create a separate isl_multi_aff to effectuate this change
12839 * in order to avoid spurious splitting of the map along the pieces
12840 * of "mpa".
12842 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
12843 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
12845 int n;
12846 isl_pw_multi_aff *pma;
12848 if (!map || !mpa)
12849 goto error;
12851 n = isl_map_dim(map, type);
12852 if (!isl_map_involves_dims(map, type, 0, n)) {
12853 isl_space *space;
12854 isl_multi_aff *ma;
12856 space = isl_multi_pw_aff_get_space(mpa);
12857 isl_multi_pw_aff_free(mpa);
12858 ma = isl_multi_aff_zero(space);
12859 return isl_map_preimage_multi_aff(map, type, ma);
12862 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
12863 return isl_map_preimage_pw_multi_aff(map, type, pma);
12864 error:
12865 isl_map_free(map);
12866 isl_multi_pw_aff_free(mpa);
12867 return NULL;
12870 /* Compute the preimage of "map" under the function represented by "mpa".
12871 * In other words, plug in "mpa" in the domain "map".
12872 * The result is a map that lives in the same space as "map",
12873 * except that domain space has been replaced by the domain space of "mpa".
12875 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
12876 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
12878 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
12881 /* Compute the preimage of "set" by the function represented by "mpa".
12882 * In other words, plug in "mpa" in "set".
12884 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
12885 __isl_take isl_multi_pw_aff *mpa)
12887 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
12890 /* Are the "n" "coefficients" starting at "first" of the integer division
12891 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
12892 * to each other?
12893 * The "coefficient" at position 0 is the denominator.
12894 * The "coefficient" at position 1 is the constant term.
12896 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
12897 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
12898 unsigned first, unsigned n)
12900 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
12901 return isl_bool_error;
12902 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
12903 return isl_bool_error;
12904 return isl_seq_eq(bmap1->div[pos1] + first,
12905 bmap2->div[pos2] + first, n);
12908 /* Are the integer division expressions at position "pos1" in "bmap1" and
12909 * "pos2" in "bmap2" equal to each other, except that the constant terms
12910 * are different?
12912 isl_bool isl_basic_map_equal_div_expr_except_constant(
12913 __isl_keep isl_basic_map *bmap1, int pos1,
12914 __isl_keep isl_basic_map *bmap2, int pos2)
12916 isl_bool equal;
12917 unsigned total;
12919 if (!bmap1 || !bmap2)
12920 return isl_bool_error;
12921 total = isl_basic_map_total_dim(bmap1);
12922 if (total != isl_basic_map_total_dim(bmap2))
12923 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
12924 "incomparable div expressions", return isl_bool_error);
12925 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
12926 0, 1);
12927 if (equal < 0 || !equal)
12928 return equal;
12929 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
12930 1, 1);
12931 if (equal < 0 || equal)
12932 return isl_bool_not(equal);
12933 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
12934 2, total);
12937 /* Replace the numerator of the constant term of the integer division
12938 * expression at position "div" in "bmap" by "value".
12939 * The caller guarantees that this does not change the meaning
12940 * of the input.
12942 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
12943 __isl_take isl_basic_map *bmap, int div, int value)
12945 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
12946 return isl_basic_map_free(bmap);
12948 isl_int_set_si(bmap->div[div][1], value);
12950 return bmap;
12953 /* Is the point "inner" internal to inequality constraint "ineq"
12954 * of "bset"?
12955 * The point is considered to be internal to the inequality constraint,
12956 * if it strictly lies on the positive side of the inequality constraint,
12957 * or if it lies on the constraint and the constraint is lexico-positive.
12959 static isl_bool is_internal(__isl_keep isl_vec *inner,
12960 __isl_keep isl_basic_set *bset, int ineq)
12962 isl_ctx *ctx;
12963 int pos;
12964 unsigned total;
12966 if (!inner || !bset)
12967 return isl_bool_error;
12969 ctx = isl_basic_set_get_ctx(bset);
12970 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
12971 &ctx->normalize_gcd);
12972 if (!isl_int_is_zero(ctx->normalize_gcd))
12973 return isl_int_is_nonneg(ctx->normalize_gcd);
12975 total = isl_basic_set_dim(bset, isl_dim_all);
12976 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
12977 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
12980 /* Tighten the inequality constraints of "bset" that are outward with respect
12981 * to the point "vec".
12982 * That is, tighten the constraints that are not satisfied by "vec".
12984 * "vec" is a point internal to some superset S of "bset" that is used
12985 * to make the subsets of S disjoint, by tightening one half of the constraints
12986 * that separate two subsets. In particular, the constraints of S
12987 * are all satisfied by "vec" and should not be tightened.
12988 * Of the internal constraints, those that have "vec" on the outside
12989 * are tightened. The shared facet is included in the adjacent subset
12990 * with the opposite constraint.
12991 * For constraints that saturate "vec", this criterion cannot be used
12992 * to determine which of the two sides should be tightened.
12993 * Instead, the sign of the first non-zero coefficient is used
12994 * to make this choice. Note that this second criterion is never used
12995 * on the constraints of S since "vec" is interior to "S".
12997 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
12998 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13000 int j;
13002 bset = isl_basic_set_cow(bset);
13003 if (!bset)
13004 return NULL;
13005 for (j = 0; j < bset->n_ineq; ++j) {
13006 isl_bool internal;
13008 internal = is_internal(vec, bset, j);
13009 if (internal < 0)
13010 return isl_basic_set_free(bset);
13011 if (internal)
13012 continue;
13013 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13016 return bset;