bc64f6489769ee0f404a670f1a56c46ecfb1f17c
[isl.git] / isl_map.c
blobbc64f6489769ee0f404a670f1a56c46ecfb1f17c
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege, K.U.Leuven, Departement
9 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
11 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
12 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
15 #include <string.h>
16 #include <isl_ctx_private.h>
17 #include <isl_map_private.h>
18 #include <isl/blk.h>
19 #include "isl_space_private.h"
20 #include "isl_equalities.h"
21 #include <isl/lp.h>
22 #include <isl_seq.h>
23 #include <isl/set.h>
24 #include <isl/map.h>
25 #include "isl_map_piplib.h"
26 #include <isl_reordering.h>
27 #include "isl_sample.h"
28 #include "isl_tab.h"
29 #include <isl/vec.h>
30 #include <isl_mat_private.h>
31 #include <isl_vec_private.h>
32 #include <isl_dim_map.h>
33 #include <isl_local_space_private.h>
34 #include <isl_aff_private.h>
35 #include <isl_options_private.h>
36 #include <isl_morph.h>
37 #include <isl_val_private.h>
39 static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
41 switch (type) {
42 case isl_dim_param: return dim->nparam;
43 case isl_dim_in: return dim->n_in;
44 case isl_dim_out: return dim->n_out;
45 case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
46 default: return 0;
50 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
52 switch (type) {
53 case isl_dim_param: return 1;
54 case isl_dim_in: return 1 + dim->nparam;
55 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
56 default: return 0;
60 unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
61 enum isl_dim_type type)
63 if (!bmap)
64 return 0;
65 switch (type) {
66 case isl_dim_cst: return 1;
67 case isl_dim_param:
68 case isl_dim_in:
69 case isl_dim_out: return isl_space_dim(bmap->dim, type);
70 case isl_dim_div: return bmap->n_div;
71 case isl_dim_all: return isl_basic_map_total_dim(bmap);
72 default: return 0;
76 unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
78 return map ? n(map->dim, type) : 0;
81 unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
83 return set ? n(set->dim, type) : 0;
86 unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
87 enum isl_dim_type type)
89 isl_space *dim = bmap->dim;
90 switch (type) {
91 case isl_dim_cst: return 0;
92 case isl_dim_param: return 1;
93 case isl_dim_in: return 1 + dim->nparam;
94 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
95 case isl_dim_div: return 1 + dim->nparam + dim->n_in + dim->n_out;
96 default: return 0;
100 unsigned isl_basic_set_offset(struct isl_basic_set *bset,
101 enum isl_dim_type type)
103 return isl_basic_map_offset(bset, type);
106 static unsigned map_offset(struct isl_map *map, enum isl_dim_type type)
108 return pos(map->dim, type);
111 unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
112 enum isl_dim_type type)
114 return isl_basic_map_dim(bset, type);
117 unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
119 return isl_basic_set_dim(bset, isl_dim_set);
122 unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
124 return isl_basic_set_dim(bset, isl_dim_param);
127 unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset)
129 if (!bset)
130 return 0;
131 return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
134 unsigned isl_set_n_dim(__isl_keep isl_set *set)
136 return isl_set_dim(set, isl_dim_set);
139 unsigned isl_set_n_param(__isl_keep isl_set *set)
141 return isl_set_dim(set, isl_dim_param);
144 unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap)
146 return bmap ? bmap->dim->n_in : 0;
149 unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap)
151 return bmap ? bmap->dim->n_out : 0;
154 unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap)
156 return bmap ? bmap->dim->nparam : 0;
159 unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap)
161 return bmap ? bmap->n_div : 0;
164 unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap)
166 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
169 unsigned isl_map_n_in(const struct isl_map *map)
171 return map ? map->dim->n_in : 0;
174 unsigned isl_map_n_out(const struct isl_map *map)
176 return map ? map->dim->n_out : 0;
179 unsigned isl_map_n_param(const struct isl_map *map)
181 return map ? map->dim->nparam : 0;
184 int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set)
186 int m;
187 if (!map || !set)
188 return -1;
189 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
190 if (m < 0 || !m)
191 return m;
192 return isl_space_tuple_match(map->dim, isl_dim_in, set->dim, isl_dim_set);
195 int isl_basic_map_compatible_domain(struct isl_basic_map *bmap,
196 struct isl_basic_set *bset)
198 int m;
199 if (!bmap || !bset)
200 return -1;
201 m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
202 if (m < 0 || !m)
203 return m;
204 return isl_space_tuple_match(bmap->dim, isl_dim_in, bset->dim, isl_dim_set);
207 int isl_map_compatible_range(__isl_keep isl_map *map, __isl_keep isl_set *set)
209 int m;
210 if (!map || !set)
211 return -1;
212 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
213 if (m < 0 || !m)
214 return m;
215 return isl_space_tuple_match(map->dim, isl_dim_out, set->dim, isl_dim_set);
218 int isl_basic_map_compatible_range(struct isl_basic_map *bmap,
219 struct isl_basic_set *bset)
221 int m;
222 if (!bmap || !bset)
223 return -1;
224 m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
225 if (m < 0 || !m)
226 return m;
227 return isl_space_tuple_match(bmap->dim, isl_dim_out, bset->dim, isl_dim_set);
230 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
232 return bmap ? bmap->ctx : NULL;
235 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
237 return bset ? bset->ctx : NULL;
240 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
242 return map ? map->ctx : NULL;
245 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
247 return set ? set->ctx : NULL;
250 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
252 if (!bmap)
253 return NULL;
254 return isl_space_copy(bmap->dim);
257 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
259 if (!bset)
260 return NULL;
261 return isl_space_copy(bset->dim);
264 /* Extract the divs in "bmap" as a matrix.
266 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
268 int i;
269 isl_ctx *ctx;
270 isl_mat *div;
271 unsigned total;
272 unsigned cols;
274 if (!bmap)
275 return NULL;
277 ctx = isl_basic_map_get_ctx(bmap);
278 total = isl_space_dim(bmap->dim, isl_dim_all);
279 cols = 1 + 1 + total + bmap->n_div;
280 div = isl_mat_alloc(ctx, bmap->n_div, cols);
281 if (!div)
282 return NULL;
284 for (i = 0; i < bmap->n_div; ++i)
285 isl_seq_cpy(div->row[i], bmap->div[i], cols);
287 return div;
290 /* Extract the divs in "bset" as a matrix.
292 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
294 return isl_basic_map_get_divs(bset);
297 __isl_give isl_local_space *isl_basic_map_get_local_space(
298 __isl_keep isl_basic_map *bmap)
300 isl_mat *div;
302 if (!bmap)
303 return NULL;
305 div = isl_basic_map_get_divs(bmap);
306 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
309 __isl_give isl_local_space *isl_basic_set_get_local_space(
310 __isl_keep isl_basic_set *bset)
312 return isl_basic_map_get_local_space(bset);
315 __isl_give isl_basic_map *isl_basic_map_from_local_space(
316 __isl_take isl_local_space *ls)
318 int i;
319 int n_div;
320 isl_basic_map *bmap;
322 if (!ls)
323 return NULL;
325 n_div = isl_local_space_dim(ls, isl_dim_div);
326 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
327 n_div, 0, 2 * n_div);
329 for (i = 0; i < n_div; ++i)
330 if (isl_basic_map_alloc_div(bmap) < 0)
331 goto error;
333 for (i = 0; i < n_div; ++i) {
334 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
335 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
336 goto error;
339 isl_local_space_free(ls);
340 return bmap;
341 error:
342 isl_local_space_free(ls);
343 isl_basic_map_free(bmap);
344 return NULL;
347 __isl_give isl_basic_set *isl_basic_set_from_local_space(
348 __isl_take isl_local_space *ls)
350 return isl_basic_map_from_local_space(ls);
353 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
355 if (!map)
356 return NULL;
357 return isl_space_copy(map->dim);
360 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
362 if (!set)
363 return NULL;
364 return isl_space_copy(set->dim);
367 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
368 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
370 bmap = isl_basic_map_cow(bmap);
371 if (!bmap)
372 return NULL;
373 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
374 if (!bmap->dim)
375 goto error;
376 bmap = isl_basic_map_finalize(bmap);
377 return bmap;
378 error:
379 isl_basic_map_free(bmap);
380 return NULL;
383 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
384 __isl_take isl_basic_set *bset, const char *s)
386 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
389 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
390 enum isl_dim_type type)
392 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
395 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
396 enum isl_dim_type type, const char *s)
398 int i;
400 map = isl_map_cow(map);
401 if (!map)
402 return NULL;
404 map->dim = isl_space_set_tuple_name(map->dim, type, s);
405 if (!map->dim)
406 goto error;
408 for (i = 0; i < map->n; ++i) {
409 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
410 if (!map->p[i])
411 goto error;
414 return map;
415 error:
416 isl_map_free(map);
417 return NULL;
420 /* Does the input or output tuple have a name?
422 int isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
424 return map ? isl_space_has_tuple_name(map->dim, type) : -1;
427 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
428 enum isl_dim_type type)
430 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
433 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
434 const char *s)
436 return (isl_set *)isl_map_set_tuple_name((isl_map *)set, isl_dim_set, s);
439 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
440 enum isl_dim_type type, __isl_take isl_id *id)
442 map = isl_map_cow(map);
443 if (!map)
444 return isl_id_free(id);
446 map->dim = isl_space_set_tuple_id(map->dim, type, id);
448 return isl_map_reset_space(map, isl_space_copy(map->dim));
451 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
452 __isl_take isl_id *id)
454 return isl_map_set_tuple_id(set, isl_dim_set, id);
457 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
458 enum isl_dim_type type)
460 map = isl_map_cow(map);
461 if (!map)
462 return NULL;
464 map->dim = isl_space_reset_tuple_id(map->dim, type);
466 return isl_map_reset_space(map, isl_space_copy(map->dim));
469 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
471 return isl_map_reset_tuple_id(set, isl_dim_set);
474 int isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
476 return map ? isl_space_has_tuple_id(map->dim, type) : -1;
479 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
480 enum isl_dim_type type)
482 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
485 int isl_set_has_tuple_id(__isl_keep isl_set *set)
487 return isl_map_has_tuple_id(set, isl_dim_set);
490 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
492 return isl_map_get_tuple_id(set, isl_dim_set);
495 /* Does the set tuple have a name?
497 int isl_set_has_tuple_name(__isl_keep isl_set *set)
499 return set ? isl_space_has_tuple_name(set->dim, isl_dim_set) : -1;
503 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
505 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
508 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
510 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
513 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
514 enum isl_dim_type type, unsigned pos)
516 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
519 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
520 enum isl_dim_type type, unsigned pos)
522 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
525 /* Does the given dimension have a name?
527 int isl_map_has_dim_name(__isl_keep isl_map *map,
528 enum isl_dim_type type, unsigned pos)
530 return map ? isl_space_has_dim_name(map->dim, type, pos) : -1;
533 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
534 enum isl_dim_type type, unsigned pos)
536 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
539 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
540 enum isl_dim_type type, unsigned pos)
542 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
545 /* Does the given dimension have a name?
547 int isl_set_has_dim_name(__isl_keep isl_set *set,
548 enum isl_dim_type type, unsigned pos)
550 return set ? isl_space_has_dim_name(set->dim, type, pos) : -1;
553 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
554 __isl_take isl_basic_map *bmap,
555 enum isl_dim_type type, unsigned pos, const char *s)
557 bmap = isl_basic_map_cow(bmap);
558 if (!bmap)
559 return NULL;
560 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
561 if (!bmap->dim)
562 goto error;
563 return isl_basic_map_finalize(bmap);
564 error:
565 isl_basic_map_free(bmap);
566 return NULL;
569 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
570 enum isl_dim_type type, unsigned pos, const char *s)
572 int i;
574 map = isl_map_cow(map);
575 if (!map)
576 return NULL;
578 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
579 if (!map->dim)
580 goto error;
582 for (i = 0; i < map->n; ++i) {
583 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
584 if (!map->p[i])
585 goto error;
588 return map;
589 error:
590 isl_map_free(map);
591 return NULL;
594 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
595 __isl_take isl_basic_set *bset,
596 enum isl_dim_type type, unsigned pos, const char *s)
598 return (isl_basic_set *)isl_basic_map_set_dim_name(
599 (isl_basic_map *)bset, type, pos, s);
602 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
603 enum isl_dim_type type, unsigned pos, const char *s)
605 return (isl_set *)isl_map_set_dim_name((isl_map *)set, type, pos, s);
608 int isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
609 enum isl_dim_type type, unsigned pos)
611 return bmap ? isl_space_has_dim_id(bmap->dim, type, pos) : -1;
614 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
615 enum isl_dim_type type, unsigned pos)
617 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
620 int isl_map_has_dim_id(__isl_keep isl_map *map,
621 enum isl_dim_type type, unsigned pos)
623 return map ? isl_space_has_dim_id(map->dim, type, pos) : -1;
626 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
627 enum isl_dim_type type, unsigned pos)
629 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
632 int isl_set_has_dim_id(__isl_keep isl_set *set,
633 enum isl_dim_type type, unsigned pos)
635 return isl_map_has_dim_id(set, type, pos);
638 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
639 enum isl_dim_type type, unsigned pos)
641 return isl_map_get_dim_id(set, type, pos);
644 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
645 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
647 map = isl_map_cow(map);
648 if (!map)
649 return isl_id_free(id);
651 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
653 return isl_map_reset_space(map, isl_space_copy(map->dim));
656 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
657 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
659 return isl_map_set_dim_id(set, type, pos, id);
662 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
663 __isl_keep isl_id *id)
665 if (!map)
666 return -1;
667 return isl_space_find_dim_by_id(map->dim, type, id);
670 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
671 __isl_keep isl_id *id)
673 return isl_map_find_dim_by_id(set, type, id);
676 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
677 const char *name)
679 if (!map)
680 return -1;
681 return isl_space_find_dim_by_name(map->dim, type, name);
684 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
685 const char *name)
687 return isl_map_find_dim_by_name(set, type, name);
690 int isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
692 if (!bmap)
693 return -1;
694 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
697 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
699 return isl_basic_map_is_rational(bset);
702 /* Does "bmap" contain any rational points?
704 * If "bmap" has an equality for each dimension, equating the dimension
705 * to an integer constant, then it has no rational points, even if it
706 * is marked as rational.
708 int isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
710 int has_rational = 1;
711 unsigned total;
713 if (!bmap)
714 return -1;
715 if (isl_basic_map_plain_is_empty(bmap))
716 return 0;
717 if (!isl_basic_map_is_rational(bmap))
718 return 0;
719 bmap = isl_basic_map_copy(bmap);
720 bmap = isl_basic_map_implicit_equalities(bmap);
721 if (!bmap)
722 return -1;
723 total = isl_basic_map_total_dim(bmap);
724 if (bmap->n_eq == total) {
725 int i, j;
726 for (i = 0; i < bmap->n_eq; ++i) {
727 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
728 if (j < 0)
729 break;
730 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
731 !isl_int_is_negone(bmap->eq[i][1 + j]))
732 break;
733 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
734 total - j - 1);
735 if (j >= 0)
736 break;
738 if (i == bmap->n_eq)
739 has_rational = 0;
741 isl_basic_map_free(bmap);
743 return has_rational;
746 /* Does "map" contain any rational points?
748 int isl_map_has_rational(__isl_keep isl_map *map)
750 int i;
751 int has_rational;
753 if (!map)
754 return -1;
755 for (i = 0; i < map->n; ++i) {
756 has_rational = isl_basic_map_has_rational(map->p[i]);
757 if (has_rational < 0)
758 return -1;
759 if (has_rational)
760 return 1;
762 return 0;
765 /* Does "set" contain any rational points?
767 int isl_set_has_rational(__isl_keep isl_set *set)
769 return isl_map_has_rational(set);
772 /* Is this basic set a parameter domain?
774 int isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
776 if (!bset)
777 return -1;
778 return isl_space_is_params(bset->dim);
781 /* Is this set a parameter domain?
783 int isl_set_is_params(__isl_keep isl_set *set)
785 if (!set)
786 return -1;
787 return isl_space_is_params(set->dim);
790 /* Is this map actually a parameter domain?
791 * Users should never call this function. Outside of isl,
792 * a map can never be a parameter domain.
794 int isl_map_is_params(__isl_keep isl_map *map)
796 if (!map)
797 return -1;
798 return isl_space_is_params(map->dim);
801 static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
802 struct isl_basic_map *bmap, unsigned extra,
803 unsigned n_eq, unsigned n_ineq)
805 int i;
806 size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
808 bmap->ctx = ctx;
809 isl_ctx_ref(ctx);
811 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
812 if (isl_blk_is_error(bmap->block))
813 goto error;
815 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
816 if (!bmap->ineq)
817 goto error;
819 if (extra == 0) {
820 bmap->block2 = isl_blk_empty();
821 bmap->div = NULL;
822 } else {
823 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
824 if (isl_blk_is_error(bmap->block2))
825 goto error;
827 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
828 if (!bmap->div)
829 goto error;
832 for (i = 0; i < n_ineq + n_eq; ++i)
833 bmap->ineq[i] = bmap->block.data + i * row_size;
835 for (i = 0; i < extra; ++i)
836 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
838 bmap->ref = 1;
839 bmap->flags = 0;
840 bmap->c_size = n_eq + n_ineq;
841 bmap->eq = bmap->ineq + n_ineq;
842 bmap->extra = extra;
843 bmap->n_eq = 0;
844 bmap->n_ineq = 0;
845 bmap->n_div = 0;
846 bmap->sample = NULL;
848 return bmap;
849 error:
850 isl_basic_map_free(bmap);
851 return NULL;
854 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
855 unsigned nparam, unsigned dim, unsigned extra,
856 unsigned n_eq, unsigned n_ineq)
858 struct isl_basic_map *bmap;
859 isl_space *space;
861 space = isl_space_set_alloc(ctx, nparam, dim);
862 if (!space)
863 return NULL;
865 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
866 return (struct isl_basic_set *)bmap;
869 struct isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
870 unsigned extra, unsigned n_eq, unsigned n_ineq)
872 struct isl_basic_map *bmap;
873 if (!dim)
874 return NULL;
875 isl_assert(dim->ctx, dim->n_in == 0, goto error);
876 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
877 return (struct isl_basic_set *)bmap;
878 error:
879 isl_space_free(dim);
880 return NULL;
883 struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
884 unsigned extra, unsigned n_eq, unsigned n_ineq)
886 struct isl_basic_map *bmap;
888 if (!dim)
889 return NULL;
890 bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
891 if (!bmap)
892 goto error;
893 bmap->dim = dim;
895 return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
896 error:
897 isl_space_free(dim);
898 return NULL;
901 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
902 unsigned nparam, unsigned in, unsigned out, unsigned extra,
903 unsigned n_eq, unsigned n_ineq)
905 struct isl_basic_map *bmap;
906 isl_space *dim;
908 dim = isl_space_alloc(ctx, nparam, in, out);
909 if (!dim)
910 return NULL;
912 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
913 return bmap;
916 static void dup_constraints(
917 struct isl_basic_map *dst, struct isl_basic_map *src)
919 int i;
920 unsigned total = isl_basic_map_total_dim(src);
922 for (i = 0; i < src->n_eq; ++i) {
923 int j = isl_basic_map_alloc_equality(dst);
924 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
927 for (i = 0; i < src->n_ineq; ++i) {
928 int j = isl_basic_map_alloc_inequality(dst);
929 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
932 for (i = 0; i < src->n_div; ++i) {
933 int j = isl_basic_map_alloc_div(dst);
934 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
936 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
939 struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap)
941 struct isl_basic_map *dup;
943 if (!bmap)
944 return NULL;
945 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
946 bmap->n_div, bmap->n_eq, bmap->n_ineq);
947 if (!dup)
948 return NULL;
949 dup_constraints(dup, bmap);
950 dup->flags = bmap->flags;
951 dup->sample = isl_vec_copy(bmap->sample);
952 return dup;
955 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
957 struct isl_basic_map *dup;
959 dup = isl_basic_map_dup((struct isl_basic_map *)bset);
960 return (struct isl_basic_set *)dup;
963 struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset)
965 if (!bset)
966 return NULL;
968 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
969 bset->ref++;
970 return bset;
972 return isl_basic_set_dup(bset);
975 struct isl_set *isl_set_copy(struct isl_set *set)
977 if (!set)
978 return NULL;
980 set->ref++;
981 return set;
984 struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap)
986 if (!bmap)
987 return NULL;
989 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
990 bmap->ref++;
991 return bmap;
993 bmap = isl_basic_map_dup(bmap);
994 if (bmap)
995 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
996 return bmap;
999 struct isl_map *isl_map_copy(struct isl_map *map)
1001 if (!map)
1002 return NULL;
1004 map->ref++;
1005 return map;
1008 void *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1010 if (!bmap)
1011 return NULL;
1013 if (--bmap->ref > 0)
1014 return NULL;
1016 isl_ctx_deref(bmap->ctx);
1017 free(bmap->div);
1018 isl_blk_free(bmap->ctx, bmap->block2);
1019 free(bmap->ineq);
1020 isl_blk_free(bmap->ctx, bmap->block);
1021 isl_vec_free(bmap->sample);
1022 isl_space_free(bmap->dim);
1023 free(bmap);
1025 return NULL;
1028 void *isl_basic_set_free(struct isl_basic_set *bset)
1030 return isl_basic_map_free((struct isl_basic_map *)bset);
1033 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1035 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1038 __isl_give isl_map *isl_map_align_params_map_map_and(
1039 __isl_take isl_map *map1, __isl_take isl_map *map2,
1040 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1041 __isl_take isl_map *map2))
1043 if (!map1 || !map2)
1044 goto error;
1045 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1046 return fn(map1, map2);
1047 if (!isl_space_has_named_params(map1->dim) ||
1048 !isl_space_has_named_params(map2->dim))
1049 isl_die(map1->ctx, isl_error_invalid,
1050 "unaligned unnamed parameters", goto error);
1051 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1052 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1053 return fn(map1, map2);
1054 error:
1055 isl_map_free(map1);
1056 isl_map_free(map2);
1057 return NULL;
1060 int isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1061 __isl_keep isl_map *map2,
1062 int (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1064 int r;
1066 if (!map1 || !map2)
1067 return -1;
1068 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1069 return fn(map1, map2);
1070 if (!isl_space_has_named_params(map1->dim) ||
1071 !isl_space_has_named_params(map2->dim))
1072 isl_die(map1->ctx, isl_error_invalid,
1073 "unaligned unnamed parameters", return -1);
1074 map1 = isl_map_copy(map1);
1075 map2 = isl_map_copy(map2);
1076 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1077 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1078 r = fn(map1, map2);
1079 isl_map_free(map1);
1080 isl_map_free(map2);
1081 return r;
1084 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1086 struct isl_ctx *ctx;
1087 if (!bmap)
1088 return -1;
1089 ctx = bmap->ctx;
1090 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1091 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1092 return -1);
1093 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1094 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1095 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1096 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1097 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1098 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1099 isl_int *t;
1100 int j = isl_basic_map_alloc_inequality(bmap);
1101 if (j < 0)
1102 return -1;
1103 t = bmap->ineq[j];
1104 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1105 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1106 bmap->eq[-1] = t;
1107 bmap->n_eq++;
1108 bmap->n_ineq--;
1109 bmap->eq--;
1110 return 0;
1112 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1113 bmap->extra - bmap->n_div);
1114 return bmap->n_eq++;
1117 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1119 return isl_basic_map_alloc_equality((struct isl_basic_map *)bset);
1122 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1124 if (!bmap)
1125 return -1;
1126 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1127 bmap->n_eq -= n;
1128 return 0;
1131 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1133 return isl_basic_map_free_equality((struct isl_basic_map *)bset, n);
1136 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1138 isl_int *t;
1139 if (!bmap)
1140 return -1;
1141 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1143 if (pos != bmap->n_eq - 1) {
1144 t = bmap->eq[pos];
1145 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1146 bmap->eq[bmap->n_eq - 1] = t;
1148 bmap->n_eq--;
1149 return 0;
1152 int isl_basic_set_drop_equality(struct isl_basic_set *bset, unsigned pos)
1154 return isl_basic_map_drop_equality((struct isl_basic_map *)bset, pos);
1157 /* Turn inequality "pos" of "bmap" into an equality.
1159 * In particular, we move the inequality in front of the equalities
1160 * and move the last inequality in the position of the moved inequality.
1161 * Note that isl_tab_make_equalities_explicit depends on this particular
1162 * change in the ordering of the constraints.
1164 void isl_basic_map_inequality_to_equality(
1165 struct isl_basic_map *bmap, unsigned pos)
1167 isl_int *t;
1169 t = bmap->ineq[pos];
1170 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1171 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1172 bmap->eq[-1] = t;
1173 bmap->n_eq++;
1174 bmap->n_ineq--;
1175 bmap->eq--;
1176 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1177 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1178 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1179 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1182 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1184 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1187 int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap)
1189 struct isl_ctx *ctx;
1190 if (!bmap)
1191 return -1;
1192 ctx = bmap->ctx;
1193 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1194 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1195 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1196 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1197 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1198 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1199 1 + isl_basic_map_total_dim(bmap),
1200 bmap->extra - bmap->n_div);
1201 return bmap->n_ineq++;
1204 int isl_basic_set_alloc_inequality(struct isl_basic_set *bset)
1206 return isl_basic_map_alloc_inequality((struct isl_basic_map *)bset);
1209 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1211 if (!bmap)
1212 return -1;
1213 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1214 bmap->n_ineq -= n;
1215 return 0;
1218 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1220 return isl_basic_map_free_inequality((struct isl_basic_map *)bset, n);
1223 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1225 isl_int *t;
1226 if (!bmap)
1227 return -1;
1228 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1230 if (pos != bmap->n_ineq - 1) {
1231 t = bmap->ineq[pos];
1232 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1233 bmap->ineq[bmap->n_ineq - 1] = t;
1234 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1236 bmap->n_ineq--;
1237 return 0;
1240 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1242 return isl_basic_map_drop_inequality((struct isl_basic_map *)bset, pos);
1245 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1246 isl_int *eq)
1248 int k;
1250 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1251 if (!bmap)
1252 return NULL;
1253 k = isl_basic_map_alloc_equality(bmap);
1254 if (k < 0)
1255 goto error;
1256 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1257 return bmap;
1258 error:
1259 isl_basic_map_free(bmap);
1260 return NULL;
1263 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1264 isl_int *eq)
1266 return (isl_basic_set *)
1267 isl_basic_map_add_eq((isl_basic_map *)bset, eq);
1270 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1271 isl_int *ineq)
1273 int k;
1275 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1276 if (!bmap)
1277 return NULL;
1278 k = isl_basic_map_alloc_inequality(bmap);
1279 if (k < 0)
1280 goto error;
1281 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1282 return bmap;
1283 error:
1284 isl_basic_map_free(bmap);
1285 return NULL;
1288 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1289 isl_int *ineq)
1291 return (isl_basic_set *)
1292 isl_basic_map_add_ineq((isl_basic_map *)bset, ineq);
1295 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1297 if (!bmap)
1298 return -1;
1299 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1300 isl_seq_clr(bmap->div[bmap->n_div] +
1301 1 + 1 + isl_basic_map_total_dim(bmap),
1302 bmap->extra - bmap->n_div);
1303 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1304 return bmap->n_div++;
1307 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1309 return isl_basic_map_alloc_div((struct isl_basic_map *)bset);
1312 int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1314 if (!bmap)
1315 return -1;
1316 isl_assert(bmap->ctx, n <= bmap->n_div, return -1);
1317 bmap->n_div -= n;
1318 return 0;
1321 int isl_basic_set_free_div(struct isl_basic_set *bset, unsigned n)
1323 return isl_basic_map_free_div((struct isl_basic_map *)bset, n);
1326 /* Copy constraint from src to dst, putting the vars of src at offset
1327 * dim_off in dst and the divs of src at offset div_off in dst.
1328 * If both sets are actually map, then dim_off applies to the input
1329 * variables.
1331 static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
1332 struct isl_basic_map *src_map, isl_int *src,
1333 unsigned in_off, unsigned out_off, unsigned div_off)
1335 unsigned src_nparam = isl_basic_map_n_param(src_map);
1336 unsigned dst_nparam = isl_basic_map_n_param(dst_map);
1337 unsigned src_in = isl_basic_map_n_in(src_map);
1338 unsigned dst_in = isl_basic_map_n_in(dst_map);
1339 unsigned src_out = isl_basic_map_n_out(src_map);
1340 unsigned dst_out = isl_basic_map_n_out(dst_map);
1341 isl_int_set(dst[0], src[0]);
1342 isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
1343 if (dst_nparam > src_nparam)
1344 isl_seq_clr(dst+1+src_nparam,
1345 dst_nparam - src_nparam);
1346 isl_seq_clr(dst+1+dst_nparam, in_off);
1347 isl_seq_cpy(dst+1+dst_nparam+in_off,
1348 src+1+src_nparam,
1349 isl_min(dst_in-in_off, src_in));
1350 if (dst_in-in_off > src_in)
1351 isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
1352 dst_in - in_off - src_in);
1353 isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
1354 isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
1355 src+1+src_nparam+src_in,
1356 isl_min(dst_out-out_off, src_out));
1357 if (dst_out-out_off > src_out)
1358 isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
1359 dst_out - out_off - src_out);
1360 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
1361 isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
1362 src+1+src_nparam+src_in+src_out,
1363 isl_min(dst_map->extra-div_off, src_map->n_div));
1364 if (dst_map->n_div-div_off > src_map->n_div)
1365 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
1366 div_off+src_map->n_div,
1367 dst_map->n_div - div_off - src_map->n_div);
1370 static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
1371 struct isl_basic_map *src_map, isl_int *src,
1372 unsigned in_off, unsigned out_off, unsigned div_off)
1374 isl_int_set(dst[0], src[0]);
1375 copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
1378 static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1,
1379 struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos)
1381 int i;
1382 unsigned div_off;
1384 if (!bmap1 || !bmap2)
1385 goto error;
1387 div_off = bmap1->n_div;
1389 for (i = 0; i < bmap2->n_eq; ++i) {
1390 int i1 = isl_basic_map_alloc_equality(bmap1);
1391 if (i1 < 0)
1392 goto error;
1393 copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
1394 i_pos, o_pos, div_off);
1397 for (i = 0; i < bmap2->n_ineq; ++i) {
1398 int i1 = isl_basic_map_alloc_inequality(bmap1);
1399 if (i1 < 0)
1400 goto error;
1401 copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
1402 i_pos, o_pos, div_off);
1405 for (i = 0; i < bmap2->n_div; ++i) {
1406 int i1 = isl_basic_map_alloc_div(bmap1);
1407 if (i1 < 0)
1408 goto error;
1409 copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
1410 i_pos, o_pos, div_off);
1413 isl_basic_map_free(bmap2);
1415 return bmap1;
1417 error:
1418 isl_basic_map_free(bmap1);
1419 isl_basic_map_free(bmap2);
1420 return NULL;
1423 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1424 struct isl_basic_set *bset2, unsigned pos)
1426 return (struct isl_basic_set *)
1427 add_constraints((struct isl_basic_map *)bset1,
1428 (struct isl_basic_map *)bset2, 0, pos);
1431 struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base,
1432 __isl_take isl_space *dim, unsigned extra,
1433 unsigned n_eq, unsigned n_ineq)
1435 struct isl_basic_map *ext;
1436 unsigned flags;
1437 int dims_ok;
1439 if (!dim)
1440 goto error;
1442 if (!base)
1443 goto error;
1445 dims_ok = isl_space_is_equal(base->dim, dim) &&
1446 base->extra >= base->n_div + extra;
1448 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1449 room_for_ineq(base, n_ineq)) {
1450 isl_space_free(dim);
1451 return base;
1454 isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
1455 isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
1456 isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
1457 extra += base->extra;
1458 n_eq += base->n_eq;
1459 n_ineq += base->n_ineq;
1461 ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1462 dim = NULL;
1463 if (!ext)
1464 goto error;
1466 if (dims_ok)
1467 ext->sample = isl_vec_copy(base->sample);
1468 flags = base->flags;
1469 ext = add_constraints(ext, base, 0, 0);
1470 if (ext) {
1471 ext->flags = flags;
1472 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1475 return ext;
1477 error:
1478 isl_space_free(dim);
1479 isl_basic_map_free(base);
1480 return NULL;
1483 struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base,
1484 __isl_take isl_space *dim, unsigned extra,
1485 unsigned n_eq, unsigned n_ineq)
1487 return (struct isl_basic_set *)
1488 isl_basic_map_extend_space((struct isl_basic_map *)base, dim,
1489 extra, n_eq, n_ineq);
1492 struct isl_basic_map *isl_basic_map_extend_constraints(
1493 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1495 if (!base)
1496 return NULL;
1497 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1498 0, n_eq, n_ineq);
1501 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1502 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1503 unsigned n_eq, unsigned n_ineq)
1505 struct isl_basic_map *bmap;
1506 isl_space *dim;
1508 if (!base)
1509 return NULL;
1510 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1511 if (!dim)
1512 goto error;
1514 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1515 return bmap;
1516 error:
1517 isl_basic_map_free(base);
1518 return NULL;
1521 struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
1522 unsigned nparam, unsigned dim, unsigned extra,
1523 unsigned n_eq, unsigned n_ineq)
1525 return (struct isl_basic_set *)
1526 isl_basic_map_extend((struct isl_basic_map *)base,
1527 nparam, 0, dim, extra, n_eq, n_ineq);
1530 struct isl_basic_set *isl_basic_set_extend_constraints(
1531 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1533 return (struct isl_basic_set *)
1534 isl_basic_map_extend_constraints((struct isl_basic_map *)base,
1535 n_eq, n_ineq);
1538 struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset)
1540 return (struct isl_basic_set *)
1541 isl_basic_map_cow((struct isl_basic_map *)bset);
1544 struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap)
1546 if (!bmap)
1547 return NULL;
1549 if (bmap->ref > 1) {
1550 bmap->ref--;
1551 bmap = isl_basic_map_dup(bmap);
1553 if (bmap)
1554 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1555 return bmap;
1558 struct isl_set *isl_set_cow(struct isl_set *set)
1560 if (!set)
1561 return NULL;
1563 if (set->ref == 1)
1564 return set;
1565 set->ref--;
1566 return isl_set_dup(set);
1569 struct isl_map *isl_map_cow(struct isl_map *map)
1571 if (!map)
1572 return NULL;
1574 if (map->ref == 1)
1575 return map;
1576 map->ref--;
1577 return isl_map_dup(map);
1580 static void swap_vars(struct isl_blk blk, isl_int *a,
1581 unsigned a_len, unsigned b_len)
1583 isl_seq_cpy(blk.data, a+a_len, b_len);
1584 isl_seq_cpy(blk.data+b_len, a, a_len);
1585 isl_seq_cpy(a, blk.data, b_len+a_len);
1588 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1589 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1591 int i;
1592 struct isl_blk blk;
1594 if (!bmap)
1595 goto error;
1597 isl_assert(bmap->ctx,
1598 pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
1600 if (n1 == 0 || n2 == 0)
1601 return bmap;
1603 bmap = isl_basic_map_cow(bmap);
1604 if (!bmap)
1605 return NULL;
1607 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
1608 if (isl_blk_is_error(blk))
1609 goto error;
1611 for (i = 0; i < bmap->n_eq; ++i)
1612 swap_vars(blk,
1613 bmap->eq[i] + pos, n1, n2);
1615 for (i = 0; i < bmap->n_ineq; ++i)
1616 swap_vars(blk,
1617 bmap->ineq[i] + pos, n1, n2);
1619 for (i = 0; i < bmap->n_div; ++i)
1620 swap_vars(blk,
1621 bmap->div[i]+1 + pos, n1, n2);
1623 isl_blk_free(bmap->ctx, blk);
1625 ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
1626 bmap = isl_basic_map_gauss(bmap, NULL);
1627 return isl_basic_map_finalize(bmap);
1628 error:
1629 isl_basic_map_free(bmap);
1630 return NULL;
1633 static __isl_give isl_basic_set *isl_basic_set_swap_vars(
1634 __isl_take isl_basic_set *bset, unsigned n)
1636 unsigned dim;
1637 unsigned nparam;
1639 if (!bset)
1640 return NULL;
1642 nparam = isl_basic_set_n_param(bset);
1643 dim = isl_basic_set_n_dim(bset);
1644 isl_assert(bset->ctx, n <= dim, goto error);
1646 return isl_basic_map_swap_vars(bset, 1 + nparam, n, dim - n);
1647 error:
1648 isl_basic_set_free(bset);
1649 return NULL;
1652 struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap)
1654 int i = 0;
1655 unsigned total;
1656 if (!bmap)
1657 goto error;
1658 total = isl_basic_map_total_dim(bmap);
1659 isl_basic_map_free_div(bmap, bmap->n_div);
1660 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
1661 if (bmap->n_eq > 0)
1662 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
1663 else {
1664 i = isl_basic_map_alloc_equality(bmap);
1665 if (i < 0)
1666 goto error;
1668 isl_int_set_si(bmap->eq[i][0], 1);
1669 isl_seq_clr(bmap->eq[i]+1, total);
1670 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
1671 isl_vec_free(bmap->sample);
1672 bmap->sample = NULL;
1673 return isl_basic_map_finalize(bmap);
1674 error:
1675 isl_basic_map_free(bmap);
1676 return NULL;
1679 struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset)
1681 return (struct isl_basic_set *)
1682 isl_basic_map_set_to_empty((struct isl_basic_map *)bset);
1685 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
1686 * of "bmap").
1688 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
1690 isl_int *t = bmap->div[a];
1691 bmap->div[a] = bmap->div[b];
1692 bmap->div[b] = t;
1695 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
1696 * div definitions accordingly.
1698 void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
1700 int i;
1701 unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
1703 swap_div(bmap, a, b);
1705 for (i = 0; i < bmap->n_eq; ++i)
1706 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
1708 for (i = 0; i < bmap->n_ineq; ++i)
1709 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
1711 for (i = 0; i < bmap->n_div; ++i)
1712 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
1713 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1716 /* Eliminate the specified n dimensions starting at first from the
1717 * constraints, without removing the dimensions from the space.
1718 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1720 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
1721 enum isl_dim_type type, unsigned first, unsigned n)
1723 int i;
1725 if (!map)
1726 return NULL;
1727 if (n == 0)
1728 return map;
1730 if (first + n > isl_map_dim(map, type) || first + n < first)
1731 isl_die(map->ctx, isl_error_invalid,
1732 "index out of bounds", goto error);
1734 map = isl_map_cow(map);
1735 if (!map)
1736 return NULL;
1738 for (i = 0; i < map->n; ++i) {
1739 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
1740 if (!map->p[i])
1741 goto error;
1743 return map;
1744 error:
1745 isl_map_free(map);
1746 return NULL;
1749 /* Eliminate the specified n dimensions starting at first from the
1750 * constraints, without removing the dimensions from the space.
1751 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1753 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
1754 enum isl_dim_type type, unsigned first, unsigned n)
1756 return (isl_set *)isl_map_eliminate((isl_map *)set, type, first, n);
1759 /* Eliminate the specified n dimensions starting at first from the
1760 * constraints, without removing the dimensions from the space.
1761 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1763 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
1764 unsigned first, unsigned n)
1766 return isl_set_eliminate(set, isl_dim_set, first, n);
1769 __isl_give isl_basic_map *isl_basic_map_remove_divs(
1770 __isl_take isl_basic_map *bmap)
1772 if (!bmap)
1773 return NULL;
1774 bmap = isl_basic_map_eliminate_vars(bmap,
1775 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
1776 if (!bmap)
1777 return NULL;
1778 bmap->n_div = 0;
1779 return isl_basic_map_finalize(bmap);
1782 __isl_give isl_basic_set *isl_basic_set_remove_divs(
1783 __isl_take isl_basic_set *bset)
1785 return (struct isl_basic_set *)isl_basic_map_remove_divs(
1786 (struct isl_basic_map *)bset);
1789 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
1791 int i;
1793 if (!map)
1794 return NULL;
1795 if (map->n == 0)
1796 return map;
1798 map = isl_map_cow(map);
1799 if (!map)
1800 return NULL;
1802 for (i = 0; i < map->n; ++i) {
1803 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
1804 if (!map->p[i])
1805 goto error;
1807 return map;
1808 error:
1809 isl_map_free(map);
1810 return NULL;
1813 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
1815 return isl_map_remove_divs(set);
1818 struct isl_basic_map *isl_basic_map_remove_dims(struct isl_basic_map *bmap,
1819 enum isl_dim_type type, unsigned first, unsigned n)
1821 if (!bmap)
1822 return NULL;
1823 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
1824 goto error);
1825 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
1826 return bmap;
1827 bmap = isl_basic_map_eliminate_vars(bmap,
1828 isl_basic_map_offset(bmap, type) - 1 + first, n);
1829 if (!bmap)
1830 return bmap;
1831 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
1832 return bmap;
1833 bmap = isl_basic_map_drop(bmap, type, first, n);
1834 return bmap;
1835 error:
1836 isl_basic_map_free(bmap);
1837 return NULL;
1840 /* Return true if the definition of the given div (recursively) involves
1841 * any of the given variables.
1843 static int div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
1844 unsigned first, unsigned n)
1846 int i;
1847 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
1849 if (isl_int_is_zero(bmap->div[div][0]))
1850 return 0;
1851 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
1852 return 1;
1854 for (i = bmap->n_div - 1; i >= 0; --i) {
1855 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
1856 continue;
1857 if (div_involves_vars(bmap, i, first, n))
1858 return 1;
1861 return 0;
1864 /* Try and add a lower and/or upper bound on "div" to "bmap"
1865 * based on inequality "i".
1866 * "total" is the total number of variables (excluding the divs).
1867 * "v" is a temporary object that can be used during the calculations.
1868 * If "lb" is set, then a lower bound should be constructed.
1869 * If "ub" is set, then an upper bound should be constructed.
1871 * The calling function has already checked that the inequality does not
1872 * reference "div", but we still need to check that the inequality is
1873 * of the right form. We'll consider the case where we want to construct
1874 * a lower bound. The construction of upper bounds is similar.
1876 * Let "div" be of the form
1878 * q = floor((a + f(x))/d)
1880 * We essentially check if constraint "i" is of the form
1882 * b + f(x) >= 0
1884 * so that we can use it to derive a lower bound on "div".
1885 * However, we allow a slightly more general form
1887 * b + g(x) >= 0
1889 * with the condition that the coefficients of g(x) - f(x) are all
1890 * divisible by d.
1891 * Rewriting this constraint as
1893 * 0 >= -b - g(x)
1895 * adding a + f(x) to both sides and dividing by d, we obtain
1897 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
1899 * Taking the floor on both sides, we obtain
1901 * q >= floor((a-b)/d) + (f(x)-g(x))/d
1903 * or
1905 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
1907 * In the case of an upper bound, we construct the constraint
1909 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
1912 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
1913 __isl_take isl_basic_map *bmap, int div, int i,
1914 unsigned total, isl_int v, int lb, int ub)
1916 int j;
1918 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
1919 if (lb) {
1920 isl_int_sub(v, bmap->ineq[i][1 + j],
1921 bmap->div[div][1 + 1 + j]);
1922 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
1924 if (ub) {
1925 isl_int_add(v, bmap->ineq[i][1 + j],
1926 bmap->div[div][1 + 1 + j]);
1927 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
1930 if (!lb && !ub)
1931 return bmap;
1933 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
1934 if (lb) {
1935 int k = isl_basic_map_alloc_inequality(bmap);
1936 if (k < 0)
1937 goto error;
1938 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
1939 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
1940 bmap->div[div][1 + j]);
1941 isl_int_cdiv_q(bmap->ineq[k][j],
1942 bmap->ineq[k][j], bmap->div[div][0]);
1944 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
1946 if (ub) {
1947 int k = isl_basic_map_alloc_inequality(bmap);
1948 if (k < 0)
1949 goto error;
1950 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
1951 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
1952 bmap->div[div][1 + j]);
1953 isl_int_fdiv_q(bmap->ineq[k][j],
1954 bmap->ineq[k][j], bmap->div[div][0]);
1956 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
1959 return bmap;
1960 error:
1961 isl_basic_map_free(bmap);
1962 return NULL;
1965 /* This function is called right before "div" is eliminated from "bmap"
1966 * using Fourier-Motzkin.
1967 * Look through the constraints of "bmap" for constraints on the argument
1968 * of the integer division and use them to construct constraints on the
1969 * integer division itself. These constraints can then be combined
1970 * during the Fourier-Motzkin elimination.
1971 * Note that it is only useful to introduce lower bounds on "div"
1972 * if "bmap" already contains upper bounds on "div" as the newly
1973 * introduce lower bounds can then be combined with the pre-existing
1974 * upper bounds. Similarly for upper bounds.
1975 * We therefore first check if "bmap" contains any lower and/or upper bounds
1976 * on "div".
1978 * It is interesting to note that the introduction of these constraints
1979 * can indeed lead to more accurate results, even when compared to
1980 * deriving constraints on the argument of "div" from constraints on "div".
1981 * Consider, for example, the set
1983 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
1985 * The second constraint can be rewritten as
1987 * 2 * [(-i-2j+3)/4] + k >= 0
1989 * from which we can derive
1991 * -i - 2j + 3 >= -2k
1993 * or
1995 * i + 2j <= 3 + 2k
1997 * Combined with the first constraint, we obtain
1999 * -3 <= 3 + 2k or k >= -3
2001 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2002 * the first constraint, we obtain
2004 * [(i + 2j)/4] >= [-3/4] = -1
2006 * Combining this constraint with the second constraint, we obtain
2008 * k >= -2
2010 static __isl_give isl_basic_map *insert_bounds_on_div(
2011 __isl_take isl_basic_map *bmap, int div)
2013 int i;
2014 int check_lb, check_ub;
2015 isl_int v;
2016 unsigned total;
2018 if (!bmap)
2019 return NULL;
2021 if (isl_int_is_zero(bmap->div[div][0]))
2022 return bmap;
2024 total = isl_space_dim(bmap->dim, isl_dim_all);
2026 check_lb = 0;
2027 check_ub = 0;
2028 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2029 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2030 if (s > 0)
2031 check_ub = 1;
2032 if (s < 0)
2033 check_lb = 1;
2036 if (!check_lb && !check_ub)
2037 return bmap;
2039 isl_int_init(v);
2041 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2042 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2043 continue;
2045 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2046 check_lb, check_ub);
2049 isl_int_clear(v);
2051 return bmap;
2054 /* Remove all divs (recursively) involving any of the given dimensions
2055 * in their definitions.
2057 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2058 __isl_take isl_basic_map *bmap,
2059 enum isl_dim_type type, unsigned first, unsigned n)
2061 int i;
2063 if (!bmap)
2064 return NULL;
2065 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
2066 goto error);
2067 first += isl_basic_map_offset(bmap, type);
2069 for (i = bmap->n_div - 1; i >= 0; --i) {
2070 if (!div_involves_vars(bmap, i, first, n))
2071 continue;
2072 bmap = insert_bounds_on_div(bmap, i);
2073 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2074 if (!bmap)
2075 return NULL;
2076 i = bmap->n_div;
2079 return bmap;
2080 error:
2081 isl_basic_map_free(bmap);
2082 return NULL;
2085 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2086 __isl_take isl_basic_set *bset,
2087 enum isl_dim_type type, unsigned first, unsigned n)
2089 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2092 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2093 enum isl_dim_type type, unsigned first, unsigned n)
2095 int i;
2097 if (!map)
2098 return NULL;
2099 if (map->n == 0)
2100 return map;
2102 map = isl_map_cow(map);
2103 if (!map)
2104 return NULL;
2106 for (i = 0; i < map->n; ++i) {
2107 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2108 type, first, n);
2109 if (!map->p[i])
2110 goto error;
2112 return map;
2113 error:
2114 isl_map_free(map);
2115 return NULL;
2118 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2119 enum isl_dim_type type, unsigned first, unsigned n)
2121 return (isl_set *)isl_map_remove_divs_involving_dims((isl_map *)set,
2122 type, first, n);
2125 /* Does the desciption of "bmap" depend on the specified dimensions?
2126 * We also check whether the dimensions appear in any of the div definitions.
2127 * In principle there is no need for this check. If the dimensions appear
2128 * in a div definition, they also appear in the defining constraints of that
2129 * div.
2131 int isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2132 enum isl_dim_type type, unsigned first, unsigned n)
2134 int i;
2136 if (!bmap)
2137 return -1;
2139 if (first + n > isl_basic_map_dim(bmap, type))
2140 isl_die(bmap->ctx, isl_error_invalid,
2141 "index out of bounds", return -1);
2143 first += isl_basic_map_offset(bmap, type);
2144 for (i = 0; i < bmap->n_eq; ++i)
2145 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2146 return 1;
2147 for (i = 0; i < bmap->n_ineq; ++i)
2148 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2149 return 1;
2150 for (i = 0; i < bmap->n_div; ++i) {
2151 if (isl_int_is_zero(bmap->div[i][0]))
2152 continue;
2153 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2154 return 1;
2157 return 0;
2160 int isl_map_involves_dims(__isl_keep isl_map *map,
2161 enum isl_dim_type type, unsigned first, unsigned n)
2163 int i;
2165 if (!map)
2166 return -1;
2168 if (first + n > isl_map_dim(map, type))
2169 isl_die(map->ctx, isl_error_invalid,
2170 "index out of bounds", return -1);
2172 for (i = 0; i < map->n; ++i) {
2173 int involves = isl_basic_map_involves_dims(map->p[i],
2174 type, first, n);
2175 if (involves < 0 || involves)
2176 return involves;
2179 return 0;
2182 int isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2183 enum isl_dim_type type, unsigned first, unsigned n)
2185 return isl_basic_map_involves_dims(bset, type, first, n);
2188 int isl_set_involves_dims(__isl_keep isl_set *set,
2189 enum isl_dim_type type, unsigned first, unsigned n)
2191 return isl_map_involves_dims(set, type, first, n);
2194 /* Return true if the definition of the given div is unknown or depends
2195 * on unknown divs.
2197 static int div_is_unknown(__isl_keep isl_basic_map *bmap, int div)
2199 int i;
2200 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2202 if (isl_int_is_zero(bmap->div[div][0]))
2203 return 1;
2205 for (i = bmap->n_div - 1; i >= 0; --i) {
2206 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2207 continue;
2208 if (div_is_unknown(bmap, i))
2209 return 1;
2212 return 0;
2215 /* Remove all divs that are unknown or defined in terms of unknown divs.
2217 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
2218 __isl_take isl_basic_map *bmap)
2220 int i;
2222 if (!bmap)
2223 return NULL;
2225 for (i = bmap->n_div - 1; i >= 0; --i) {
2226 if (!div_is_unknown(bmap, i))
2227 continue;
2228 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2229 if (!bmap)
2230 return NULL;
2231 i = bmap->n_div;
2234 return bmap;
2237 /* Remove all divs that are unknown or defined in terms of unknown divs.
2239 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
2240 __isl_take isl_basic_set *bset)
2242 return isl_basic_map_remove_unknown_divs(bset);
2245 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
2247 int i;
2249 if (!map)
2250 return NULL;
2251 if (map->n == 0)
2252 return map;
2254 map = isl_map_cow(map);
2255 if (!map)
2256 return NULL;
2258 for (i = 0; i < map->n; ++i) {
2259 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
2260 if (!map->p[i])
2261 goto error;
2263 return map;
2264 error:
2265 isl_map_free(map);
2266 return NULL;
2269 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
2271 return (isl_set *)isl_map_remove_unknown_divs((isl_map *)set);
2274 __isl_give isl_basic_set *isl_basic_set_remove_dims(
2275 __isl_take isl_basic_set *bset,
2276 enum isl_dim_type type, unsigned first, unsigned n)
2278 return (isl_basic_set *)
2279 isl_basic_map_remove_dims((isl_basic_map *)bset, type, first, n);
2282 struct isl_map *isl_map_remove_dims(struct isl_map *map,
2283 enum isl_dim_type type, unsigned first, unsigned n)
2285 int i;
2287 if (n == 0)
2288 return map;
2290 map = isl_map_cow(map);
2291 if (!map)
2292 return NULL;
2293 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
2295 for (i = 0; i < map->n; ++i) {
2296 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
2297 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
2298 if (!map->p[i])
2299 goto error;
2301 map = isl_map_drop(map, type, first, n);
2302 return map;
2303 error:
2304 isl_map_free(map);
2305 return NULL;
2308 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
2309 enum isl_dim_type type, unsigned first, unsigned n)
2311 return (isl_set *)isl_map_remove_dims((isl_map *)bset, type, first, n);
2314 /* Project out n inputs starting at first using Fourier-Motzkin */
2315 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
2316 unsigned first, unsigned n)
2318 return isl_map_remove_dims(map, isl_dim_in, first, n);
2321 static void dump_term(struct isl_basic_map *bmap,
2322 isl_int c, int pos, FILE *out)
2324 const char *name;
2325 unsigned in = isl_basic_map_n_in(bmap);
2326 unsigned dim = in + isl_basic_map_n_out(bmap);
2327 unsigned nparam = isl_basic_map_n_param(bmap);
2328 if (!pos)
2329 isl_int_print(out, c, 0);
2330 else {
2331 if (!isl_int_is_one(c))
2332 isl_int_print(out, c, 0);
2333 if (pos < 1 + nparam) {
2334 name = isl_space_get_dim_name(bmap->dim,
2335 isl_dim_param, pos - 1);
2336 if (name)
2337 fprintf(out, "%s", name);
2338 else
2339 fprintf(out, "p%d", pos - 1);
2340 } else if (pos < 1 + nparam + in)
2341 fprintf(out, "i%d", pos - 1 - nparam);
2342 else if (pos < 1 + nparam + dim)
2343 fprintf(out, "o%d", pos - 1 - nparam - in);
2344 else
2345 fprintf(out, "e%d", pos - 1 - nparam - dim);
2349 static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
2350 int sign, FILE *out)
2352 int i;
2353 int first;
2354 unsigned len = 1 + isl_basic_map_total_dim(bmap);
2355 isl_int v;
2357 isl_int_init(v);
2358 for (i = 0, first = 1; i < len; ++i) {
2359 if (isl_int_sgn(c[i]) * sign <= 0)
2360 continue;
2361 if (!first)
2362 fprintf(out, " + ");
2363 first = 0;
2364 isl_int_abs(v, c[i]);
2365 dump_term(bmap, v, i, out);
2367 isl_int_clear(v);
2368 if (first)
2369 fprintf(out, "0");
2372 static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
2373 const char *op, FILE *out, int indent)
2375 int i;
2377 fprintf(out, "%*s", indent, "");
2379 dump_constraint_sign(bmap, c, 1, out);
2380 fprintf(out, " %s ", op);
2381 dump_constraint_sign(bmap, c, -1, out);
2383 fprintf(out, "\n");
2385 for (i = bmap->n_div; i < bmap->extra; ++i) {
2386 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
2387 continue;
2388 fprintf(out, "%*s", indent, "");
2389 fprintf(out, "ERROR: unused div coefficient not zero\n");
2390 abort();
2394 static void dump_constraints(struct isl_basic_map *bmap,
2395 isl_int **c, unsigned n,
2396 const char *op, FILE *out, int indent)
2398 int i;
2400 for (i = 0; i < n; ++i)
2401 dump_constraint(bmap, c[i], op, out, indent);
2404 static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
2406 int j;
2407 int first = 1;
2408 unsigned total = isl_basic_map_total_dim(bmap);
2410 for (j = 0; j < 1 + total; ++j) {
2411 if (isl_int_is_zero(exp[j]))
2412 continue;
2413 if (!first && isl_int_is_pos(exp[j]))
2414 fprintf(out, "+");
2415 dump_term(bmap, exp[j], j, out);
2416 first = 0;
2420 static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
2422 int i;
2424 dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
2425 dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
2427 for (i = 0; i < bmap->n_div; ++i) {
2428 fprintf(out, "%*s", indent, "");
2429 fprintf(out, "e%d = [(", i);
2430 dump_affine(bmap, bmap->div[i]+1, out);
2431 fprintf(out, ")/");
2432 isl_int_print(out, bmap->div[i][0], 0);
2433 fprintf(out, "]\n");
2437 void isl_basic_set_print_internal(struct isl_basic_set *bset,
2438 FILE *out, int indent)
2440 if (!bset) {
2441 fprintf(out, "null basic set\n");
2442 return;
2445 fprintf(out, "%*s", indent, "");
2446 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
2447 bset->ref, bset->dim->nparam, bset->dim->n_out,
2448 bset->extra, bset->flags);
2449 dump((struct isl_basic_map *)bset, out, indent);
2452 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
2453 FILE *out, int indent)
2455 if (!bmap) {
2456 fprintf(out, "null basic map\n");
2457 return;
2460 fprintf(out, "%*s", indent, "");
2461 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
2462 "flags: %x, n_name: %d\n",
2463 bmap->ref,
2464 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
2465 bmap->extra, bmap->flags, bmap->dim->n_id);
2466 dump(bmap, out, indent);
2469 int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
2471 unsigned total;
2472 if (!bmap)
2473 return -1;
2474 total = isl_basic_map_total_dim(bmap);
2475 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
2476 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
2477 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
2478 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2479 return 0;
2482 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *dim, int n,
2483 unsigned flags)
2485 struct isl_set *set;
2487 if (!dim)
2488 return NULL;
2489 isl_assert(dim->ctx, dim->n_in == 0, goto error);
2490 isl_assert(dim->ctx, n >= 0, goto error);
2491 set = isl_alloc(dim->ctx, struct isl_set,
2492 sizeof(struct isl_set) +
2493 (n - 1) * sizeof(struct isl_basic_set *));
2494 if (!set)
2495 goto error;
2497 set->ctx = dim->ctx;
2498 isl_ctx_ref(set->ctx);
2499 set->ref = 1;
2500 set->size = n;
2501 set->n = 0;
2502 set->dim = dim;
2503 set->flags = flags;
2504 return set;
2505 error:
2506 isl_space_free(dim);
2507 return NULL;
2510 struct isl_set *isl_set_alloc(struct isl_ctx *ctx,
2511 unsigned nparam, unsigned dim, int n, unsigned flags)
2513 struct isl_set *set;
2514 isl_space *dims;
2516 dims = isl_space_alloc(ctx, nparam, 0, dim);
2517 if (!dims)
2518 return NULL;
2520 set = isl_set_alloc_space(dims, n, flags);
2521 return set;
2524 /* Make sure "map" has room for at least "n" more basic maps.
2526 struct isl_map *isl_map_grow(struct isl_map *map, int n)
2528 int i;
2529 struct isl_map *grown = NULL;
2531 if (!map)
2532 return NULL;
2533 isl_assert(map->ctx, n >= 0, goto error);
2534 if (map->n + n <= map->size)
2535 return map;
2536 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
2537 if (!grown)
2538 goto error;
2539 for (i = 0; i < map->n; ++i) {
2540 grown->p[i] = isl_basic_map_copy(map->p[i]);
2541 if (!grown->p[i])
2542 goto error;
2543 grown->n++;
2545 isl_map_free(map);
2546 return grown;
2547 error:
2548 isl_map_free(grown);
2549 isl_map_free(map);
2550 return NULL;
2553 /* Make sure "set" has room for at least "n" more basic sets.
2555 struct isl_set *isl_set_grow(struct isl_set *set, int n)
2557 return (struct isl_set *)isl_map_grow((struct isl_map *)set, n);
2560 struct isl_set *isl_set_dup(struct isl_set *set)
2562 int i;
2563 struct isl_set *dup;
2565 if (!set)
2566 return NULL;
2568 dup = isl_set_alloc_space(isl_space_copy(set->dim), set->n, set->flags);
2569 if (!dup)
2570 return NULL;
2571 for (i = 0; i < set->n; ++i)
2572 dup = isl_set_add_basic_set(dup, isl_basic_set_copy(set->p[i]));
2573 return dup;
2576 struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset)
2578 return isl_map_from_basic_map(bset);
2581 struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap)
2583 struct isl_map *map;
2585 if (!bmap)
2586 return NULL;
2588 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
2589 return isl_map_add_basic_map(map, bmap);
2592 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
2593 __isl_take isl_basic_set *bset)
2595 return (struct isl_set *)isl_map_add_basic_map((struct isl_map *)set,
2596 (struct isl_basic_map *)bset);
2599 void *isl_set_free(__isl_take isl_set *set)
2601 int i;
2603 if (!set)
2604 return NULL;
2606 if (--set->ref > 0)
2607 return NULL;
2609 isl_ctx_deref(set->ctx);
2610 for (i = 0; i < set->n; ++i)
2611 isl_basic_set_free(set->p[i]);
2612 isl_space_free(set->dim);
2613 free(set);
2615 return NULL;
2618 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
2620 int i;
2622 if (!set) {
2623 fprintf(out, "null set\n");
2624 return;
2627 fprintf(out, "%*s", indent, "");
2628 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
2629 set->ref, set->n, set->dim->nparam, set->dim->n_out,
2630 set->flags);
2631 for (i = 0; i < set->n; ++i) {
2632 fprintf(out, "%*s", indent, "");
2633 fprintf(out, "basic set %d:\n", i);
2634 isl_basic_set_print_internal(set->p[i], out, indent+4);
2638 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
2640 int i;
2642 if (!map) {
2643 fprintf(out, "null map\n");
2644 return;
2647 fprintf(out, "%*s", indent, "");
2648 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
2649 "flags: %x, n_name: %d\n",
2650 map->ref, map->n, map->dim->nparam, map->dim->n_in,
2651 map->dim->n_out, map->flags, map->dim->n_id);
2652 for (i = 0; i < map->n; ++i) {
2653 fprintf(out, "%*s", indent, "");
2654 fprintf(out, "basic map %d:\n", i);
2655 isl_basic_map_print_internal(map->p[i], out, indent+4);
2659 struct isl_basic_map *isl_basic_map_intersect_domain(
2660 struct isl_basic_map *bmap, struct isl_basic_set *bset)
2662 struct isl_basic_map *bmap_domain;
2664 if (!bmap || !bset)
2665 goto error;
2667 isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
2668 bset->dim, isl_dim_param), goto error);
2670 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
2671 isl_assert(bset->ctx,
2672 isl_basic_map_compatible_domain(bmap, bset), goto error);
2674 bmap = isl_basic_map_cow(bmap);
2675 if (!bmap)
2676 goto error;
2677 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
2678 bset->n_div, bset->n_eq, bset->n_ineq);
2679 bmap_domain = isl_basic_map_from_domain(bset);
2680 bmap = add_constraints(bmap, bmap_domain, 0, 0);
2682 bmap = isl_basic_map_simplify(bmap);
2683 return isl_basic_map_finalize(bmap);
2684 error:
2685 isl_basic_map_free(bmap);
2686 isl_basic_set_free(bset);
2687 return NULL;
2690 struct isl_basic_map *isl_basic_map_intersect_range(
2691 struct isl_basic_map *bmap, struct isl_basic_set *bset)
2693 struct isl_basic_map *bmap_range;
2695 if (!bmap || !bset)
2696 goto error;
2698 isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
2699 bset->dim, isl_dim_param), goto error);
2701 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
2702 isl_assert(bset->ctx,
2703 isl_basic_map_compatible_range(bmap, bset), goto error);
2705 if (isl_basic_set_is_universe(bset)) {
2706 isl_basic_set_free(bset);
2707 return bmap;
2710 bmap = isl_basic_map_cow(bmap);
2711 if (!bmap)
2712 goto error;
2713 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
2714 bset->n_div, bset->n_eq, bset->n_ineq);
2715 bmap_range = isl_basic_map_from_basic_set(bset, isl_space_copy(bset->dim));
2716 bmap = add_constraints(bmap, bmap_range, 0, 0);
2718 bmap = isl_basic_map_simplify(bmap);
2719 return isl_basic_map_finalize(bmap);
2720 error:
2721 isl_basic_map_free(bmap);
2722 isl_basic_set_free(bset);
2723 return NULL;
2726 int isl_basic_map_contains(struct isl_basic_map *bmap, struct isl_vec *vec)
2728 int i;
2729 unsigned total;
2730 isl_int s;
2732 if (!bmap || !vec)
2733 return -1;
2735 total = 1 + isl_basic_map_total_dim(bmap);
2736 if (total != vec->size)
2737 return -1;
2739 isl_int_init(s);
2741 for (i = 0; i < bmap->n_eq; ++i) {
2742 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
2743 if (!isl_int_is_zero(s)) {
2744 isl_int_clear(s);
2745 return 0;
2749 for (i = 0; i < bmap->n_ineq; ++i) {
2750 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
2751 if (isl_int_is_neg(s)) {
2752 isl_int_clear(s);
2753 return 0;
2757 isl_int_clear(s);
2759 return 1;
2762 int isl_basic_set_contains(struct isl_basic_set *bset, struct isl_vec *vec)
2764 return isl_basic_map_contains((struct isl_basic_map *)bset, vec);
2767 struct isl_basic_map *isl_basic_map_intersect(
2768 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
2770 struct isl_vec *sample = NULL;
2772 if (!bmap1 || !bmap2)
2773 goto error;
2775 isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
2776 bmap2->dim, isl_dim_param), goto error);
2777 if (isl_space_dim(bmap1->dim, isl_dim_all) ==
2778 isl_space_dim(bmap1->dim, isl_dim_param) &&
2779 isl_space_dim(bmap2->dim, isl_dim_all) !=
2780 isl_space_dim(bmap2->dim, isl_dim_param))
2781 return isl_basic_map_intersect(bmap2, bmap1);
2783 if (isl_space_dim(bmap2->dim, isl_dim_all) !=
2784 isl_space_dim(bmap2->dim, isl_dim_param))
2785 isl_assert(bmap1->ctx,
2786 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
2788 if (bmap1->sample &&
2789 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
2790 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
2791 sample = isl_vec_copy(bmap1->sample);
2792 else if (bmap2->sample &&
2793 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
2794 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
2795 sample = isl_vec_copy(bmap2->sample);
2797 bmap1 = isl_basic_map_cow(bmap1);
2798 if (!bmap1)
2799 goto error;
2800 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
2801 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
2802 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
2804 if (!bmap1)
2805 isl_vec_free(sample);
2806 else if (sample) {
2807 isl_vec_free(bmap1->sample);
2808 bmap1->sample = sample;
2811 bmap1 = isl_basic_map_simplify(bmap1);
2812 return isl_basic_map_finalize(bmap1);
2813 error:
2814 if (sample)
2815 isl_vec_free(sample);
2816 isl_basic_map_free(bmap1);
2817 isl_basic_map_free(bmap2);
2818 return NULL;
2821 struct isl_basic_set *isl_basic_set_intersect(
2822 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
2824 return (struct isl_basic_set *)
2825 isl_basic_map_intersect(
2826 (struct isl_basic_map *)bset1,
2827 (struct isl_basic_map *)bset2);
2830 __isl_give isl_basic_set *isl_basic_set_intersect_params(
2831 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
2833 return isl_basic_set_intersect(bset1, bset2);
2836 /* Special case of isl_map_intersect, where both map1 and map2
2837 * are convex, without any divs and such that either map1 or map2
2838 * contains a single constraint. This constraint is then simply
2839 * added to the other map.
2841 static __isl_give isl_map *map_intersect_add_constraint(
2842 __isl_take isl_map *map1, __isl_take isl_map *map2)
2844 isl_assert(map1->ctx, map1->n == 1, goto error);
2845 isl_assert(map2->ctx, map1->n == 1, goto error);
2846 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
2847 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
2849 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
2850 return isl_map_intersect(map2, map1);
2852 isl_assert(map2->ctx,
2853 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1, goto error);
2855 map1 = isl_map_cow(map1);
2856 if (!map1)
2857 goto error;
2858 if (isl_map_plain_is_empty(map1)) {
2859 isl_map_free(map2);
2860 return map1;
2862 map1->p[0] = isl_basic_map_cow(map1->p[0]);
2863 if (map2->p[0]->n_eq == 1)
2864 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
2865 else
2866 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
2867 map2->p[0]->ineq[0]);
2869 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
2870 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
2871 if (!map1->p[0])
2872 goto error;
2874 if (isl_basic_map_plain_is_empty(map1->p[0])) {
2875 isl_basic_map_free(map1->p[0]);
2876 map1->n = 0;
2879 isl_map_free(map2);
2881 return map1;
2882 error:
2883 isl_map_free(map1);
2884 isl_map_free(map2);
2885 return NULL;
2888 /* map2 may be either a parameter domain or a map living in the same
2889 * space as map1.
2891 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
2892 __isl_take isl_map *map2)
2894 unsigned flags = 0;
2895 isl_map *result;
2896 int i, j;
2898 if (!map1 || !map2)
2899 goto error;
2901 if ((isl_map_plain_is_empty(map1) ||
2902 isl_map_plain_is_universe(map2)) &&
2903 isl_space_is_equal(map1->dim, map2->dim)) {
2904 isl_map_free(map2);
2905 return map1;
2907 if ((isl_map_plain_is_empty(map2) ||
2908 isl_map_plain_is_universe(map1)) &&
2909 isl_space_is_equal(map1->dim, map2->dim)) {
2910 isl_map_free(map1);
2911 return map2;
2914 if (map1->n == 1 && map2->n == 1 &&
2915 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
2916 isl_space_is_equal(map1->dim, map2->dim) &&
2917 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
2918 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
2919 return map_intersect_add_constraint(map1, map2);
2921 if (isl_space_dim(map2->dim, isl_dim_all) !=
2922 isl_space_dim(map2->dim, isl_dim_param))
2923 isl_assert(map1->ctx,
2924 isl_space_is_equal(map1->dim, map2->dim), goto error);
2926 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
2927 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
2928 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
2930 result = isl_map_alloc_space(isl_space_copy(map1->dim),
2931 map1->n * map2->n, flags);
2932 if (!result)
2933 goto error;
2934 for (i = 0; i < map1->n; ++i)
2935 for (j = 0; j < map2->n; ++j) {
2936 struct isl_basic_map *part;
2937 part = isl_basic_map_intersect(
2938 isl_basic_map_copy(map1->p[i]),
2939 isl_basic_map_copy(map2->p[j]));
2940 if (isl_basic_map_is_empty(part) < 0)
2941 part = isl_basic_map_free(part);
2942 result = isl_map_add_basic_map(result, part);
2943 if (!result)
2944 goto error;
2946 isl_map_free(map1);
2947 isl_map_free(map2);
2948 return result;
2949 error:
2950 isl_map_free(map1);
2951 isl_map_free(map2);
2952 return NULL;
2955 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
2956 __isl_take isl_map *map2)
2958 if (!map1 || !map2)
2959 goto error;
2960 if (!isl_space_is_equal(map1->dim, map2->dim))
2961 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
2962 "spaces don't match", goto error);
2963 return map_intersect_internal(map1, map2);
2964 error:
2965 isl_map_free(map1);
2966 isl_map_free(map2);
2967 return NULL;
2970 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
2971 __isl_take isl_map *map2)
2973 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
2976 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
2978 return (struct isl_set *)
2979 isl_map_intersect((struct isl_map *)set1,
2980 (struct isl_map *)set2);
2983 /* map_intersect_internal accepts intersections
2984 * with parameter domains, so we can just call that function.
2986 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
2987 __isl_take isl_set *params)
2989 return map_intersect_internal(map, params);
2992 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
2993 __isl_take isl_map *map2)
2995 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
2998 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
2999 __isl_take isl_set *params)
3001 return isl_map_intersect_params(set, params);
3004 struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap)
3006 isl_space *dim;
3007 struct isl_basic_set *bset;
3008 unsigned in;
3010 if (!bmap)
3011 return NULL;
3012 bmap = isl_basic_map_cow(bmap);
3013 if (!bmap)
3014 return NULL;
3015 dim = isl_space_reverse(isl_space_copy(bmap->dim));
3016 in = isl_basic_map_n_in(bmap);
3017 bset = isl_basic_set_from_basic_map(bmap);
3018 bset = isl_basic_set_swap_vars(bset, in);
3019 return isl_basic_map_from_basic_set(bset, dim);
3022 static __isl_give isl_basic_map *basic_map_space_reset(
3023 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3025 isl_space *space;
3027 if (!bmap)
3028 return NULL;
3029 if (!isl_space_is_named_or_nested(bmap->dim, type))
3030 return bmap;
3032 space = isl_basic_map_get_space(bmap);
3033 space = isl_space_reset(space, type);
3034 bmap = isl_basic_map_reset_space(bmap, space);
3035 return bmap;
3038 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3039 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3040 unsigned pos, unsigned n)
3042 isl_space *res_dim;
3043 struct isl_basic_map *res;
3044 struct isl_dim_map *dim_map;
3045 unsigned total, off;
3046 enum isl_dim_type t;
3048 if (n == 0)
3049 return basic_map_space_reset(bmap, type);
3051 if (!bmap)
3052 return NULL;
3054 res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n);
3056 total = isl_basic_map_total_dim(bmap) + n;
3057 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3058 off = 0;
3059 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3060 if (t != type) {
3061 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3062 } else {
3063 unsigned size = isl_basic_map_dim(bmap, t);
3064 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3065 0, pos, off);
3066 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3067 pos, size - pos, off + pos + n);
3069 off += isl_space_dim(res_dim, t);
3071 isl_dim_map_div(dim_map, bmap, off);
3073 res = isl_basic_map_alloc_space(res_dim,
3074 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3075 if (isl_basic_map_is_rational(bmap))
3076 res = isl_basic_map_set_rational(res);
3077 if (isl_basic_map_plain_is_empty(bmap)) {
3078 isl_basic_map_free(bmap);
3079 free(dim_map);
3080 return isl_basic_map_set_to_empty(res);
3082 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3083 return isl_basic_map_finalize(res);
3086 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3087 __isl_take isl_basic_set *bset,
3088 enum isl_dim_type type, unsigned pos, unsigned n)
3090 return isl_basic_map_insert_dims(bset, type, pos, n);
3093 __isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
3094 enum isl_dim_type type, unsigned n)
3096 if (!bmap)
3097 return NULL;
3098 return isl_basic_map_insert_dims(bmap, type,
3099 isl_basic_map_dim(bmap, type), n);
3102 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3103 enum isl_dim_type type, unsigned n)
3105 if (!bset)
3106 return NULL;
3107 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3108 return (isl_basic_set *)isl_basic_map_add((isl_basic_map *)bset, type, n);
3109 error:
3110 isl_basic_set_free(bset);
3111 return NULL;
3114 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3115 enum isl_dim_type type)
3117 isl_space *space;
3119 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3120 return map;
3122 space = isl_map_get_space(map);
3123 space = isl_space_reset(space, type);
3124 map = isl_map_reset_space(map, space);
3125 return map;
3128 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3129 enum isl_dim_type type, unsigned pos, unsigned n)
3131 int i;
3133 if (n == 0)
3134 return map_space_reset(map, type);
3136 map = isl_map_cow(map);
3137 if (!map)
3138 return NULL;
3140 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3141 if (!map->dim)
3142 goto error;
3144 for (i = 0; i < map->n; ++i) {
3145 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3146 if (!map->p[i])
3147 goto error;
3150 return map;
3151 error:
3152 isl_map_free(map);
3153 return NULL;
3156 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3157 enum isl_dim_type type, unsigned pos, unsigned n)
3159 return isl_map_insert_dims(set, type, pos, n);
3162 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3163 enum isl_dim_type type, unsigned n)
3165 if (!map)
3166 return NULL;
3167 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3170 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3171 enum isl_dim_type type, unsigned n)
3173 if (!set)
3174 return NULL;
3175 isl_assert(set->ctx, type != isl_dim_in, goto error);
3176 return (isl_set *)isl_map_add_dims((isl_map *)set, type, n);
3177 error:
3178 isl_set_free(set);
3179 return NULL;
3182 __isl_give isl_basic_map *isl_basic_map_move_dims(
3183 __isl_take isl_basic_map *bmap,
3184 enum isl_dim_type dst_type, unsigned dst_pos,
3185 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3187 struct isl_dim_map *dim_map;
3188 struct isl_basic_map *res;
3189 enum isl_dim_type t;
3190 unsigned total, off;
3192 if (!bmap)
3193 return NULL;
3194 if (n == 0)
3195 return bmap;
3197 isl_assert(bmap->ctx, src_pos + n <= isl_basic_map_dim(bmap, src_type),
3198 goto error);
3200 if (dst_type == src_type && dst_pos == src_pos)
3201 return bmap;
3203 isl_assert(bmap->ctx, dst_type != src_type, goto error);
3205 if (pos(bmap->dim, dst_type) + dst_pos ==
3206 pos(bmap->dim, src_type) + src_pos +
3207 ((src_type < dst_type) ? n : 0)) {
3208 bmap = isl_basic_map_cow(bmap);
3209 if (!bmap)
3210 return NULL;
3212 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3213 src_type, src_pos, n);
3214 if (!bmap->dim)
3215 goto error;
3217 bmap = isl_basic_map_finalize(bmap);
3219 return bmap;
3222 total = isl_basic_map_total_dim(bmap);
3223 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3225 off = 0;
3226 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3227 unsigned size = isl_space_dim(bmap->dim, t);
3228 if (t == dst_type) {
3229 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3230 0, dst_pos, off);
3231 off += dst_pos;
3232 isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
3233 src_pos, n, off);
3234 off += n;
3235 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3236 dst_pos, size - dst_pos, off);
3237 off += size - dst_pos;
3238 } else if (t == src_type) {
3239 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3240 0, src_pos, off);
3241 off += src_pos;
3242 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3243 src_pos + n, size - src_pos - n, off);
3244 off += size - src_pos - n;
3245 } else {
3246 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3247 off += size;
3250 isl_dim_map_div(dim_map, bmap, off);
3252 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3253 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3254 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3255 if (!bmap)
3256 goto error;
3258 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3259 src_type, src_pos, n);
3260 if (!bmap->dim)
3261 goto error;
3263 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
3264 bmap = isl_basic_map_gauss(bmap, NULL);
3265 bmap = isl_basic_map_finalize(bmap);
3267 return bmap;
3268 error:
3269 isl_basic_map_free(bmap);
3270 return NULL;
3273 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
3274 enum isl_dim_type dst_type, unsigned dst_pos,
3275 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3277 return (isl_basic_set *)isl_basic_map_move_dims(
3278 (isl_basic_map *)bset, dst_type, dst_pos, src_type, src_pos, n);
3281 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
3282 enum isl_dim_type dst_type, unsigned dst_pos,
3283 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3285 if (!set)
3286 return NULL;
3287 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
3288 return (isl_set *)isl_map_move_dims((isl_map *)set, dst_type, dst_pos,
3289 src_type, src_pos, n);
3290 error:
3291 isl_set_free(set);
3292 return NULL;
3295 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
3296 enum isl_dim_type dst_type, unsigned dst_pos,
3297 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3299 int i;
3301 if (!map)
3302 return NULL;
3303 if (n == 0)
3304 return map;
3306 isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type),
3307 goto error);
3309 if (dst_type == src_type && dst_pos == src_pos)
3310 return map;
3312 isl_assert(map->ctx, dst_type != src_type, goto error);
3314 map = isl_map_cow(map);
3315 if (!map)
3316 return NULL;
3318 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
3319 if (!map->dim)
3320 goto error;
3322 for (i = 0; i < map->n; ++i) {
3323 map->p[i] = isl_basic_map_move_dims(map->p[i],
3324 dst_type, dst_pos,
3325 src_type, src_pos, n);
3326 if (!map->p[i])
3327 goto error;
3330 return map;
3331 error:
3332 isl_map_free(map);
3333 return NULL;
3336 /* Move the specified dimensions to the last columns right before
3337 * the divs. Don't change the dimension specification of bmap.
3338 * That's the responsibility of the caller.
3340 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
3341 enum isl_dim_type type, unsigned first, unsigned n)
3343 struct isl_dim_map *dim_map;
3344 struct isl_basic_map *res;
3345 enum isl_dim_type t;
3346 unsigned total, off;
3348 if (!bmap)
3349 return NULL;
3350 if (pos(bmap->dim, type) + first + n ==
3351 1 + isl_space_dim(bmap->dim, isl_dim_all))
3352 return bmap;
3354 total = isl_basic_map_total_dim(bmap);
3355 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3357 off = 0;
3358 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3359 unsigned size = isl_space_dim(bmap->dim, t);
3360 if (t == type) {
3361 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3362 0, first, off);
3363 off += first;
3364 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3365 first, n, total - bmap->n_div - n);
3366 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3367 first + n, size - (first + n), off);
3368 off += size - (first + n);
3369 } else {
3370 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3371 off += size;
3374 isl_dim_map_div(dim_map, bmap, off + n);
3376 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3377 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3378 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3379 return res;
3382 /* Insert "n" rows in the divs of "bmap".
3384 * The number of columns is not changed, which means that the last
3385 * dimensions of "bmap" are being reintepreted as the new divs.
3386 * The space of "bmap" is not adjusted, however, which means
3387 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
3388 * from the space of "bmap" is the responsibility of the caller.
3390 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
3391 int n)
3393 int i;
3394 size_t row_size;
3395 isl_int **new_div;
3396 isl_int *old;
3398 bmap = isl_basic_map_cow(bmap);
3399 if (!bmap)
3400 return NULL;
3402 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
3403 old = bmap->block2.data;
3404 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
3405 (bmap->extra + n) * (1 + row_size));
3406 if (!bmap->block2.data)
3407 return isl_basic_map_free(bmap);
3408 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
3409 if (!new_div)
3410 return isl_basic_map_free(bmap);
3411 for (i = 0; i < n; ++i) {
3412 new_div[i] = bmap->block2.data +
3413 (bmap->extra + i) * (1 + row_size);
3414 isl_seq_clr(new_div[i], 1 + row_size);
3416 for (i = 0; i < bmap->extra; ++i)
3417 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
3418 free(bmap->div);
3419 bmap->div = new_div;
3420 bmap->n_div += n;
3421 bmap->extra += n;
3423 return bmap;
3426 /* Turn the n dimensions of type type, starting at first
3427 * into existentially quantified variables.
3429 __isl_give isl_basic_map *isl_basic_map_project_out(
3430 __isl_take isl_basic_map *bmap,
3431 enum isl_dim_type type, unsigned first, unsigned n)
3433 if (n == 0)
3434 return basic_map_space_reset(bmap, type);
3436 if (!bmap)
3437 return NULL;
3439 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
3440 return isl_basic_map_remove_dims(bmap, type, first, n);
3442 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
3443 goto error);
3445 bmap = move_last(bmap, type, first, n);
3446 bmap = isl_basic_map_cow(bmap);
3447 bmap = insert_div_rows(bmap, n);
3448 if (!bmap)
3449 return NULL;
3451 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
3452 if (!bmap->dim)
3453 goto error;
3454 bmap = isl_basic_map_simplify(bmap);
3455 bmap = isl_basic_map_drop_redundant_divs(bmap);
3456 return isl_basic_map_finalize(bmap);
3457 error:
3458 isl_basic_map_free(bmap);
3459 return NULL;
3462 /* Turn the n dimensions of type type, starting at first
3463 * into existentially quantified variables.
3465 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
3466 enum isl_dim_type type, unsigned first, unsigned n)
3468 return (isl_basic_set *)isl_basic_map_project_out(
3469 (isl_basic_map *)bset, type, first, n);
3472 /* Turn the n dimensions of type type, starting at first
3473 * into existentially quantified variables.
3475 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
3476 enum isl_dim_type type, unsigned first, unsigned n)
3478 int i;
3480 if (!map)
3481 return NULL;
3483 if (n == 0)
3484 return map_space_reset(map, type);
3486 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
3488 map = isl_map_cow(map);
3489 if (!map)
3490 return NULL;
3492 map->dim = isl_space_drop_dims(map->dim, type, first, n);
3493 if (!map->dim)
3494 goto error;
3496 for (i = 0; i < map->n; ++i) {
3497 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
3498 if (!map->p[i])
3499 goto error;
3502 return map;
3503 error:
3504 isl_map_free(map);
3505 return NULL;
3508 /* Turn the n dimensions of type type, starting at first
3509 * into existentially quantified variables.
3511 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
3512 enum isl_dim_type type, unsigned first, unsigned n)
3514 return (isl_set *)isl_map_project_out((isl_map *)set, type, first, n);
3517 static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
3519 int i, j;
3521 for (i = 0; i < n; ++i) {
3522 j = isl_basic_map_alloc_div(bmap);
3523 if (j < 0)
3524 goto error;
3525 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
3527 return bmap;
3528 error:
3529 isl_basic_map_free(bmap);
3530 return NULL;
3533 struct isl_basic_map *isl_basic_map_apply_range(
3534 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3536 isl_space *dim_result = NULL;
3537 struct isl_basic_map *bmap;
3538 unsigned n_in, n_out, n, nparam, total, pos;
3539 struct isl_dim_map *dim_map1, *dim_map2;
3541 if (!bmap1 || !bmap2)
3542 goto error;
3544 dim_result = isl_space_join(isl_space_copy(bmap1->dim),
3545 isl_space_copy(bmap2->dim));
3547 n_in = isl_basic_map_n_in(bmap1);
3548 n_out = isl_basic_map_n_out(bmap2);
3549 n = isl_basic_map_n_out(bmap1);
3550 nparam = isl_basic_map_n_param(bmap1);
3552 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
3553 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
3554 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
3555 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
3556 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
3557 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
3558 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
3559 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
3560 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
3561 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
3562 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
3564 bmap = isl_basic_map_alloc_space(dim_result,
3565 bmap1->n_div + bmap2->n_div + n,
3566 bmap1->n_eq + bmap2->n_eq,
3567 bmap1->n_ineq + bmap2->n_ineq);
3568 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
3569 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
3570 bmap = add_divs(bmap, n);
3571 bmap = isl_basic_map_simplify(bmap);
3572 bmap = isl_basic_map_drop_redundant_divs(bmap);
3573 return isl_basic_map_finalize(bmap);
3574 error:
3575 isl_basic_map_free(bmap1);
3576 isl_basic_map_free(bmap2);
3577 return NULL;
3580 struct isl_basic_set *isl_basic_set_apply(
3581 struct isl_basic_set *bset, struct isl_basic_map *bmap)
3583 if (!bset || !bmap)
3584 goto error;
3586 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
3587 goto error);
3589 return (struct isl_basic_set *)
3590 isl_basic_map_apply_range((struct isl_basic_map *)bset, bmap);
3591 error:
3592 isl_basic_set_free(bset);
3593 isl_basic_map_free(bmap);
3594 return NULL;
3597 struct isl_basic_map *isl_basic_map_apply_domain(
3598 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3600 if (!bmap1 || !bmap2)
3601 goto error;
3603 isl_assert(bmap1->ctx,
3604 isl_basic_map_n_in(bmap1) == isl_basic_map_n_in(bmap2), goto error);
3605 isl_assert(bmap1->ctx,
3606 isl_basic_map_n_param(bmap1) == isl_basic_map_n_param(bmap2),
3607 goto error);
3609 bmap1 = isl_basic_map_reverse(bmap1);
3610 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
3611 return isl_basic_map_reverse(bmap1);
3612 error:
3613 isl_basic_map_free(bmap1);
3614 isl_basic_map_free(bmap2);
3615 return NULL;
3618 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
3619 * A \cap B -> f(A) + f(B)
3621 struct isl_basic_map *isl_basic_map_sum(
3622 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3624 unsigned n_in, n_out, nparam, total, pos;
3625 struct isl_basic_map *bmap = NULL;
3626 struct isl_dim_map *dim_map1, *dim_map2;
3627 int i;
3629 if (!bmap1 || !bmap2)
3630 goto error;
3632 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
3633 goto error);
3635 nparam = isl_basic_map_n_param(bmap1);
3636 n_in = isl_basic_map_n_in(bmap1);
3637 n_out = isl_basic_map_n_out(bmap1);
3639 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
3640 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
3641 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
3642 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
3643 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
3644 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
3645 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
3646 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
3647 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
3648 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
3649 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
3651 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
3652 bmap1->n_div + bmap2->n_div + 2 * n_out,
3653 bmap1->n_eq + bmap2->n_eq + n_out,
3654 bmap1->n_ineq + bmap2->n_ineq);
3655 for (i = 0; i < n_out; ++i) {
3656 int j = isl_basic_map_alloc_equality(bmap);
3657 if (j < 0)
3658 goto error;
3659 isl_seq_clr(bmap->eq[j], 1+total);
3660 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
3661 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
3662 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
3664 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
3665 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
3666 bmap = add_divs(bmap, 2 * n_out);
3668 bmap = isl_basic_map_simplify(bmap);
3669 return isl_basic_map_finalize(bmap);
3670 error:
3671 isl_basic_map_free(bmap);
3672 isl_basic_map_free(bmap1);
3673 isl_basic_map_free(bmap2);
3674 return NULL;
3677 /* Given two maps A -> f(A) and B -> g(B), construct a map
3678 * A \cap B -> f(A) + f(B)
3680 struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2)
3682 struct isl_map *result;
3683 int i, j;
3685 if (!map1 || !map2)
3686 goto error;
3688 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
3690 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3691 map1->n * map2->n, 0);
3692 if (!result)
3693 goto error;
3694 for (i = 0; i < map1->n; ++i)
3695 for (j = 0; j < map2->n; ++j) {
3696 struct isl_basic_map *part;
3697 part = isl_basic_map_sum(
3698 isl_basic_map_copy(map1->p[i]),
3699 isl_basic_map_copy(map2->p[j]));
3700 if (isl_basic_map_is_empty(part))
3701 isl_basic_map_free(part);
3702 else
3703 result = isl_map_add_basic_map(result, part);
3704 if (!result)
3705 goto error;
3707 isl_map_free(map1);
3708 isl_map_free(map2);
3709 return result;
3710 error:
3711 isl_map_free(map1);
3712 isl_map_free(map2);
3713 return NULL;
3716 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
3717 __isl_take isl_set *set2)
3719 return (isl_set *)isl_map_sum((isl_map *)set1, (isl_map *)set2);
3722 /* Given a basic map A -> f(A), construct A -> -f(A).
3724 struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap)
3726 int i, j;
3727 unsigned off, n;
3729 bmap = isl_basic_map_cow(bmap);
3730 if (!bmap)
3731 return NULL;
3733 n = isl_basic_map_dim(bmap, isl_dim_out);
3734 off = isl_basic_map_offset(bmap, isl_dim_out);
3735 for (i = 0; i < bmap->n_eq; ++i)
3736 for (j = 0; j < n; ++j)
3737 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
3738 for (i = 0; i < bmap->n_ineq; ++i)
3739 for (j = 0; j < n; ++j)
3740 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
3741 for (i = 0; i < bmap->n_div; ++i)
3742 for (j = 0; j < n; ++j)
3743 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
3744 bmap = isl_basic_map_gauss(bmap, NULL);
3745 return isl_basic_map_finalize(bmap);
3748 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
3750 return isl_basic_map_neg(bset);
3753 /* Given a map A -> f(A), construct A -> -f(A).
3755 struct isl_map *isl_map_neg(struct isl_map *map)
3757 int i;
3759 map = isl_map_cow(map);
3760 if (!map)
3761 return NULL;
3763 for (i = 0; i < map->n; ++i) {
3764 map->p[i] = isl_basic_map_neg(map->p[i]);
3765 if (!map->p[i])
3766 goto error;
3769 return map;
3770 error:
3771 isl_map_free(map);
3772 return NULL;
3775 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
3777 return (isl_set *)isl_map_neg((isl_map *)set);
3780 /* Given a basic map A -> f(A) and an integer d, construct a basic map
3781 * A -> floor(f(A)/d).
3783 struct isl_basic_map *isl_basic_map_floordiv(struct isl_basic_map *bmap,
3784 isl_int d)
3786 unsigned n_in, n_out, nparam, total, pos;
3787 struct isl_basic_map *result = NULL;
3788 struct isl_dim_map *dim_map;
3789 int i;
3791 if (!bmap)
3792 return NULL;
3794 nparam = isl_basic_map_n_param(bmap);
3795 n_in = isl_basic_map_n_in(bmap);
3796 n_out = isl_basic_map_n_out(bmap);
3798 total = nparam + n_in + n_out + bmap->n_div + n_out;
3799 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3800 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
3801 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
3802 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
3803 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
3805 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
3806 bmap->n_div + n_out,
3807 bmap->n_eq, bmap->n_ineq + 2 * n_out);
3808 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
3809 result = add_divs(result, n_out);
3810 for (i = 0; i < n_out; ++i) {
3811 int j;
3812 j = isl_basic_map_alloc_inequality(result);
3813 if (j < 0)
3814 goto error;
3815 isl_seq_clr(result->ineq[j], 1+total);
3816 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
3817 isl_int_set_si(result->ineq[j][1+pos+i], 1);
3818 j = isl_basic_map_alloc_inequality(result);
3819 if (j < 0)
3820 goto error;
3821 isl_seq_clr(result->ineq[j], 1+total);
3822 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
3823 isl_int_set_si(result->ineq[j][1+pos+i], -1);
3824 isl_int_sub_ui(result->ineq[j][0], d, 1);
3827 result = isl_basic_map_simplify(result);
3828 return isl_basic_map_finalize(result);
3829 error:
3830 isl_basic_map_free(result);
3831 return NULL;
3834 /* Given a map A -> f(A) and an integer d, construct a map
3835 * A -> floor(f(A)/d).
3837 struct isl_map *isl_map_floordiv(struct isl_map *map, isl_int d)
3839 int i;
3841 map = isl_map_cow(map);
3842 if (!map)
3843 return NULL;
3845 ISL_F_CLR(map, ISL_MAP_DISJOINT);
3846 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
3847 for (i = 0; i < map->n; ++i) {
3848 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
3849 if (!map->p[i])
3850 goto error;
3853 return map;
3854 error:
3855 isl_map_free(map);
3856 return NULL;
3859 /* Given a map A -> f(A) and an integer d, construct a map
3860 * A -> floor(f(A)/d).
3862 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
3863 __isl_take isl_val *d)
3865 if (!map || !d)
3866 goto error;
3867 if (!isl_val_is_int(d))
3868 isl_die(isl_val_get_ctx(d), isl_error_invalid,
3869 "expecting integer denominator", goto error);
3870 map = isl_map_floordiv(map, d->n);
3871 isl_val_free(d);
3872 return map;
3873 error:
3874 isl_map_free(map);
3875 isl_val_free(d);
3876 return NULL;
3879 static struct isl_basic_map *var_equal(struct isl_basic_map *bmap, unsigned pos)
3881 int i;
3882 unsigned nparam;
3883 unsigned n_in;
3885 i = isl_basic_map_alloc_equality(bmap);
3886 if (i < 0)
3887 goto error;
3888 nparam = isl_basic_map_n_param(bmap);
3889 n_in = isl_basic_map_n_in(bmap);
3890 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
3891 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
3892 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
3893 return isl_basic_map_finalize(bmap);
3894 error:
3895 isl_basic_map_free(bmap);
3896 return NULL;
3899 /* Add a constraints to "bmap" expressing i_pos < o_pos
3901 static struct isl_basic_map *var_less(struct isl_basic_map *bmap, unsigned pos)
3903 int i;
3904 unsigned nparam;
3905 unsigned n_in;
3907 i = isl_basic_map_alloc_inequality(bmap);
3908 if (i < 0)
3909 goto error;
3910 nparam = isl_basic_map_n_param(bmap);
3911 n_in = isl_basic_map_n_in(bmap);
3912 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3913 isl_int_set_si(bmap->ineq[i][0], -1);
3914 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
3915 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
3916 return isl_basic_map_finalize(bmap);
3917 error:
3918 isl_basic_map_free(bmap);
3919 return NULL;
3922 /* Add a constraint to "bmap" expressing i_pos <= o_pos
3924 static __isl_give isl_basic_map *var_less_or_equal(
3925 __isl_take isl_basic_map *bmap, unsigned pos)
3927 int i;
3928 unsigned nparam;
3929 unsigned n_in;
3931 i = isl_basic_map_alloc_inequality(bmap);
3932 if (i < 0)
3933 goto error;
3934 nparam = isl_basic_map_n_param(bmap);
3935 n_in = isl_basic_map_n_in(bmap);
3936 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3937 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
3938 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
3939 return isl_basic_map_finalize(bmap);
3940 error:
3941 isl_basic_map_free(bmap);
3942 return NULL;
3945 /* Add a constraints to "bmap" expressing i_pos > o_pos
3947 static struct isl_basic_map *var_more(struct isl_basic_map *bmap, unsigned pos)
3949 int i;
3950 unsigned nparam;
3951 unsigned n_in;
3953 i = isl_basic_map_alloc_inequality(bmap);
3954 if (i < 0)
3955 goto error;
3956 nparam = isl_basic_map_n_param(bmap);
3957 n_in = isl_basic_map_n_in(bmap);
3958 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3959 isl_int_set_si(bmap->ineq[i][0], -1);
3960 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
3961 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
3962 return isl_basic_map_finalize(bmap);
3963 error:
3964 isl_basic_map_free(bmap);
3965 return NULL;
3968 /* Add a constraint to "bmap" expressing i_pos >= o_pos
3970 static __isl_give isl_basic_map *var_more_or_equal(
3971 __isl_take isl_basic_map *bmap, unsigned pos)
3973 int i;
3974 unsigned nparam;
3975 unsigned n_in;
3977 i = isl_basic_map_alloc_inequality(bmap);
3978 if (i < 0)
3979 goto error;
3980 nparam = isl_basic_map_n_param(bmap);
3981 n_in = isl_basic_map_n_in(bmap);
3982 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3983 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
3984 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
3985 return isl_basic_map_finalize(bmap);
3986 error:
3987 isl_basic_map_free(bmap);
3988 return NULL;
3991 __isl_give isl_basic_map *isl_basic_map_equal(
3992 __isl_take isl_space *dim, unsigned n_equal)
3994 int i;
3995 struct isl_basic_map *bmap;
3996 bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
3997 if (!bmap)
3998 return NULL;
3999 for (i = 0; i < n_equal && bmap; ++i)
4000 bmap = var_equal(bmap, i);
4001 return isl_basic_map_finalize(bmap);
4004 /* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
4006 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
4007 unsigned pos)
4009 int i;
4010 struct isl_basic_map *bmap;
4011 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4012 if (!bmap)
4013 return NULL;
4014 for (i = 0; i < pos && bmap; ++i)
4015 bmap = var_equal(bmap, i);
4016 if (bmap)
4017 bmap = var_less(bmap, pos);
4018 return isl_basic_map_finalize(bmap);
4021 /* Return a relation on of dimension "dim" expressing i_[0..pos] <<= o_[0..pos]
4023 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4024 __isl_take isl_space *dim, unsigned pos)
4026 int i;
4027 isl_basic_map *bmap;
4029 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4030 for (i = 0; i < pos; ++i)
4031 bmap = var_equal(bmap, i);
4032 bmap = var_less_or_equal(bmap, pos);
4033 return isl_basic_map_finalize(bmap);
4036 /* Return a relation on pairs of sets of dimension "dim" expressing i_pos > o_pos
4038 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
4039 unsigned pos)
4041 int i;
4042 struct isl_basic_map *bmap;
4043 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4044 if (!bmap)
4045 return NULL;
4046 for (i = 0; i < pos && bmap; ++i)
4047 bmap = var_equal(bmap, i);
4048 if (bmap)
4049 bmap = var_more(bmap, pos);
4050 return isl_basic_map_finalize(bmap);
4053 /* Return a relation on of dimension "dim" expressing i_[0..pos] >>= o_[0..pos]
4055 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4056 __isl_take isl_space *dim, unsigned pos)
4058 int i;
4059 isl_basic_map *bmap;
4061 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4062 for (i = 0; i < pos; ++i)
4063 bmap = var_equal(bmap, i);
4064 bmap = var_more_or_equal(bmap, pos);
4065 return isl_basic_map_finalize(bmap);
4068 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
4069 unsigned n, int equal)
4071 struct isl_map *map;
4072 int i;
4074 if (n == 0 && equal)
4075 return isl_map_universe(dims);
4077 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4079 for (i = 0; i + 1 < n; ++i)
4080 map = isl_map_add_basic_map(map,
4081 isl_basic_map_less_at(isl_space_copy(dims), i));
4082 if (n > 0) {
4083 if (equal)
4084 map = isl_map_add_basic_map(map,
4085 isl_basic_map_less_or_equal_at(dims, n - 1));
4086 else
4087 map = isl_map_add_basic_map(map,
4088 isl_basic_map_less_at(dims, n - 1));
4089 } else
4090 isl_space_free(dims);
4092 return map;
4095 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
4097 if (!dims)
4098 return NULL;
4099 return map_lex_lte_first(dims, dims->n_out, equal);
4102 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
4104 return map_lex_lte_first(dim, n, 0);
4107 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
4109 return map_lex_lte_first(dim, n, 1);
4112 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
4114 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
4117 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
4119 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
4122 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
4123 unsigned n, int equal)
4125 struct isl_map *map;
4126 int i;
4128 if (n == 0 && equal)
4129 return isl_map_universe(dims);
4131 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4133 for (i = 0; i + 1 < n; ++i)
4134 map = isl_map_add_basic_map(map,
4135 isl_basic_map_more_at(isl_space_copy(dims), i));
4136 if (n > 0) {
4137 if (equal)
4138 map = isl_map_add_basic_map(map,
4139 isl_basic_map_more_or_equal_at(dims, n - 1));
4140 else
4141 map = isl_map_add_basic_map(map,
4142 isl_basic_map_more_at(dims, n - 1));
4143 } else
4144 isl_space_free(dims);
4146 return map;
4149 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
4151 if (!dims)
4152 return NULL;
4153 return map_lex_gte_first(dims, dims->n_out, equal);
4156 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
4158 return map_lex_gte_first(dim, n, 0);
4161 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
4163 return map_lex_gte_first(dim, n, 1);
4166 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
4168 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
4171 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
4173 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
4176 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
4177 __isl_take isl_set *set2)
4179 isl_map *map;
4180 map = isl_map_lex_le(isl_set_get_space(set1));
4181 map = isl_map_intersect_domain(map, set1);
4182 map = isl_map_intersect_range(map, set2);
4183 return map;
4186 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
4187 __isl_take isl_set *set2)
4189 isl_map *map;
4190 map = isl_map_lex_lt(isl_set_get_space(set1));
4191 map = isl_map_intersect_domain(map, set1);
4192 map = isl_map_intersect_range(map, set2);
4193 return map;
4196 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
4197 __isl_take isl_set *set2)
4199 isl_map *map;
4200 map = isl_map_lex_ge(isl_set_get_space(set1));
4201 map = isl_map_intersect_domain(map, set1);
4202 map = isl_map_intersect_range(map, set2);
4203 return map;
4206 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
4207 __isl_take isl_set *set2)
4209 isl_map *map;
4210 map = isl_map_lex_gt(isl_set_get_space(set1));
4211 map = isl_map_intersect_domain(map, set1);
4212 map = isl_map_intersect_range(map, set2);
4213 return map;
4216 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
4217 __isl_take isl_map *map2)
4219 isl_map *map;
4220 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
4221 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4222 map = isl_map_apply_range(map, isl_map_reverse(map2));
4223 return map;
4226 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
4227 __isl_take isl_map *map2)
4229 isl_map *map;
4230 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
4231 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4232 map = isl_map_apply_range(map, isl_map_reverse(map2));
4233 return map;
4236 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
4237 __isl_take isl_map *map2)
4239 isl_map *map;
4240 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
4241 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4242 map = isl_map_apply_range(map, isl_map_reverse(map2));
4243 return map;
4246 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
4247 __isl_take isl_map *map2)
4249 isl_map *map;
4250 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
4251 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4252 map = isl_map_apply_range(map, isl_map_reverse(map2));
4253 return map;
4256 __isl_give isl_basic_map *isl_basic_map_from_basic_set(
4257 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
4259 struct isl_basic_map *bmap;
4261 bset = isl_basic_set_cow(bset);
4262 if (!bset || !dim)
4263 goto error;
4265 isl_assert(bset->ctx, isl_space_compatible(bset->dim, dim), goto error);
4266 isl_space_free(bset->dim);
4267 bmap = (struct isl_basic_map *) bset;
4268 bmap->dim = dim;
4269 return isl_basic_map_finalize(bmap);
4270 error:
4271 isl_basic_set_free(bset);
4272 isl_space_free(dim);
4273 return NULL;
4276 struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap)
4278 if (!bmap)
4279 goto error;
4280 if (bmap->dim->n_in == 0)
4281 return (struct isl_basic_set *)bmap;
4282 bmap = isl_basic_map_cow(bmap);
4283 if (!bmap)
4284 goto error;
4285 bmap->dim = isl_space_as_set_space(bmap->dim);
4286 if (!bmap->dim)
4287 goto error;
4288 bmap = isl_basic_map_finalize(bmap);
4289 return (struct isl_basic_set *)bmap;
4290 error:
4291 isl_basic_map_free(bmap);
4292 return NULL;
4295 /* For a div d = floor(f/m), add the constraints
4297 * f - m d >= 0
4298 * -(f-(n-1)) + m d >= 0
4300 * Note that the second constraint is the negation of
4302 * f - m d >= n
4304 int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
4305 unsigned pos, isl_int *div)
4307 int i, j;
4308 unsigned total = isl_basic_map_total_dim(bmap);
4310 i = isl_basic_map_alloc_inequality(bmap);
4311 if (i < 0)
4312 return -1;
4313 isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
4314 isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
4316 j = isl_basic_map_alloc_inequality(bmap);
4317 if (j < 0)
4318 return -1;
4319 isl_seq_neg(bmap->ineq[j], bmap->ineq[i], 1 + total);
4320 isl_int_add(bmap->ineq[j][0], bmap->ineq[j][0], bmap->ineq[j][1 + pos]);
4321 isl_int_sub_ui(bmap->ineq[j][0], bmap->ineq[j][0], 1);
4322 return j;
4325 int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
4326 unsigned pos, isl_int *div)
4328 return isl_basic_map_add_div_constraints_var((isl_basic_map *)bset,
4329 pos, div);
4332 int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
4334 unsigned total = isl_basic_map_total_dim(bmap);
4335 unsigned div_pos = total - bmap->n_div + div;
4337 return isl_basic_map_add_div_constraints_var(bmap, div_pos,
4338 bmap->div[div]);
4341 int isl_basic_set_add_div_constraints(struct isl_basic_set *bset, unsigned div)
4343 return isl_basic_map_add_div_constraints(bset, div);
4346 struct isl_basic_set *isl_basic_map_underlying_set(
4347 struct isl_basic_map *bmap)
4349 if (!bmap)
4350 goto error;
4351 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
4352 bmap->n_div == 0 &&
4353 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
4354 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
4355 return (struct isl_basic_set *)bmap;
4356 bmap = isl_basic_map_cow(bmap);
4357 if (!bmap)
4358 goto error;
4359 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
4360 if (!bmap->dim)
4361 goto error;
4362 bmap->extra -= bmap->n_div;
4363 bmap->n_div = 0;
4364 bmap = isl_basic_map_finalize(bmap);
4365 return (struct isl_basic_set *)bmap;
4366 error:
4367 isl_basic_map_free(bmap);
4368 return NULL;
4371 __isl_give isl_basic_set *isl_basic_set_underlying_set(
4372 __isl_take isl_basic_set *bset)
4374 return isl_basic_map_underlying_set((isl_basic_map *)bset);
4377 struct isl_basic_map *isl_basic_map_overlying_set(
4378 struct isl_basic_set *bset, struct isl_basic_map *like)
4380 struct isl_basic_map *bmap;
4381 struct isl_ctx *ctx;
4382 unsigned total;
4383 int i;
4385 if (!bset || !like)
4386 goto error;
4387 ctx = bset->ctx;
4388 isl_assert(ctx, bset->n_div == 0, goto error);
4389 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
4390 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
4391 goto error);
4392 if (isl_space_is_equal(bset->dim, like->dim) && like->n_div == 0) {
4393 isl_basic_map_free(like);
4394 return (struct isl_basic_map *)bset;
4396 bset = isl_basic_set_cow(bset);
4397 if (!bset)
4398 goto error;
4399 total = bset->dim->n_out + bset->extra;
4400 bmap = (struct isl_basic_map *)bset;
4401 isl_space_free(bmap->dim);
4402 bmap->dim = isl_space_copy(like->dim);
4403 if (!bmap->dim)
4404 goto error;
4405 bmap->n_div = like->n_div;
4406 bmap->extra += like->n_div;
4407 if (bmap->extra) {
4408 unsigned ltotal;
4409 isl_int **div;
4410 ltotal = total - bmap->extra + like->extra;
4411 if (ltotal > total)
4412 ltotal = total;
4413 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
4414 bmap->extra * (1 + 1 + total));
4415 if (isl_blk_is_error(bmap->block2))
4416 goto error;
4417 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
4418 if (!div)
4419 goto error;
4420 bmap->div = div;
4421 for (i = 0; i < bmap->extra; ++i)
4422 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
4423 for (i = 0; i < like->n_div; ++i) {
4424 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
4425 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
4427 bmap = isl_basic_map_extend_constraints(bmap,
4428 0, 2 * like->n_div);
4429 for (i = 0; i < like->n_div; ++i) {
4430 if (!bmap)
4431 break;
4432 if (isl_int_is_zero(bmap->div[i][0]))
4433 continue;
4434 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
4435 bmap = isl_basic_map_free(bmap);
4438 isl_basic_map_free(like);
4439 bmap = isl_basic_map_simplify(bmap);
4440 bmap = isl_basic_map_finalize(bmap);
4441 return bmap;
4442 error:
4443 isl_basic_map_free(like);
4444 isl_basic_set_free(bset);
4445 return NULL;
4448 struct isl_basic_set *isl_basic_set_from_underlying_set(
4449 struct isl_basic_set *bset, struct isl_basic_set *like)
4451 return (struct isl_basic_set *)
4452 isl_basic_map_overlying_set(bset, (struct isl_basic_map *)like);
4455 struct isl_set *isl_set_from_underlying_set(
4456 struct isl_set *set, struct isl_basic_set *like)
4458 int i;
4460 if (!set || !like)
4461 goto error;
4462 isl_assert(set->ctx, set->dim->n_out == isl_basic_set_total_dim(like),
4463 goto error);
4464 if (isl_space_is_equal(set->dim, like->dim) && like->n_div == 0) {
4465 isl_basic_set_free(like);
4466 return set;
4468 set = isl_set_cow(set);
4469 if (!set)
4470 goto error;
4471 for (i = 0; i < set->n; ++i) {
4472 set->p[i] = isl_basic_set_from_underlying_set(set->p[i],
4473 isl_basic_set_copy(like));
4474 if (!set->p[i])
4475 goto error;
4477 isl_space_free(set->dim);
4478 set->dim = isl_space_copy(like->dim);
4479 if (!set->dim)
4480 goto error;
4481 isl_basic_set_free(like);
4482 return set;
4483 error:
4484 isl_basic_set_free(like);
4485 isl_set_free(set);
4486 return NULL;
4489 struct isl_set *isl_map_underlying_set(struct isl_map *map)
4491 int i;
4493 map = isl_map_cow(map);
4494 if (!map)
4495 return NULL;
4496 map->dim = isl_space_cow(map->dim);
4497 if (!map->dim)
4498 goto error;
4500 for (i = 1; i < map->n; ++i)
4501 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
4502 goto error);
4503 for (i = 0; i < map->n; ++i) {
4504 map->p[i] = (struct isl_basic_map *)
4505 isl_basic_map_underlying_set(map->p[i]);
4506 if (!map->p[i])
4507 goto error;
4509 if (map->n == 0)
4510 map->dim = isl_space_underlying(map->dim, 0);
4511 else {
4512 isl_space_free(map->dim);
4513 map->dim = isl_space_copy(map->p[0]->dim);
4515 if (!map->dim)
4516 goto error;
4517 return (struct isl_set *)map;
4518 error:
4519 isl_map_free(map);
4520 return NULL;
4523 struct isl_set *isl_set_to_underlying_set(struct isl_set *set)
4525 return (struct isl_set *)isl_map_underlying_set((struct isl_map *)set);
4528 __isl_give isl_basic_map *isl_basic_map_reset_space(
4529 __isl_take isl_basic_map *bmap, __isl_take isl_space *dim)
4531 bmap = isl_basic_map_cow(bmap);
4532 if (!bmap || !dim)
4533 goto error;
4535 isl_space_free(bmap->dim);
4536 bmap->dim = dim;
4538 bmap = isl_basic_map_finalize(bmap);
4540 return bmap;
4541 error:
4542 isl_basic_map_free(bmap);
4543 isl_space_free(dim);
4544 return NULL;
4547 __isl_give isl_basic_set *isl_basic_set_reset_space(
4548 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
4550 return (isl_basic_set *)isl_basic_map_reset_space((isl_basic_map *)bset,
4551 dim);
4554 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
4555 __isl_take isl_space *dim)
4557 int i;
4559 map = isl_map_cow(map);
4560 if (!map || !dim)
4561 goto error;
4563 for (i = 0; i < map->n; ++i) {
4564 map->p[i] = isl_basic_map_reset_space(map->p[i],
4565 isl_space_copy(dim));
4566 if (!map->p[i])
4567 goto error;
4569 isl_space_free(map->dim);
4570 map->dim = dim;
4572 return map;
4573 error:
4574 isl_map_free(map);
4575 isl_space_free(dim);
4576 return NULL;
4579 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
4580 __isl_take isl_space *dim)
4582 return (struct isl_set *) isl_map_reset_space((struct isl_map *)set, dim);
4585 /* Compute the parameter domain of the given basic set.
4587 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
4589 isl_space *space;
4590 unsigned n;
4592 if (isl_basic_set_is_params(bset))
4593 return bset;
4595 n = isl_basic_set_dim(bset, isl_dim_set);
4596 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
4597 space = isl_basic_set_get_space(bset);
4598 space = isl_space_params(space);
4599 bset = isl_basic_set_reset_space(bset, space);
4600 return bset;
4603 /* Construct a zero-dimensional basic set with the given parameter domain.
4605 __isl_give isl_basic_set *isl_basic_set_from_params(
4606 __isl_take isl_basic_set *bset)
4608 isl_space *space;
4609 space = isl_basic_set_get_space(bset);
4610 space = isl_space_set_from_params(space);
4611 bset = isl_basic_set_reset_space(bset, space);
4612 return bset;
4615 /* Compute the parameter domain of the given set.
4617 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
4619 isl_space *space;
4620 unsigned n;
4622 if (isl_set_is_params(set))
4623 return set;
4625 n = isl_set_dim(set, isl_dim_set);
4626 set = isl_set_project_out(set, isl_dim_set, 0, n);
4627 space = isl_set_get_space(set);
4628 space = isl_space_params(space);
4629 set = isl_set_reset_space(set, space);
4630 return set;
4633 /* Construct a zero-dimensional set with the given parameter domain.
4635 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
4637 isl_space *space;
4638 space = isl_set_get_space(set);
4639 space = isl_space_set_from_params(space);
4640 set = isl_set_reset_space(set, space);
4641 return set;
4644 /* Compute the parameter domain of the given map.
4646 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
4648 isl_space *space;
4649 unsigned n;
4651 n = isl_map_dim(map, isl_dim_in);
4652 map = isl_map_project_out(map, isl_dim_in, 0, n);
4653 n = isl_map_dim(map, isl_dim_out);
4654 map = isl_map_project_out(map, isl_dim_out, 0, n);
4655 space = isl_map_get_space(map);
4656 space = isl_space_params(space);
4657 map = isl_map_reset_space(map, space);
4658 return map;
4661 struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
4663 isl_space *dim;
4664 struct isl_basic_set *domain;
4665 unsigned n_in;
4666 unsigned n_out;
4668 if (!bmap)
4669 return NULL;
4670 dim = isl_space_domain(isl_basic_map_get_space(bmap));
4672 n_in = isl_basic_map_n_in(bmap);
4673 n_out = isl_basic_map_n_out(bmap);
4674 domain = isl_basic_set_from_basic_map(bmap);
4675 domain = isl_basic_set_project_out(domain, isl_dim_set, n_in, n_out);
4677 domain = isl_basic_set_reset_space(domain, dim);
4679 return domain;
4682 int isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
4684 if (!bmap)
4685 return -1;
4686 return isl_space_may_be_set(bmap->dim);
4689 /* Is this basic map actually a set?
4690 * Users should never call this function. Outside of isl,
4691 * the type should indicate whether something is a set or a map.
4693 int isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
4695 if (!bmap)
4696 return -1;
4697 return isl_space_is_set(bmap->dim);
4700 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
4702 if (!bmap)
4703 return NULL;
4704 if (isl_basic_map_is_set(bmap))
4705 return bmap;
4706 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
4709 __isl_give isl_basic_map *isl_basic_map_domain_map(
4710 __isl_take isl_basic_map *bmap)
4712 int i, k;
4713 isl_space *dim;
4714 isl_basic_map *domain;
4715 int nparam, n_in, n_out;
4716 unsigned total;
4718 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4719 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4720 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4722 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
4723 domain = isl_basic_map_universe(dim);
4725 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
4726 bmap = isl_basic_map_apply_range(bmap, domain);
4727 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
4729 total = isl_basic_map_total_dim(bmap);
4731 for (i = 0; i < n_in; ++i) {
4732 k = isl_basic_map_alloc_equality(bmap);
4733 if (k < 0)
4734 goto error;
4735 isl_seq_clr(bmap->eq[k], 1 + total);
4736 isl_int_set_si(bmap->eq[k][1 + nparam + i], -1);
4737 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1);
4740 bmap = isl_basic_map_gauss(bmap, NULL);
4741 return isl_basic_map_finalize(bmap);
4742 error:
4743 isl_basic_map_free(bmap);
4744 return NULL;
4747 __isl_give isl_basic_map *isl_basic_map_range_map(
4748 __isl_take isl_basic_map *bmap)
4750 int i, k;
4751 isl_space *dim;
4752 isl_basic_map *range;
4753 int nparam, n_in, n_out;
4754 unsigned total;
4756 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4757 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4758 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4760 dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
4761 range = isl_basic_map_universe(dim);
4763 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
4764 bmap = isl_basic_map_apply_range(bmap, range);
4765 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
4767 total = isl_basic_map_total_dim(bmap);
4769 for (i = 0; i < n_out; ++i) {
4770 k = isl_basic_map_alloc_equality(bmap);
4771 if (k < 0)
4772 goto error;
4773 isl_seq_clr(bmap->eq[k], 1 + total);
4774 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + i], -1);
4775 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1);
4778 bmap = isl_basic_map_gauss(bmap, NULL);
4779 return isl_basic_map_finalize(bmap);
4780 error:
4781 isl_basic_map_free(bmap);
4782 return NULL;
4785 int isl_map_may_be_set(__isl_keep isl_map *map)
4787 if (!map)
4788 return -1;
4789 return isl_space_may_be_set(map->dim);
4792 /* Is this map actually a set?
4793 * Users should never call this function. Outside of isl,
4794 * the type should indicate whether something is a set or a map.
4796 int isl_map_is_set(__isl_keep isl_map *map)
4798 if (!map)
4799 return -1;
4800 return isl_space_is_set(map->dim);
4803 struct isl_set *isl_map_range(struct isl_map *map)
4805 int i;
4806 struct isl_set *set;
4808 if (!map)
4809 goto error;
4810 if (isl_map_is_set(map))
4811 return (isl_set *)map;
4813 map = isl_map_cow(map);
4814 if (!map)
4815 goto error;
4817 set = (struct isl_set *) map;
4818 set->dim = isl_space_range(set->dim);
4819 if (!set->dim)
4820 goto error;
4821 for (i = 0; i < map->n; ++i) {
4822 set->p[i] = isl_basic_map_range(map->p[i]);
4823 if (!set->p[i])
4824 goto error;
4826 ISL_F_CLR(set, ISL_MAP_DISJOINT);
4827 ISL_F_CLR(set, ISL_SET_NORMALIZED);
4828 return set;
4829 error:
4830 isl_map_free(map);
4831 return NULL;
4834 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
4836 int i;
4837 isl_space *domain_dim;
4839 map = isl_map_cow(map);
4840 if (!map)
4841 return NULL;
4843 domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
4844 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
4845 map->dim = isl_space_join(map->dim, domain_dim);
4846 if (!map->dim)
4847 goto error;
4848 for (i = 0; i < map->n; ++i) {
4849 map->p[i] = isl_basic_map_domain_map(map->p[i]);
4850 if (!map->p[i])
4851 goto error;
4853 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4854 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
4855 return map;
4856 error:
4857 isl_map_free(map);
4858 return NULL;
4861 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
4863 int i;
4864 isl_space *range_dim;
4866 map = isl_map_cow(map);
4867 if (!map)
4868 return NULL;
4870 range_dim = isl_space_range(isl_map_get_space(map));
4871 range_dim = isl_space_from_range(range_dim);
4872 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
4873 map->dim = isl_space_join(map->dim, range_dim);
4874 if (!map->dim)
4875 goto error;
4876 for (i = 0; i < map->n; ++i) {
4877 map->p[i] = isl_basic_map_range_map(map->p[i]);
4878 if (!map->p[i])
4879 goto error;
4881 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4882 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
4883 return map;
4884 error:
4885 isl_map_free(map);
4886 return NULL;
4889 __isl_give isl_map *isl_map_from_set(__isl_take isl_set *set,
4890 __isl_take isl_space *dim)
4892 int i;
4893 struct isl_map *map = NULL;
4895 set = isl_set_cow(set);
4896 if (!set || !dim)
4897 goto error;
4898 isl_assert(set->ctx, isl_space_compatible(set->dim, dim), goto error);
4899 map = (struct isl_map *)set;
4900 for (i = 0; i < set->n; ++i) {
4901 map->p[i] = isl_basic_map_from_basic_set(
4902 set->p[i], isl_space_copy(dim));
4903 if (!map->p[i])
4904 goto error;
4906 isl_space_free(map->dim);
4907 map->dim = dim;
4908 return map;
4909 error:
4910 isl_space_free(dim);
4911 isl_set_free(set);
4912 return NULL;
4915 __isl_give isl_basic_map *isl_basic_map_from_domain(
4916 __isl_take isl_basic_set *bset)
4918 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
4921 __isl_give isl_basic_map *isl_basic_map_from_range(
4922 __isl_take isl_basic_set *bset)
4924 isl_space *space;
4925 space = isl_basic_set_get_space(bset);
4926 space = isl_space_from_range(space);
4927 bset = isl_basic_set_reset_space(bset, space);
4928 return (isl_basic_map *)bset;
4931 struct isl_map *isl_map_from_range(struct isl_set *set)
4933 isl_space *space;
4934 space = isl_set_get_space(set);
4935 space = isl_space_from_range(space);
4936 set = isl_set_reset_space(set, space);
4937 return (struct isl_map *)set;
4940 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
4942 return isl_map_reverse(isl_map_from_range(set));
4945 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
4946 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
4948 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
4951 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
4952 __isl_take isl_set *range)
4954 return isl_map_apply_range(isl_map_reverse(domain), range);
4957 struct isl_set *isl_set_from_map(struct isl_map *map)
4959 int i;
4960 struct isl_set *set = NULL;
4962 if (!map)
4963 return NULL;
4964 map = isl_map_cow(map);
4965 if (!map)
4966 return NULL;
4967 map->dim = isl_space_as_set_space(map->dim);
4968 if (!map->dim)
4969 goto error;
4970 set = (struct isl_set *)map;
4971 for (i = 0; i < map->n; ++i) {
4972 set->p[i] = isl_basic_set_from_basic_map(map->p[i]);
4973 if (!set->p[i])
4974 goto error;
4976 return set;
4977 error:
4978 isl_map_free(map);
4979 return NULL;
4982 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *dim, int n,
4983 unsigned flags)
4985 struct isl_map *map;
4987 if (!dim)
4988 return NULL;
4989 if (n < 0)
4990 isl_die(dim->ctx, isl_error_internal,
4991 "negative number of basic maps", goto error);
4992 map = isl_alloc(dim->ctx, struct isl_map,
4993 sizeof(struct isl_map) +
4994 (n - 1) * sizeof(struct isl_basic_map *));
4995 if (!map)
4996 goto error;
4998 map->ctx = dim->ctx;
4999 isl_ctx_ref(map->ctx);
5000 map->ref = 1;
5001 map->size = n;
5002 map->n = 0;
5003 map->dim = dim;
5004 map->flags = flags;
5005 return map;
5006 error:
5007 isl_space_free(dim);
5008 return NULL;
5011 struct isl_map *isl_map_alloc(struct isl_ctx *ctx,
5012 unsigned nparam, unsigned in, unsigned out, int n,
5013 unsigned flags)
5015 struct isl_map *map;
5016 isl_space *dims;
5018 dims = isl_space_alloc(ctx, nparam, in, out);
5019 if (!dims)
5020 return NULL;
5022 map = isl_map_alloc_space(dims, n, flags);
5023 return map;
5026 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim)
5028 struct isl_basic_map *bmap;
5029 bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
5030 bmap = isl_basic_map_set_to_empty(bmap);
5031 return bmap;
5034 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim)
5036 struct isl_basic_set *bset;
5037 bset = isl_basic_set_alloc_space(dim, 0, 1, 0);
5038 bset = isl_basic_set_set_to_empty(bset);
5039 return bset;
5042 struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model)
5044 struct isl_basic_map *bmap;
5045 if (!model)
5046 return NULL;
5047 bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5048 bmap = isl_basic_map_set_to_empty(bmap);
5049 return bmap;
5052 struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model)
5054 struct isl_basic_map *bmap;
5055 if (!model)
5056 return NULL;
5057 bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5058 bmap = isl_basic_map_set_to_empty(bmap);
5059 return bmap;
5062 struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *model)
5064 struct isl_basic_set *bset;
5065 if (!model)
5066 return NULL;
5067 bset = isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5068 bset = isl_basic_set_set_to_empty(bset);
5069 return bset;
5072 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim)
5074 struct isl_basic_map *bmap;
5075 bmap = isl_basic_map_alloc_space(dim, 0, 0, 0);
5076 bmap = isl_basic_map_finalize(bmap);
5077 return bmap;
5080 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim)
5082 struct isl_basic_set *bset;
5083 bset = isl_basic_set_alloc_space(dim, 0, 0, 0);
5084 bset = isl_basic_set_finalize(bset);
5085 return bset;
5088 __isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
5090 int i;
5091 unsigned total = isl_space_dim(dim, isl_dim_all);
5092 isl_basic_map *bmap;
5094 bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
5095 for (i = 0; i < total; ++i) {
5096 int k = isl_basic_map_alloc_inequality(bmap);
5097 if (k < 0)
5098 goto error;
5099 isl_seq_clr(bmap->ineq[k], 1 + total);
5100 isl_int_set_si(bmap->ineq[k][1 + i], 1);
5102 return bmap;
5103 error:
5104 isl_basic_map_free(bmap);
5105 return NULL;
5108 __isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
5110 return isl_basic_map_nat_universe(dim);
5113 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
5115 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
5118 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
5120 return isl_map_nat_universe(dim);
5123 __isl_give isl_basic_map *isl_basic_map_universe_like(
5124 __isl_keep isl_basic_map *model)
5126 if (!model)
5127 return NULL;
5128 return isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5131 struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *model)
5133 if (!model)
5134 return NULL;
5135 return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5138 __isl_give isl_basic_set *isl_basic_set_universe_like_set(
5139 __isl_keep isl_set *model)
5141 if (!model)
5142 return NULL;
5143 return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5146 __isl_give isl_map *isl_map_empty(__isl_take isl_space *dim)
5148 return isl_map_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5151 struct isl_map *isl_map_empty_like(struct isl_map *model)
5153 if (!model)
5154 return NULL;
5155 return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT);
5158 struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model)
5160 if (!model)
5161 return NULL;
5162 return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT);
5165 __isl_give isl_set *isl_set_empty(__isl_take isl_space *dim)
5167 return isl_set_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5170 struct isl_set *isl_set_empty_like(struct isl_set *model)
5172 if (!model)
5173 return NULL;
5174 return isl_set_empty(isl_space_copy(model->dim));
5177 __isl_give isl_map *isl_map_universe(__isl_take isl_space *dim)
5179 struct isl_map *map;
5180 if (!dim)
5181 return NULL;
5182 map = isl_map_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5183 map = isl_map_add_basic_map(map, isl_basic_map_universe(dim));
5184 return map;
5187 __isl_give isl_set *isl_set_universe(__isl_take isl_space *dim)
5189 struct isl_set *set;
5190 if (!dim)
5191 return NULL;
5192 set = isl_set_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5193 set = isl_set_add_basic_set(set, isl_basic_set_universe(dim));
5194 return set;
5197 __isl_give isl_set *isl_set_universe_like(__isl_keep isl_set *model)
5199 if (!model)
5200 return NULL;
5201 return isl_set_universe(isl_space_copy(model->dim));
5204 struct isl_map *isl_map_dup(struct isl_map *map)
5206 int i;
5207 struct isl_map *dup;
5209 if (!map)
5210 return NULL;
5211 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
5212 for (i = 0; i < map->n; ++i)
5213 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
5214 return dup;
5217 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
5218 __isl_take isl_basic_map *bmap)
5220 if (!bmap || !map)
5221 goto error;
5222 if (isl_basic_map_plain_is_empty(bmap)) {
5223 isl_basic_map_free(bmap);
5224 return map;
5226 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
5227 isl_assert(map->ctx, map->n < map->size, goto error);
5228 map->p[map->n] = bmap;
5229 map->n++;
5230 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5231 return map;
5232 error:
5233 if (map)
5234 isl_map_free(map);
5235 if (bmap)
5236 isl_basic_map_free(bmap);
5237 return NULL;
5240 void *isl_map_free(struct isl_map *map)
5242 int i;
5244 if (!map)
5245 return NULL;
5247 if (--map->ref > 0)
5248 return NULL;
5250 isl_ctx_deref(map->ctx);
5251 for (i = 0; i < map->n; ++i)
5252 isl_basic_map_free(map->p[i]);
5253 isl_space_free(map->dim);
5254 free(map);
5256 return NULL;
5259 struct isl_map *isl_map_extend(struct isl_map *base,
5260 unsigned nparam, unsigned n_in, unsigned n_out)
5262 int i;
5264 base = isl_map_cow(base);
5265 if (!base)
5266 return NULL;
5268 base->dim = isl_space_extend(base->dim, nparam, n_in, n_out);
5269 if (!base->dim)
5270 goto error;
5271 for (i = 0; i < base->n; ++i) {
5272 base->p[i] = isl_basic_map_extend_space(base->p[i],
5273 isl_space_copy(base->dim), 0, 0, 0);
5274 if (!base->p[i])
5275 goto error;
5277 return base;
5278 error:
5279 isl_map_free(base);
5280 return NULL;
5283 struct isl_set *isl_set_extend(struct isl_set *base,
5284 unsigned nparam, unsigned dim)
5286 return (struct isl_set *)isl_map_extend((struct isl_map *)base,
5287 nparam, 0, dim);
5290 static struct isl_basic_map *isl_basic_map_fix_pos_si(
5291 struct isl_basic_map *bmap, unsigned pos, int value)
5293 int j;
5295 bmap = isl_basic_map_cow(bmap);
5296 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5297 j = isl_basic_map_alloc_equality(bmap);
5298 if (j < 0)
5299 goto error;
5300 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5301 isl_int_set_si(bmap->eq[j][pos], -1);
5302 isl_int_set_si(bmap->eq[j][0], value);
5303 bmap = isl_basic_map_simplify(bmap);
5304 return isl_basic_map_finalize(bmap);
5305 error:
5306 isl_basic_map_free(bmap);
5307 return NULL;
5310 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
5311 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
5313 int j;
5315 bmap = isl_basic_map_cow(bmap);
5316 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5317 j = isl_basic_map_alloc_equality(bmap);
5318 if (j < 0)
5319 goto error;
5320 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5321 isl_int_set_si(bmap->eq[j][pos], -1);
5322 isl_int_set(bmap->eq[j][0], value);
5323 bmap = isl_basic_map_simplify(bmap);
5324 return isl_basic_map_finalize(bmap);
5325 error:
5326 isl_basic_map_free(bmap);
5327 return NULL;
5330 struct isl_basic_map *isl_basic_map_fix_si(struct isl_basic_map *bmap,
5331 enum isl_dim_type type, unsigned pos, int value)
5333 if (!bmap)
5334 return NULL;
5335 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5336 return isl_basic_map_fix_pos_si(bmap,
5337 isl_basic_map_offset(bmap, type) + pos, value);
5338 error:
5339 isl_basic_map_free(bmap);
5340 return NULL;
5343 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
5344 enum isl_dim_type type, unsigned pos, isl_int value)
5346 if (!bmap)
5347 return NULL;
5348 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5349 return isl_basic_map_fix_pos(bmap,
5350 isl_basic_map_offset(bmap, type) + pos, value);
5351 error:
5352 isl_basic_map_free(bmap);
5353 return NULL;
5356 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
5357 * to be equal to "v".
5359 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
5360 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5362 if (!bmap || !v)
5363 goto error;
5364 if (!isl_val_is_int(v))
5365 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
5366 "expecting integer value", goto error);
5367 if (pos >= isl_basic_map_dim(bmap, type))
5368 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
5369 "index out of bounds", goto error);
5370 pos += isl_basic_map_offset(bmap, type);
5371 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
5372 isl_val_free(v);
5373 return bmap;
5374 error:
5375 isl_basic_map_free(bmap);
5376 isl_val_free(v);
5377 return NULL;
5380 /* Fix the value of the variable at position "pos" of type "type" of "bset"
5381 * to be equal to "v".
5383 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
5384 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5386 return isl_basic_map_fix_val(bset, type, pos, v);
5389 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
5390 enum isl_dim_type type, unsigned pos, int value)
5392 return (struct isl_basic_set *)
5393 isl_basic_map_fix_si((struct isl_basic_map *)bset,
5394 type, pos, value);
5397 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
5398 enum isl_dim_type type, unsigned pos, isl_int value)
5400 return (struct isl_basic_set *)
5401 isl_basic_map_fix((struct isl_basic_map *)bset,
5402 type, pos, value);
5405 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
5406 unsigned input, int value)
5408 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
5411 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
5412 unsigned dim, int value)
5414 return (struct isl_basic_set *)
5415 isl_basic_map_fix_si((struct isl_basic_map *)bset,
5416 isl_dim_set, dim, value);
5419 static int remove_if_empty(__isl_keep isl_map *map, int i)
5421 int empty = isl_basic_map_plain_is_empty(map->p[i]);
5423 if (empty < 0)
5424 return -1;
5425 if (!empty)
5426 return 0;
5428 isl_basic_map_free(map->p[i]);
5429 if (i != map->n - 1) {
5430 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5431 map->p[i] = map->p[map->n - 1];
5433 map->n--;
5435 return 0;
5438 /* Perform "fn" on each basic map of "map", where we may not be holding
5439 * the only reference to "map".
5440 * In particular, "fn" should be a semantics preserving operation
5441 * that we want to apply to all copies of "map". We therefore need
5442 * to be careful not to modify "map" in a way that breaks "map"
5443 * in case anything goes wrong.
5445 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
5446 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
5448 struct isl_basic_map *bmap;
5449 int i;
5451 if (!map)
5452 return NULL;
5454 for (i = map->n - 1; i >= 0; --i) {
5455 bmap = isl_basic_map_copy(map->p[i]);
5456 bmap = fn(bmap);
5457 if (!bmap)
5458 goto error;
5459 isl_basic_map_free(map->p[i]);
5460 map->p[i] = bmap;
5461 if (remove_if_empty(map, i) < 0)
5462 goto error;
5465 return map;
5466 error:
5467 isl_map_free(map);
5468 return NULL;
5471 struct isl_map *isl_map_fix_si(struct isl_map *map,
5472 enum isl_dim_type type, unsigned pos, int value)
5474 int i;
5476 map = isl_map_cow(map);
5477 if (!map)
5478 return NULL;
5480 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5481 for (i = map->n - 1; i >= 0; --i) {
5482 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
5483 if (remove_if_empty(map, i) < 0)
5484 goto error;
5486 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5487 return map;
5488 error:
5489 isl_map_free(map);
5490 return NULL;
5493 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
5494 enum isl_dim_type type, unsigned pos, int value)
5496 return (struct isl_set *)
5497 isl_map_fix_si((struct isl_map *)set, type, pos, value);
5500 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
5501 enum isl_dim_type type, unsigned pos, isl_int value)
5503 int i;
5505 map = isl_map_cow(map);
5506 if (!map)
5507 return NULL;
5509 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5510 for (i = 0; i < map->n; ++i) {
5511 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
5512 if (!map->p[i])
5513 goto error;
5515 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5516 return map;
5517 error:
5518 isl_map_free(map);
5519 return NULL;
5522 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
5523 enum isl_dim_type type, unsigned pos, isl_int value)
5525 return (struct isl_set *)isl_map_fix((isl_map *)set, type, pos, value);
5528 /* Fix the value of the variable at position "pos" of type "type" of "map"
5529 * to be equal to "v".
5531 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
5532 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5534 int i;
5536 map = isl_map_cow(map);
5537 if (!map || !v)
5538 goto error;
5540 if (!isl_val_is_int(v))
5541 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5542 "expecting integer value", goto error);
5543 if (pos >= isl_map_dim(map, type))
5544 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5545 "index out of bounds", goto error);
5546 for (i = map->n - 1; i >= 0; --i) {
5547 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
5548 isl_val_copy(v));
5549 if (remove_if_empty(map, i) < 0)
5550 goto error;
5552 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5553 isl_val_free(v);
5554 return map;
5555 error:
5556 isl_map_free(map);
5557 isl_val_free(v);
5558 return NULL;
5561 /* Fix the value of the variable at position "pos" of type "type" of "set"
5562 * to be equal to "v".
5564 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
5565 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5567 return isl_map_fix_val(set, type, pos, v);
5570 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
5571 unsigned input, int value)
5573 return isl_map_fix_si(map, isl_dim_in, input, value);
5576 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
5578 return (struct isl_set *)
5579 isl_map_fix_si((struct isl_map *)set, isl_dim_set, dim, value);
5582 static __isl_give isl_basic_map *basic_map_bound_si(
5583 __isl_take isl_basic_map *bmap,
5584 enum isl_dim_type type, unsigned pos, int value, int upper)
5586 int j;
5588 if (!bmap)
5589 return NULL;
5590 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5591 pos += isl_basic_map_offset(bmap, type);
5592 bmap = isl_basic_map_cow(bmap);
5593 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
5594 j = isl_basic_map_alloc_inequality(bmap);
5595 if (j < 0)
5596 goto error;
5597 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
5598 if (upper) {
5599 isl_int_set_si(bmap->ineq[j][pos], -1);
5600 isl_int_set_si(bmap->ineq[j][0], value);
5601 } else {
5602 isl_int_set_si(bmap->ineq[j][pos], 1);
5603 isl_int_set_si(bmap->ineq[j][0], -value);
5605 bmap = isl_basic_map_simplify(bmap);
5606 return isl_basic_map_finalize(bmap);
5607 error:
5608 isl_basic_map_free(bmap);
5609 return NULL;
5612 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
5613 __isl_take isl_basic_map *bmap,
5614 enum isl_dim_type type, unsigned pos, int value)
5616 return basic_map_bound_si(bmap, type, pos, value, 0);
5619 /* Constrain the values of the given dimension to be no greater than "value".
5621 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
5622 __isl_take isl_basic_map *bmap,
5623 enum isl_dim_type type, unsigned pos, int value)
5625 return basic_map_bound_si(bmap, type, pos, value, 1);
5628 struct isl_basic_set *isl_basic_set_lower_bound_dim(struct isl_basic_set *bset,
5629 unsigned dim, isl_int value)
5631 int j;
5633 bset = isl_basic_set_cow(bset);
5634 bset = isl_basic_set_extend_constraints(bset, 0, 1);
5635 j = isl_basic_set_alloc_inequality(bset);
5636 if (j < 0)
5637 goto error;
5638 isl_seq_clr(bset->ineq[j], 1 + isl_basic_set_total_dim(bset));
5639 isl_int_set_si(bset->ineq[j][1 + isl_basic_set_n_param(bset) + dim], 1);
5640 isl_int_neg(bset->ineq[j][0], value);
5641 bset = isl_basic_set_simplify(bset);
5642 return isl_basic_set_finalize(bset);
5643 error:
5644 isl_basic_set_free(bset);
5645 return NULL;
5648 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
5649 enum isl_dim_type type, unsigned pos, int value, int upper)
5651 int i;
5653 map = isl_map_cow(map);
5654 if (!map)
5655 return NULL;
5657 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5658 for (i = 0; i < map->n; ++i) {
5659 map->p[i] = basic_map_bound_si(map->p[i],
5660 type, pos, value, upper);
5661 if (!map->p[i])
5662 goto error;
5664 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5665 return map;
5666 error:
5667 isl_map_free(map);
5668 return NULL;
5671 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
5672 enum isl_dim_type type, unsigned pos, int value)
5674 return map_bound_si(map, type, pos, value, 0);
5677 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
5678 enum isl_dim_type type, unsigned pos, int value)
5680 return map_bound_si(map, type, pos, value, 1);
5683 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
5684 enum isl_dim_type type, unsigned pos, int value)
5686 return (struct isl_set *)
5687 isl_map_lower_bound_si((struct isl_map *)set, type, pos, value);
5690 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
5691 enum isl_dim_type type, unsigned pos, int value)
5693 return isl_map_upper_bound_si(set, type, pos, value);
5696 /* Bound the given variable of "bmap" from below (or above is "upper"
5697 * is set) to "value".
5699 static __isl_give isl_basic_map *basic_map_bound(
5700 __isl_take isl_basic_map *bmap,
5701 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
5703 int j;
5705 if (!bmap)
5706 return NULL;
5707 if (pos >= isl_basic_map_dim(bmap, type))
5708 isl_die(bmap->ctx, isl_error_invalid,
5709 "index out of bounds", goto error);
5710 pos += isl_basic_map_offset(bmap, type);
5711 bmap = isl_basic_map_cow(bmap);
5712 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
5713 j = isl_basic_map_alloc_inequality(bmap);
5714 if (j < 0)
5715 goto error;
5716 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
5717 if (upper) {
5718 isl_int_set_si(bmap->ineq[j][pos], -1);
5719 isl_int_set(bmap->ineq[j][0], value);
5720 } else {
5721 isl_int_set_si(bmap->ineq[j][pos], 1);
5722 isl_int_neg(bmap->ineq[j][0], value);
5724 bmap = isl_basic_map_simplify(bmap);
5725 return isl_basic_map_finalize(bmap);
5726 error:
5727 isl_basic_map_free(bmap);
5728 return NULL;
5731 /* Bound the given variable of "map" from below (or above is "upper"
5732 * is set) to "value".
5734 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
5735 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
5737 int i;
5739 map = isl_map_cow(map);
5740 if (!map)
5741 return NULL;
5743 if (pos >= isl_map_dim(map, type))
5744 isl_die(map->ctx, isl_error_invalid,
5745 "index out of bounds", goto error);
5746 for (i = map->n - 1; i >= 0; --i) {
5747 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
5748 if (remove_if_empty(map, i) < 0)
5749 goto error;
5751 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5752 return map;
5753 error:
5754 isl_map_free(map);
5755 return NULL;
5758 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
5759 enum isl_dim_type type, unsigned pos, isl_int value)
5761 return map_bound(map, type, pos, value, 0);
5764 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
5765 enum isl_dim_type type, unsigned pos, isl_int value)
5767 return map_bound(map, type, pos, value, 1);
5770 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
5771 enum isl_dim_type type, unsigned pos, isl_int value)
5773 return isl_map_lower_bound(set, type, pos, value);
5776 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
5777 enum isl_dim_type type, unsigned pos, isl_int value)
5779 return isl_map_upper_bound(set, type, pos, value);
5782 /* Force the values of the variable at position "pos" of type "type" of "set"
5783 * to be no smaller than "value".
5785 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
5786 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
5788 if (!value)
5789 goto error;
5790 if (!isl_val_is_int(value))
5791 isl_die(isl_set_get_ctx(set), isl_error_invalid,
5792 "expecting integer value", goto error);
5793 set = isl_set_lower_bound(set, type, pos, value->n);
5794 isl_val_free(value);
5795 return set;
5796 error:
5797 isl_val_free(value);
5798 isl_set_free(set);
5799 return NULL;
5802 /* Force the values of the variable at position "pos" of type "type" of "set"
5803 * to be no greater than "value".
5805 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
5806 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
5808 if (!value)
5809 goto error;
5810 if (!isl_val_is_int(value))
5811 isl_die(isl_set_get_ctx(set), isl_error_invalid,
5812 "expecting integer value", goto error);
5813 set = isl_set_upper_bound(set, type, pos, value->n);
5814 isl_val_free(value);
5815 return set;
5816 error:
5817 isl_val_free(value);
5818 isl_set_free(set);
5819 return NULL;
5822 struct isl_set *isl_set_lower_bound_dim(struct isl_set *set, unsigned dim,
5823 isl_int value)
5825 int i;
5827 set = isl_set_cow(set);
5828 if (!set)
5829 return NULL;
5831 isl_assert(set->ctx, dim < isl_set_n_dim(set), goto error);
5832 for (i = 0; i < set->n; ++i) {
5833 set->p[i] = isl_basic_set_lower_bound_dim(set->p[i], dim, value);
5834 if (!set->p[i])
5835 goto error;
5837 return set;
5838 error:
5839 isl_set_free(set);
5840 return NULL;
5843 struct isl_map *isl_map_reverse(struct isl_map *map)
5845 int i;
5847 map = isl_map_cow(map);
5848 if (!map)
5849 return NULL;
5851 map->dim = isl_space_reverse(map->dim);
5852 if (!map->dim)
5853 goto error;
5854 for (i = 0; i < map->n; ++i) {
5855 map->p[i] = isl_basic_map_reverse(map->p[i]);
5856 if (!map->p[i])
5857 goto error;
5859 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5860 return map;
5861 error:
5862 isl_map_free(map);
5863 return NULL;
5866 static struct isl_map *isl_basic_map_partial_lexopt(
5867 struct isl_basic_map *bmap, struct isl_basic_set *dom,
5868 struct isl_set **empty, int max)
5870 if (!bmap)
5871 goto error;
5872 if (bmap->ctx->opt->pip == ISL_PIP_PIP)
5873 return isl_pip_basic_map_lexopt(bmap, dom, empty, max);
5874 else
5875 return isl_tab_basic_map_partial_lexopt(bmap, dom, empty, max);
5876 error:
5877 isl_basic_map_free(bmap);
5878 isl_basic_set_free(dom);
5879 if (empty)
5880 *empty = NULL;
5881 return NULL;
5884 struct isl_map *isl_basic_map_partial_lexmax(
5885 struct isl_basic_map *bmap, struct isl_basic_set *dom,
5886 struct isl_set **empty)
5888 return isl_basic_map_partial_lexopt(bmap, dom, empty, 1);
5891 struct isl_map *isl_basic_map_partial_lexmin(
5892 struct isl_basic_map *bmap, struct isl_basic_set *dom,
5893 struct isl_set **empty)
5895 return isl_basic_map_partial_lexopt(bmap, dom, empty, 0);
5898 struct isl_set *isl_basic_set_partial_lexmin(
5899 struct isl_basic_set *bset, struct isl_basic_set *dom,
5900 struct isl_set **empty)
5902 return (struct isl_set *)
5903 isl_basic_map_partial_lexmin((struct isl_basic_map *)bset,
5904 dom, empty);
5907 struct isl_set *isl_basic_set_partial_lexmax(
5908 struct isl_basic_set *bset, struct isl_basic_set *dom,
5909 struct isl_set **empty)
5911 return (struct isl_set *)
5912 isl_basic_map_partial_lexmax((struct isl_basic_map *)bset,
5913 dom, empty);
5916 __isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff(
5917 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
5918 __isl_give isl_set **empty)
5920 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 0);
5923 __isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
5924 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
5925 __isl_give isl_set **empty)
5927 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 1);
5930 __isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff(
5931 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
5932 __isl_give isl_set **empty)
5934 return isl_basic_map_partial_lexmin_pw_multi_aff(bset, dom, empty);
5937 __isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff(
5938 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
5939 __isl_give isl_set **empty)
5941 return isl_basic_map_partial_lexmax_pw_multi_aff(bset, dom, empty);
5944 __isl_give isl_pw_multi_aff *isl_basic_map_lexopt_pw_multi_aff(
5945 __isl_take isl_basic_map *bmap, int max)
5947 isl_basic_set *dom = NULL;
5948 isl_space *dom_space;
5950 if (!bmap)
5951 goto error;
5952 dom_space = isl_space_domain(isl_space_copy(bmap->dim));
5953 dom = isl_basic_set_universe(dom_space);
5954 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, NULL, max);
5955 error:
5956 isl_basic_map_free(bmap);
5957 return NULL;
5960 __isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
5961 __isl_take isl_basic_map *bmap)
5963 return isl_basic_map_lexopt_pw_multi_aff(bmap, 0);
5966 #undef TYPE
5967 #define TYPE isl_pw_multi_aff
5968 #undef SUFFIX
5969 #define SUFFIX _pw_multi_aff
5970 #undef EMPTY
5971 #define EMPTY isl_pw_multi_aff_empty
5972 #undef ADD
5973 #define ADD isl_pw_multi_aff_union_add
5974 #include "isl_map_lexopt_templ.c"
5976 /* Given a map "map", compute the lexicographically minimal
5977 * (or maximal) image element for each domain element in dom,
5978 * in the form of an isl_pw_multi_aff.
5979 * Set *empty to those elements in dom that do not have an image element.
5981 * We first compute the lexicographically minimal or maximal element
5982 * in the first basic map. This results in a partial solution "res"
5983 * and a subset "todo" of dom that still need to be handled.
5984 * We then consider each of the remaining maps in "map" and successively
5985 * update both "res" and "todo".
5987 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
5988 __isl_take isl_map *map, __isl_take isl_set *dom,
5989 __isl_give isl_set **empty, int max)
5991 int i;
5992 isl_pw_multi_aff *res;
5993 isl_set *todo;
5995 if (!map || !dom)
5996 goto error;
5998 if (isl_map_plain_is_empty(map)) {
5999 if (empty)
6000 *empty = dom;
6001 else
6002 isl_set_free(dom);
6003 return isl_pw_multi_aff_from_map(map);
6006 res = basic_map_partial_lexopt_pw_multi_aff(
6007 isl_basic_map_copy(map->p[0]),
6008 isl_set_copy(dom), &todo, max);
6010 for (i = 1; i < map->n; ++i) {
6011 isl_pw_multi_aff *res_i;
6012 isl_set *todo_i;
6014 res_i = basic_map_partial_lexopt_pw_multi_aff(
6015 isl_basic_map_copy(map->p[i]),
6016 isl_set_copy(dom), &todo_i, max);
6018 if (max)
6019 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6020 else
6021 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6023 todo = isl_set_intersect(todo, todo_i);
6026 isl_set_free(dom);
6027 isl_map_free(map);
6029 if (empty)
6030 *empty = todo;
6031 else
6032 isl_set_free(todo);
6034 return res;
6035 error:
6036 if (empty)
6037 *empty = NULL;
6038 isl_set_free(dom);
6039 isl_map_free(map);
6040 return NULL;
6043 #undef TYPE
6044 #define TYPE isl_map
6045 #undef SUFFIX
6046 #define SUFFIX
6047 #undef EMPTY
6048 #define EMPTY isl_map_empty
6049 #undef ADD
6050 #define ADD isl_map_union_disjoint
6051 #include "isl_map_lexopt_templ.c"
6053 /* Given a map "map", compute the lexicographically minimal
6054 * (or maximal) image element for each domain element in dom.
6055 * Set *empty to those elements in dom that do not have an image element.
6057 * We first compute the lexicographically minimal or maximal element
6058 * in the first basic map. This results in a partial solution "res"
6059 * and a subset "todo" of dom that still need to be handled.
6060 * We then consider each of the remaining maps in "map" and successively
6061 * update both "res" and "todo".
6063 * Let res^k and todo^k be the results after k steps and let i = k + 1.
6064 * Assume we are computing the lexicographical maximum.
6065 * We first compute the lexicographically maximal element in basic map i.
6066 * This results in a partial solution res_i and a subset todo_i.
6067 * Then we combine these results with those obtain for the first k basic maps
6068 * to obtain a result that is valid for the first k+1 basic maps.
6069 * In particular, the set where there is no solution is the set where
6070 * there is no solution for the first k basic maps and also no solution
6071 * for the ith basic map, i.e.,
6073 * todo^i = todo^k * todo_i
6075 * On dom(res^k) * dom(res_i), we need to pick the larger of the two
6076 * solutions, arbitrarily breaking ties in favor of res^k.
6077 * That is, when res^k(a) >= res_i(a), we pick res^k and
6078 * when res^k(a) < res_i(a), we pick res_i. (Here, ">=" and "<" denote
6079 * the lexicographic order.)
6080 * In practice, we compute
6082 * res^k * (res_i . "<=")
6084 * and
6086 * res_i * (res^k . "<")
6088 * Finally, we consider the symmetric difference of dom(res^k) and dom(res_i),
6089 * where only one of res^k and res_i provides a solution and we simply pick
6090 * that one, i.e.,
6092 * res^k * todo_i
6093 * and
6094 * res_i * todo^k
6096 * Note that we only compute these intersections when dom(res^k) intersects
6097 * dom(res_i). Otherwise, the only effect of these intersections is to
6098 * potentially break up res^k and res_i into smaller pieces.
6099 * We want to avoid such splintering as much as possible.
6100 * In fact, an earlier implementation of this function would look for
6101 * better results in the domain of res^k and for extra results in todo^k,
6102 * but this would always result in a splintering according to todo^k,
6103 * even when the domain of basic map i is disjoint from the domains of
6104 * the previous basic maps.
6106 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6107 __isl_take isl_map *map, __isl_take isl_set *dom,
6108 __isl_give isl_set **empty, int max)
6110 int i;
6111 struct isl_map *res;
6112 struct isl_set *todo;
6114 if (!map || !dom)
6115 goto error;
6117 if (isl_map_plain_is_empty(map)) {
6118 if (empty)
6119 *empty = dom;
6120 else
6121 isl_set_free(dom);
6122 return map;
6125 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6126 isl_set_copy(dom), &todo, max);
6128 for (i = 1; i < map->n; ++i) {
6129 isl_map *lt, *le;
6130 isl_map *res_i;
6131 isl_set *todo_i;
6132 isl_space *dim = isl_space_range(isl_map_get_space(res));
6134 res_i = basic_map_partial_lexopt(isl_basic_map_copy(map->p[i]),
6135 isl_set_copy(dom), &todo_i, max);
6137 if (max) {
6138 lt = isl_map_lex_lt(isl_space_copy(dim));
6139 le = isl_map_lex_le(dim);
6140 } else {
6141 lt = isl_map_lex_gt(isl_space_copy(dim));
6142 le = isl_map_lex_ge(dim);
6144 lt = isl_map_apply_range(isl_map_copy(res), lt);
6145 lt = isl_map_intersect(lt, isl_map_copy(res_i));
6146 le = isl_map_apply_range(isl_map_copy(res_i), le);
6147 le = isl_map_intersect(le, isl_map_copy(res));
6149 if (!isl_map_is_empty(lt) || !isl_map_is_empty(le)) {
6150 res = isl_map_intersect_domain(res,
6151 isl_set_copy(todo_i));
6152 res_i = isl_map_intersect_domain(res_i,
6153 isl_set_copy(todo));
6156 res = isl_map_union_disjoint(res, res_i);
6157 res = isl_map_union_disjoint(res, lt);
6158 res = isl_map_union_disjoint(res, le);
6160 todo = isl_set_intersect(todo, todo_i);
6163 isl_set_free(dom);
6164 isl_map_free(map);
6166 if (empty)
6167 *empty = todo;
6168 else
6169 isl_set_free(todo);
6171 return res;
6172 error:
6173 if (empty)
6174 *empty = NULL;
6175 isl_set_free(dom);
6176 isl_map_free(map);
6177 return NULL;
6180 __isl_give isl_map *isl_map_partial_lexmax(
6181 __isl_take isl_map *map, __isl_take isl_set *dom,
6182 __isl_give isl_set **empty)
6184 return isl_map_partial_lexopt(map, dom, empty, 1);
6187 __isl_give isl_map *isl_map_partial_lexmin(
6188 __isl_take isl_map *map, __isl_take isl_set *dom,
6189 __isl_give isl_set **empty)
6191 return isl_map_partial_lexopt(map, dom, empty, 0);
6194 __isl_give isl_set *isl_set_partial_lexmin(
6195 __isl_take isl_set *set, __isl_take isl_set *dom,
6196 __isl_give isl_set **empty)
6198 return (struct isl_set *)
6199 isl_map_partial_lexmin((struct isl_map *)set,
6200 dom, empty);
6203 __isl_give isl_set *isl_set_partial_lexmax(
6204 __isl_take isl_set *set, __isl_take isl_set *dom,
6205 __isl_give isl_set **empty)
6207 return (struct isl_set *)
6208 isl_map_partial_lexmax((struct isl_map *)set,
6209 dom, empty);
6212 /* Compute the lexicographic minimum (or maximum if "max" is set)
6213 * of "bmap" over its domain.
6215 * Since we are not interested in the part of the domain space where
6216 * there is no solution, we initialize the domain to those constraints
6217 * of "bmap" that only involve the parameters and the input dimensions.
6218 * This relieves the parametric programming engine from detecting those
6219 * inequalities and transferring them to the context. More importantly,
6220 * it ensures that those inequalities are transferred first and not
6221 * intermixed with inequalities that actually split the domain.
6223 __isl_give isl_map *isl_basic_map_lexopt(__isl_take isl_basic_map *bmap, int max)
6225 int n_div;
6226 int n_out;
6227 isl_basic_map *copy;
6228 isl_basic_set *dom;
6230 n_div = isl_basic_map_dim(bmap, isl_dim_div);
6231 n_out = isl_basic_map_dim(bmap, isl_dim_out);
6232 copy = isl_basic_map_copy(bmap);
6233 copy = isl_basic_map_drop_constraints_involving_dims(copy,
6234 isl_dim_div, 0, n_div);
6235 copy = isl_basic_map_drop_constraints_involving_dims(copy,
6236 isl_dim_out, 0, n_out);
6237 dom = isl_basic_map_domain(copy);
6238 return isl_basic_map_partial_lexopt(bmap, dom, NULL, max);
6241 __isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap)
6243 return isl_basic_map_lexopt(bmap, 0);
6246 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6248 return isl_basic_map_lexopt(bmap, 1);
6251 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6253 return (isl_set *)isl_basic_map_lexmin((isl_basic_map *)bset);
6256 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6258 return (isl_set *)isl_basic_map_lexmax((isl_basic_map *)bset);
6261 /* Extract the first and only affine expression from list
6262 * and then add it to *pwaff with the given dom.
6263 * This domain is known to be disjoint from other domains
6264 * because of the way isl_basic_map_foreach_lexmax works.
6266 static int update_dim_opt(__isl_take isl_basic_set *dom,
6267 __isl_take isl_aff_list *list, void *user)
6269 isl_ctx *ctx = isl_basic_set_get_ctx(dom);
6270 isl_aff *aff;
6271 isl_pw_aff **pwaff = user;
6272 isl_pw_aff *pwaff_i;
6274 if (!list)
6275 goto error;
6276 if (isl_aff_list_n_aff(list) != 1)
6277 isl_die(ctx, isl_error_internal,
6278 "expecting single element list", goto error);
6280 aff = isl_aff_list_get_aff(list, 0);
6281 pwaff_i = isl_pw_aff_alloc(isl_set_from_basic_set(dom), aff);
6283 *pwaff = isl_pw_aff_add_disjoint(*pwaff, pwaff_i);
6285 isl_aff_list_free(list);
6287 return 0;
6288 error:
6289 isl_basic_set_free(dom);
6290 isl_aff_list_free(list);
6291 return -1;
6294 /* Given a basic map with one output dimension, compute the minimum or
6295 * maximum of that dimension as an isl_pw_aff.
6297 * The isl_pw_aff is constructed by having isl_basic_map_foreach_lexopt
6298 * call update_dim_opt on each leaf of the result.
6300 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6301 int max)
6303 isl_space *dim = isl_basic_map_get_space(bmap);
6304 isl_pw_aff *pwaff;
6305 int r;
6307 dim = isl_space_from_domain(isl_space_domain(dim));
6308 dim = isl_space_add_dims(dim, isl_dim_out, 1);
6309 pwaff = isl_pw_aff_empty(dim);
6311 r = isl_basic_map_foreach_lexopt(bmap, max, &update_dim_opt, &pwaff);
6312 if (r < 0)
6313 return isl_pw_aff_free(pwaff);
6315 return pwaff;
6318 /* Compute the minimum or maximum of the given output dimension
6319 * as a function of the parameters and the input dimensions,
6320 * but independently of the other output dimensions.
6322 * We first project out the other output dimension and then compute
6323 * the "lexicographic" maximum in each basic map, combining the results
6324 * using isl_pw_aff_union_max.
6326 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6327 int max)
6329 int i;
6330 isl_pw_aff *pwaff;
6331 unsigned n_out;
6333 n_out = isl_map_dim(map, isl_dim_out);
6334 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6335 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6336 if (!map)
6337 return NULL;
6339 if (map->n == 0) {
6340 isl_space *dim = isl_map_get_space(map);
6341 dim = isl_space_domain(isl_space_from_range(dim));
6342 isl_map_free(map);
6343 return isl_pw_aff_empty(dim);
6346 pwaff = basic_map_dim_opt(map->p[0], max);
6347 for (i = 1; i < map->n; ++i) {
6348 isl_pw_aff *pwaff_i;
6350 pwaff_i = basic_map_dim_opt(map->p[i], max);
6351 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6354 isl_map_free(map);
6356 return pwaff;
6359 /* Compute the maximum of the given output dimension as a function of the
6360 * parameters and input dimensions, but independently of
6361 * the other output dimensions.
6363 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6365 return map_dim_opt(map, pos, 1);
6368 /* Compute the minimum or maximum of the given set dimension
6369 * as a function of the parameters,
6370 * but independently of the other set dimensions.
6372 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
6373 int max)
6375 return map_dim_opt(set, pos, max);
6378 /* Compute the maximum of the given set dimension as a function of the
6379 * parameters, but independently of the other set dimensions.
6381 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
6383 return set_dim_opt(set, pos, 1);
6386 /* Compute the minimum of the given set dimension as a function of the
6387 * parameters, but independently of the other set dimensions.
6389 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
6391 return set_dim_opt(set, pos, 0);
6394 /* Apply a preimage specified by "mat" on the parameters of "bset".
6395 * bset is assumed to have only parameters and divs.
6397 static struct isl_basic_set *basic_set_parameter_preimage(
6398 struct isl_basic_set *bset, struct isl_mat *mat)
6400 unsigned nparam;
6402 if (!bset || !mat)
6403 goto error;
6405 bset->dim = isl_space_cow(bset->dim);
6406 if (!bset->dim)
6407 goto error;
6409 nparam = isl_basic_set_dim(bset, isl_dim_param);
6411 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
6413 bset->dim->nparam = 0;
6414 bset->dim->n_out = nparam;
6415 bset = isl_basic_set_preimage(bset, mat);
6416 if (bset) {
6417 bset->dim->nparam = bset->dim->n_out;
6418 bset->dim->n_out = 0;
6420 return bset;
6421 error:
6422 isl_mat_free(mat);
6423 isl_basic_set_free(bset);
6424 return NULL;
6427 /* Apply a preimage specified by "mat" on the parameters of "set".
6428 * set is assumed to have only parameters and divs.
6430 static struct isl_set *set_parameter_preimage(
6431 struct isl_set *set, struct isl_mat *mat)
6433 isl_space *dim = NULL;
6434 unsigned nparam;
6436 if (!set || !mat)
6437 goto error;
6439 dim = isl_space_copy(set->dim);
6440 dim = isl_space_cow(dim);
6441 if (!dim)
6442 goto error;
6444 nparam = isl_set_dim(set, isl_dim_param);
6446 isl_assert(set->ctx, mat->n_row == 1 + nparam, goto error);
6448 dim->nparam = 0;
6449 dim->n_out = nparam;
6450 isl_set_reset_space(set, dim);
6451 set = isl_set_preimage(set, mat);
6452 if (!set)
6453 goto error2;
6454 dim = isl_space_copy(set->dim);
6455 dim = isl_space_cow(dim);
6456 if (!dim)
6457 goto error2;
6458 dim->nparam = dim->n_out;
6459 dim->n_out = 0;
6460 isl_set_reset_space(set, dim);
6461 return set;
6462 error:
6463 isl_space_free(dim);
6464 isl_mat_free(mat);
6465 error2:
6466 isl_set_free(set);
6467 return NULL;
6470 /* Intersect the basic set "bset" with the affine space specified by the
6471 * equalities in "eq".
6473 static struct isl_basic_set *basic_set_append_equalities(
6474 struct isl_basic_set *bset, struct isl_mat *eq)
6476 int i, k;
6477 unsigned len;
6479 if (!bset || !eq)
6480 goto error;
6482 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
6483 eq->n_row, 0);
6484 if (!bset)
6485 goto error;
6487 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
6488 for (i = 0; i < eq->n_row; ++i) {
6489 k = isl_basic_set_alloc_equality(bset);
6490 if (k < 0)
6491 goto error;
6492 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
6493 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
6495 isl_mat_free(eq);
6497 bset = isl_basic_set_gauss(bset, NULL);
6498 bset = isl_basic_set_finalize(bset);
6500 return bset;
6501 error:
6502 isl_mat_free(eq);
6503 isl_basic_set_free(bset);
6504 return NULL;
6507 /* Intersect the set "set" with the affine space specified by the
6508 * equalities in "eq".
6510 static struct isl_set *set_append_equalities(struct isl_set *set,
6511 struct isl_mat *eq)
6513 int i;
6515 if (!set || !eq)
6516 goto error;
6518 for (i = 0; i < set->n; ++i) {
6519 set->p[i] = basic_set_append_equalities(set->p[i],
6520 isl_mat_copy(eq));
6521 if (!set->p[i])
6522 goto error;
6524 isl_mat_free(eq);
6525 return set;
6526 error:
6527 isl_mat_free(eq);
6528 isl_set_free(set);
6529 return NULL;
6532 /* Given a basic set "bset" that only involves parameters and existentially
6533 * quantified variables, return the index of the first equality
6534 * that only involves parameters. If there is no such equality then
6535 * return bset->n_eq.
6537 * This function assumes that isl_basic_set_gauss has been called on "bset".
6539 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
6541 int i, j;
6542 unsigned nparam, n_div;
6544 if (!bset)
6545 return -1;
6547 nparam = isl_basic_set_dim(bset, isl_dim_param);
6548 n_div = isl_basic_set_dim(bset, isl_dim_div);
6550 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
6551 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
6552 ++i;
6555 return i;
6558 /* Compute an explicit representation for the existentially quantified
6559 * variables in "bset" by computing the "minimal value" of the set
6560 * variables. Since there are no set variables, the computation of
6561 * the minimal value essentially computes an explicit representation
6562 * of the non-empty part(s) of "bset".
6564 * The input only involves parameters and existentially quantified variables.
6565 * All equalities among parameters have been removed.
6567 * Since the existentially quantified variables in the result are in general
6568 * going to be different from those in the input, we first replace
6569 * them by the minimal number of variables based on their equalities.
6570 * This should simplify the parametric integer programming.
6572 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
6574 isl_morph *morph1, *morph2;
6575 isl_set *set;
6576 unsigned n;
6578 if (!bset)
6579 return NULL;
6580 if (bset->n_eq == 0)
6581 return isl_basic_set_lexmin(bset);
6583 morph1 = isl_basic_set_parameter_compression(bset);
6584 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
6585 bset = isl_basic_set_lift(bset);
6586 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
6587 bset = isl_morph_basic_set(morph2, bset);
6588 n = isl_basic_set_dim(bset, isl_dim_set);
6589 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
6591 set = isl_basic_set_lexmin(bset);
6593 set = isl_morph_set(isl_morph_inverse(morph1), set);
6595 return set;
6598 /* Project the given basic set onto its parameter domain, possibly introducing
6599 * new, explicit, existential variables in the constraints.
6600 * The input has parameters and (possibly implicit) existential variables.
6601 * The output has the same parameters, but only
6602 * explicit existentially quantified variables.
6604 * The actual projection is performed by pip, but pip doesn't seem
6605 * to like equalities very much, so we first remove the equalities
6606 * among the parameters by performing a variable compression on
6607 * the parameters. Afterward, an inverse transformation is performed
6608 * and the equalities among the parameters are inserted back in.
6610 * The variable compression on the parameters may uncover additional
6611 * equalities that were only implicit before. We therefore check
6612 * if there are any new parameter equalities in the result and
6613 * if so recurse. The removal of parameter equalities is required
6614 * for the parameter compression performed by base_compute_divs.
6616 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
6618 int i;
6619 struct isl_mat *eq;
6620 struct isl_mat *T, *T2;
6621 struct isl_set *set;
6622 unsigned nparam;
6624 bset = isl_basic_set_cow(bset);
6625 if (!bset)
6626 return NULL;
6628 if (bset->n_eq == 0)
6629 return base_compute_divs(bset);
6631 bset = isl_basic_set_gauss(bset, NULL);
6632 if (!bset)
6633 return NULL;
6634 if (isl_basic_set_plain_is_empty(bset))
6635 return isl_set_from_basic_set(bset);
6637 i = first_parameter_equality(bset);
6638 if (i == bset->n_eq)
6639 return base_compute_divs(bset);
6641 nparam = isl_basic_set_dim(bset, isl_dim_param);
6642 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
6643 0, 1 + nparam);
6644 eq = isl_mat_cow(eq);
6645 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
6646 if (T && T->n_col == 0) {
6647 isl_mat_free(T);
6648 isl_mat_free(T2);
6649 isl_mat_free(eq);
6650 bset = isl_basic_set_set_to_empty(bset);
6651 return isl_set_from_basic_set(bset);
6653 bset = basic_set_parameter_preimage(bset, T);
6655 i = first_parameter_equality(bset);
6656 if (!bset)
6657 set = NULL;
6658 else if (i == bset->n_eq)
6659 set = base_compute_divs(bset);
6660 else
6661 set = parameter_compute_divs(bset);
6662 set = set_parameter_preimage(set, T2);
6663 set = set_append_equalities(set, eq);
6664 return set;
6667 /* Insert the divs from "ls" before those of "bmap".
6669 * The number of columns is not changed, which means that the last
6670 * dimensions of "bmap" are being reintepreted as the divs from "ls".
6671 * The caller is responsible for removing the same number of dimensions
6672 * from the space of "bmap".
6674 static __isl_give isl_basic_map *insert_divs_from_local_space(
6675 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
6677 int i;
6678 int n_div;
6679 int old_n_div;
6681 n_div = isl_local_space_dim(ls, isl_dim_div);
6682 if (n_div == 0)
6683 return bmap;
6685 old_n_div = bmap->n_div;
6686 bmap = insert_div_rows(bmap, n_div);
6687 if (!bmap)
6688 return NULL;
6690 for (i = 0; i < n_div; ++i) {
6691 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
6692 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
6695 return bmap;
6698 /* Replace the space of "bmap" by the space and divs of "ls".
6700 * If "ls" has any divs, then we simplify the result since we may
6701 * have discovered some additional equalities that could simplify
6702 * the div expressions.
6704 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
6705 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
6707 int n_div;
6709 bmap = isl_basic_map_cow(bmap);
6710 if (!bmap || !ls)
6711 goto error;
6713 n_div = isl_local_space_dim(ls, isl_dim_div);
6714 bmap = insert_divs_from_local_space(bmap, ls);
6715 if (!bmap)
6716 goto error;
6718 isl_space_free(bmap->dim);
6719 bmap->dim = isl_local_space_get_space(ls);
6720 if (!bmap->dim)
6721 goto error;
6723 isl_local_space_free(ls);
6724 if (n_div > 0)
6725 bmap = isl_basic_map_simplify(bmap);
6726 bmap = isl_basic_map_finalize(bmap);
6727 return bmap;
6728 error:
6729 isl_basic_map_free(bmap);
6730 isl_local_space_free(ls);
6731 return NULL;
6734 /* Replace the space of "map" by the space and divs of "ls".
6736 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
6737 __isl_take isl_local_space *ls)
6739 int i;
6741 map = isl_map_cow(map);
6742 if (!map || !ls)
6743 goto error;
6745 for (i = 0; i < map->n; ++i) {
6746 map->p[i] = basic_replace_space_by_local_space(map->p[i],
6747 isl_local_space_copy(ls));
6748 if (!map->p[i])
6749 goto error;
6751 isl_space_free(map->dim);
6752 map->dim = isl_local_space_get_space(ls);
6753 if (!map->dim)
6754 goto error;
6756 isl_local_space_free(ls);
6757 return map;
6758 error:
6759 isl_local_space_free(ls);
6760 isl_map_free(map);
6761 return NULL;
6764 /* Compute an explicit representation for the existentially
6765 * quantified variables for which do not know any explicit representation yet.
6767 * We first sort the existentially quantified variables so that the
6768 * existentially quantified variables for which we already have an explicit
6769 * representation are placed before those for which we do not.
6770 * The input dimensions, the output dimensions and the existentially
6771 * quantified variables for which we already have an explicit
6772 * representation are then turned into parameters.
6773 * compute_divs returns a map with the same parameters and
6774 * no input or output dimensions and the dimension specification
6775 * is reset to that of the input, including the existentially quantified
6776 * variables for which we already had an explicit representation.
6778 static struct isl_map *compute_divs(struct isl_basic_map *bmap)
6780 struct isl_basic_set *bset;
6781 struct isl_set *set;
6782 struct isl_map *map;
6783 isl_space *dim;
6784 isl_local_space *ls;
6785 unsigned nparam;
6786 unsigned n_in;
6787 unsigned n_out;
6788 unsigned n_known;
6789 int i;
6791 bmap = isl_basic_map_sort_divs(bmap);
6792 bmap = isl_basic_map_cow(bmap);
6793 if (!bmap)
6794 return NULL;
6796 for (n_known = 0; n_known < bmap->n_div; ++n_known)
6797 if (isl_int_is_zero(bmap->div[n_known][0]))
6798 break;
6800 nparam = isl_basic_map_dim(bmap, isl_dim_param);
6801 n_in = isl_basic_map_dim(bmap, isl_dim_in);
6802 n_out = isl_basic_map_dim(bmap, isl_dim_out);
6803 dim = isl_space_set_alloc(bmap->ctx,
6804 nparam + n_in + n_out + n_known, 0);
6805 if (!dim)
6806 goto error;
6808 ls = isl_basic_map_get_local_space(bmap);
6809 ls = isl_local_space_drop_dims(ls, isl_dim_div,
6810 n_known, bmap->n_div - n_known);
6811 if (n_known > 0) {
6812 for (i = n_known; i < bmap->n_div; ++i)
6813 swap_div(bmap, i - n_known, i);
6814 bmap->n_div -= n_known;
6815 bmap->extra -= n_known;
6817 bmap = isl_basic_map_reset_space(bmap, dim);
6818 bset = (struct isl_basic_set *)bmap;
6820 set = parameter_compute_divs(bset);
6821 map = (struct isl_map *)set;
6822 map = replace_space_by_local_space(map, ls);
6824 return map;
6825 error:
6826 isl_basic_map_free(bmap);
6827 return NULL;
6830 int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
6832 int i;
6833 unsigned off;
6835 if (!bmap)
6836 return -1;
6838 off = isl_space_dim(bmap->dim, isl_dim_all);
6839 for (i = 0; i < bmap->n_div; ++i) {
6840 if (isl_int_is_zero(bmap->div[i][0]))
6841 return 0;
6842 isl_assert(bmap->ctx, isl_int_is_zero(bmap->div[i][1+1+off+i]),
6843 return -1);
6845 return 1;
6848 static int map_divs_known(__isl_keep isl_map *map)
6850 int i;
6852 if (!map)
6853 return -1;
6855 for (i = 0; i < map->n; ++i) {
6856 int known = isl_basic_map_divs_known(map->p[i]);
6857 if (known <= 0)
6858 return known;
6861 return 1;
6864 /* If bmap contains any unknown divs, then compute explicit
6865 * expressions for them. However, this computation may be
6866 * quite expensive, so first try to remove divs that aren't
6867 * strictly needed.
6869 struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap)
6871 int known;
6872 struct isl_map *map;
6874 known = isl_basic_map_divs_known(bmap);
6875 if (known < 0)
6876 goto error;
6877 if (known)
6878 return isl_map_from_basic_map(bmap);
6880 bmap = isl_basic_map_drop_redundant_divs(bmap);
6882 known = isl_basic_map_divs_known(bmap);
6883 if (known < 0)
6884 goto error;
6885 if (known)
6886 return isl_map_from_basic_map(bmap);
6888 map = compute_divs(bmap);
6889 return map;
6890 error:
6891 isl_basic_map_free(bmap);
6892 return NULL;
6895 struct isl_map *isl_map_compute_divs(struct isl_map *map)
6897 int i;
6898 int known;
6899 struct isl_map *res;
6901 if (!map)
6902 return NULL;
6903 if (map->n == 0)
6904 return map;
6906 known = map_divs_known(map);
6907 if (known < 0) {
6908 isl_map_free(map);
6909 return NULL;
6911 if (known)
6912 return map;
6914 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
6915 for (i = 1 ; i < map->n; ++i) {
6916 struct isl_map *r2;
6917 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
6918 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
6919 res = isl_map_union_disjoint(res, r2);
6920 else
6921 res = isl_map_union(res, r2);
6923 isl_map_free(map);
6925 return res;
6928 struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset)
6930 return (struct isl_set *)
6931 isl_basic_map_compute_divs((struct isl_basic_map *)bset);
6934 struct isl_set *isl_set_compute_divs(struct isl_set *set)
6936 return (struct isl_set *)
6937 isl_map_compute_divs((struct isl_map *)set);
6940 struct isl_set *isl_map_domain(struct isl_map *map)
6942 int i;
6943 struct isl_set *set;
6945 if (!map)
6946 goto error;
6948 map = isl_map_cow(map);
6949 if (!map)
6950 return NULL;
6952 set = (struct isl_set *)map;
6953 set->dim = isl_space_domain(set->dim);
6954 if (!set->dim)
6955 goto error;
6956 for (i = 0; i < map->n; ++i) {
6957 set->p[i] = isl_basic_map_domain(map->p[i]);
6958 if (!set->p[i])
6959 goto error;
6961 ISL_F_CLR(set, ISL_MAP_DISJOINT);
6962 ISL_F_CLR(set, ISL_SET_NORMALIZED);
6963 return set;
6964 error:
6965 isl_map_free(map);
6966 return NULL;
6969 /* Return the union of "map1" and "map2", where we assume for now that
6970 * "map1" and "map2" are disjoint. Note that the basic maps inside
6971 * "map1" or "map2" may not be disjoint from each other.
6972 * Also note that this function is also called from isl_map_union,
6973 * which takes care of handling the situation where "map1" and "map2"
6974 * may not be disjoint.
6976 * If one of the inputs is empty, we can simply return the other input.
6977 * Similarly, if one of the inputs is universal, then it is equal to the union.
6979 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
6980 __isl_take isl_map *map2)
6982 int i;
6983 unsigned flags = 0;
6984 struct isl_map *map = NULL;
6985 int is_universe;
6987 if (!map1 || !map2)
6988 goto error;
6990 if (map1->n == 0) {
6991 isl_map_free(map1);
6992 return map2;
6994 if (map2->n == 0) {
6995 isl_map_free(map2);
6996 return map1;
6999 is_universe = isl_map_plain_is_universe(map1);
7000 if (is_universe < 0)
7001 goto error;
7002 if (is_universe) {
7003 isl_map_free(map2);
7004 return map1;
7007 is_universe = isl_map_plain_is_universe(map2);
7008 if (is_universe < 0)
7009 goto error;
7010 if (is_universe) {
7011 isl_map_free(map1);
7012 return map2;
7015 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
7017 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7018 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7019 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7021 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7022 map1->n + map2->n, flags);
7023 if (!map)
7024 goto error;
7025 for (i = 0; i < map1->n; ++i) {
7026 map = isl_map_add_basic_map(map,
7027 isl_basic_map_copy(map1->p[i]));
7028 if (!map)
7029 goto error;
7031 for (i = 0; i < map2->n; ++i) {
7032 map = isl_map_add_basic_map(map,
7033 isl_basic_map_copy(map2->p[i]));
7034 if (!map)
7035 goto error;
7037 isl_map_free(map1);
7038 isl_map_free(map2);
7039 return map;
7040 error:
7041 isl_map_free(map);
7042 isl_map_free(map1);
7043 isl_map_free(map2);
7044 return NULL;
7047 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7048 __isl_take isl_map *map2)
7050 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7053 struct isl_map *isl_map_union(struct isl_map *map1, struct isl_map *map2)
7055 map1 = isl_map_union_disjoint(map1, map2);
7056 if (!map1)
7057 return NULL;
7058 if (map1->n > 1)
7059 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7060 return map1;
7063 struct isl_set *isl_set_union_disjoint(
7064 struct isl_set *set1, struct isl_set *set2)
7066 return (struct isl_set *)
7067 isl_map_union_disjoint(
7068 (struct isl_map *)set1, (struct isl_map *)set2);
7071 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7073 return (struct isl_set *)
7074 isl_map_union((struct isl_map *)set1, (struct isl_map *)set2);
7077 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7078 * the results.
7080 * "map" and "set" are assumed to be compatible and non-NULL.
7082 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7083 __isl_take isl_set *set,
7084 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7085 __isl_take isl_basic_set *bset))
7087 unsigned flags = 0;
7088 struct isl_map *result;
7089 int i, j;
7091 if (isl_set_plain_is_universe(set)) {
7092 isl_set_free(set);
7093 return map;
7096 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7097 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7098 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7100 result = isl_map_alloc_space(isl_space_copy(map->dim),
7101 map->n * set->n, flags);
7102 for (i = 0; result && i < map->n; ++i)
7103 for (j = 0; j < set->n; ++j) {
7104 result = isl_map_add_basic_map(result,
7105 fn(isl_basic_map_copy(map->p[i]),
7106 isl_basic_set_copy(set->p[j])));
7107 if (!result)
7108 break;
7111 isl_map_free(map);
7112 isl_set_free(set);
7113 return result;
7116 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7117 __isl_take isl_set *set)
7119 if (!map || !set)
7120 goto error;
7122 if (!isl_map_compatible_range(map, set))
7123 isl_die(set->ctx, isl_error_invalid,
7124 "incompatible spaces", goto error);
7126 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7127 error:
7128 isl_map_free(map);
7129 isl_set_free(set);
7130 return NULL;
7133 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7134 __isl_take isl_set *set)
7136 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7139 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7140 __isl_take isl_set *set)
7142 if (!map || !set)
7143 goto error;
7145 if (!isl_map_compatible_domain(map, set))
7146 isl_die(set->ctx, isl_error_invalid,
7147 "incompatible spaces", goto error);
7149 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7150 error:
7151 isl_map_free(map);
7152 isl_set_free(set);
7153 return NULL;
7156 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7157 __isl_take isl_set *set)
7159 return isl_map_align_params_map_map_and(map, set,
7160 &map_intersect_domain);
7163 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7164 __isl_take isl_map *map2)
7166 if (!map1 || !map2)
7167 goto error;
7168 map1 = isl_map_reverse(map1);
7169 map1 = isl_map_apply_range(map1, map2);
7170 return isl_map_reverse(map1);
7171 error:
7172 isl_map_free(map1);
7173 isl_map_free(map2);
7174 return NULL;
7177 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7178 __isl_take isl_map *map2)
7180 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7183 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7184 __isl_take isl_map *map2)
7186 isl_space *dim_result;
7187 struct isl_map *result;
7188 int i, j;
7190 if (!map1 || !map2)
7191 goto error;
7193 dim_result = isl_space_join(isl_space_copy(map1->dim),
7194 isl_space_copy(map2->dim));
7196 result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
7197 if (!result)
7198 goto error;
7199 for (i = 0; i < map1->n; ++i)
7200 for (j = 0; j < map2->n; ++j) {
7201 result = isl_map_add_basic_map(result,
7202 isl_basic_map_apply_range(
7203 isl_basic_map_copy(map1->p[i]),
7204 isl_basic_map_copy(map2->p[j])));
7205 if (!result)
7206 goto error;
7208 isl_map_free(map1);
7209 isl_map_free(map2);
7210 if (result && result->n <= 1)
7211 ISL_F_SET(result, ISL_MAP_DISJOINT);
7212 return result;
7213 error:
7214 isl_map_free(map1);
7215 isl_map_free(map2);
7216 return NULL;
7219 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
7220 __isl_take isl_map *map2)
7222 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
7226 * returns range - domain
7228 struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap)
7230 isl_space *dims, *target_dim;
7231 struct isl_basic_set *bset;
7232 unsigned dim;
7233 unsigned nparam;
7234 int i;
7236 if (!bmap)
7237 goto error;
7238 isl_assert(bmap->ctx, isl_space_tuple_match(bmap->dim, isl_dim_in,
7239 bmap->dim, isl_dim_out),
7240 goto error);
7241 target_dim = isl_space_domain(isl_basic_map_get_space(bmap));
7242 dim = isl_basic_map_n_in(bmap);
7243 nparam = isl_basic_map_n_param(bmap);
7244 bset = isl_basic_set_from_basic_map(bmap);
7245 bset = isl_basic_set_cow(bset);
7246 dims = isl_basic_set_get_space(bset);
7247 dims = isl_space_add_dims(dims, isl_dim_set, dim);
7248 bset = isl_basic_set_extend_space(bset, dims, 0, dim, 0);
7249 bset = isl_basic_set_swap_vars(bset, 2*dim);
7250 for (i = 0; i < dim; ++i) {
7251 int j = isl_basic_map_alloc_equality(
7252 (struct isl_basic_map *)bset);
7253 if (j < 0) {
7254 bset = isl_basic_set_free(bset);
7255 break;
7257 isl_seq_clr(bset->eq[j], 1 + isl_basic_set_total_dim(bset));
7258 isl_int_set_si(bset->eq[j][1+nparam+i], 1);
7259 isl_int_set_si(bset->eq[j][1+nparam+dim+i], 1);
7260 isl_int_set_si(bset->eq[j][1+nparam+2*dim+i], -1);
7262 bset = isl_basic_set_project_out(bset, isl_dim_set, dim, 2*dim);
7263 bset = isl_basic_set_reset_space(bset, target_dim);
7264 return bset;
7265 error:
7266 isl_basic_map_free(bmap);
7267 return NULL;
7271 * returns range - domain
7273 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
7275 int i;
7276 isl_space *dim;
7277 struct isl_set *result;
7279 if (!map)
7280 return NULL;
7282 isl_assert(map->ctx, isl_space_tuple_match(map->dim, isl_dim_in,
7283 map->dim, isl_dim_out),
7284 goto error);
7285 dim = isl_map_get_space(map);
7286 dim = isl_space_domain(dim);
7287 result = isl_set_alloc_space(dim, map->n, 0);
7288 if (!result)
7289 goto error;
7290 for (i = 0; i < map->n; ++i)
7291 result = isl_set_add_basic_set(result,
7292 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
7293 isl_map_free(map);
7294 return result;
7295 error:
7296 isl_map_free(map);
7297 return NULL;
7301 * returns [domain -> range] -> range - domain
7303 __isl_give isl_basic_map *isl_basic_map_deltas_map(
7304 __isl_take isl_basic_map *bmap)
7306 int i, k;
7307 isl_space *dim;
7308 isl_basic_map *domain;
7309 int nparam, n;
7310 unsigned total;
7312 if (!isl_space_tuple_match(bmap->dim, isl_dim_in, bmap->dim, isl_dim_out))
7313 isl_die(bmap->ctx, isl_error_invalid,
7314 "domain and range don't match", goto error);
7316 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7317 n = isl_basic_map_dim(bmap, isl_dim_in);
7319 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
7320 domain = isl_basic_map_universe(dim);
7322 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
7323 bmap = isl_basic_map_apply_range(bmap, domain);
7324 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
7326 total = isl_basic_map_total_dim(bmap);
7328 for (i = 0; i < n; ++i) {
7329 k = isl_basic_map_alloc_equality(bmap);
7330 if (k < 0)
7331 goto error;
7332 isl_seq_clr(bmap->eq[k], 1 + total);
7333 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
7334 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
7335 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
7338 bmap = isl_basic_map_gauss(bmap, NULL);
7339 return isl_basic_map_finalize(bmap);
7340 error:
7341 isl_basic_map_free(bmap);
7342 return NULL;
7346 * returns [domain -> range] -> range - domain
7348 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
7350 int i;
7351 isl_space *domain_dim;
7353 if (!map)
7354 return NULL;
7356 if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
7357 isl_die(map->ctx, isl_error_invalid,
7358 "domain and range don't match", goto error);
7360 map = isl_map_cow(map);
7361 if (!map)
7362 return NULL;
7364 domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
7365 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
7366 map->dim = isl_space_join(map->dim, domain_dim);
7367 if (!map->dim)
7368 goto error;
7369 for (i = 0; i < map->n; ++i) {
7370 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
7371 if (!map->p[i])
7372 goto error;
7374 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
7375 return map;
7376 error:
7377 isl_map_free(map);
7378 return NULL;
7381 static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
7383 struct isl_basic_map *bmap;
7384 unsigned nparam;
7385 unsigned dim;
7386 int i;
7388 if (!dims)
7389 return NULL;
7391 nparam = dims->nparam;
7392 dim = dims->n_out;
7393 bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
7394 if (!bmap)
7395 goto error;
7397 for (i = 0; i < dim; ++i) {
7398 int j = isl_basic_map_alloc_equality(bmap);
7399 if (j < 0)
7400 goto error;
7401 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7402 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7403 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
7405 return isl_basic_map_finalize(bmap);
7406 error:
7407 isl_basic_map_free(bmap);
7408 return NULL;
7411 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
7413 if (!dim)
7414 return NULL;
7415 if (dim->n_in != dim->n_out)
7416 isl_die(dim->ctx, isl_error_invalid,
7417 "number of input and output dimensions needs to be "
7418 "the same", goto error);
7419 return basic_map_identity(dim);
7420 error:
7421 isl_space_free(dim);
7422 return NULL;
7425 struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model)
7427 if (!model || !model->dim)
7428 return NULL;
7429 return isl_basic_map_identity(isl_space_copy(model->dim));
7432 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
7434 return isl_map_from_basic_map(isl_basic_map_identity(dim));
7437 struct isl_map *isl_map_identity_like(struct isl_map *model)
7439 if (!model || !model->dim)
7440 return NULL;
7441 return isl_map_identity(isl_space_copy(model->dim));
7444 struct isl_map *isl_map_identity_like_basic_map(struct isl_basic_map *model)
7446 if (!model || !model->dim)
7447 return NULL;
7448 return isl_map_identity(isl_space_copy(model->dim));
7451 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
7453 isl_space *dim = isl_set_get_space(set);
7454 isl_map *id;
7455 id = isl_map_identity(isl_space_map_from_set(dim));
7456 return isl_map_intersect_range(id, set);
7459 /* Construct a basic set with all set dimensions having only non-negative
7460 * values.
7462 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
7463 __isl_take isl_space *space)
7465 int i;
7466 unsigned nparam;
7467 unsigned dim;
7468 struct isl_basic_set *bset;
7470 if (!space)
7471 return NULL;
7472 nparam = space->nparam;
7473 dim = space->n_out;
7474 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
7475 if (!bset)
7476 return NULL;
7477 for (i = 0; i < dim; ++i) {
7478 int k = isl_basic_set_alloc_inequality(bset);
7479 if (k < 0)
7480 goto error;
7481 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
7482 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
7484 return bset;
7485 error:
7486 isl_basic_set_free(bset);
7487 return NULL;
7490 /* Construct the half-space x_pos >= 0.
7492 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
7493 int pos)
7495 int k;
7496 isl_basic_set *nonneg;
7498 nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7499 k = isl_basic_set_alloc_inequality(nonneg);
7500 if (k < 0)
7501 goto error;
7502 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
7503 isl_int_set_si(nonneg->ineq[k][pos], 1);
7505 return isl_basic_set_finalize(nonneg);
7506 error:
7507 isl_basic_set_free(nonneg);
7508 return NULL;
7511 /* Construct the half-space x_pos <= -1.
7513 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
7515 int k;
7516 isl_basic_set *neg;
7518 neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7519 k = isl_basic_set_alloc_inequality(neg);
7520 if (k < 0)
7521 goto error;
7522 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
7523 isl_int_set_si(neg->ineq[k][0], -1);
7524 isl_int_set_si(neg->ineq[k][pos], -1);
7526 return isl_basic_set_finalize(neg);
7527 error:
7528 isl_basic_set_free(neg);
7529 return NULL;
7532 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
7533 enum isl_dim_type type, unsigned first, unsigned n)
7535 int i;
7536 isl_basic_set *nonneg;
7537 isl_basic_set *neg;
7539 if (!set)
7540 return NULL;
7541 if (n == 0)
7542 return set;
7544 isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
7546 for (i = 0; i < n; ++i) {
7547 nonneg = nonneg_halfspace(isl_set_get_space(set),
7548 pos(set->dim, type) + first + i);
7549 neg = neg_halfspace(isl_set_get_space(set),
7550 pos(set->dim, type) + first + i);
7552 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
7555 return set;
7556 error:
7557 isl_set_free(set);
7558 return NULL;
7561 static int foreach_orthant(__isl_take isl_set *set, int *signs, int first,
7562 int len, int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7563 void *user)
7565 isl_set *half;
7567 if (!set)
7568 return -1;
7569 if (isl_set_plain_is_empty(set)) {
7570 isl_set_free(set);
7571 return 0;
7573 if (first == len)
7574 return fn(set, signs, user);
7576 signs[first] = 1;
7577 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
7578 1 + first));
7579 half = isl_set_intersect(half, isl_set_copy(set));
7580 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
7581 goto error;
7583 signs[first] = -1;
7584 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
7585 1 + first));
7586 half = isl_set_intersect(half, set);
7587 return foreach_orthant(half, signs, first + 1, len, fn, user);
7588 error:
7589 isl_set_free(set);
7590 return -1;
7593 /* Call "fn" on the intersections of "set" with each of the orthants
7594 * (except for obviously empty intersections). The orthant is identified
7595 * by the signs array, with each entry having value 1 or -1 according
7596 * to the sign of the corresponding variable.
7598 int isl_set_foreach_orthant(__isl_keep isl_set *set,
7599 int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7600 void *user)
7602 unsigned nparam;
7603 unsigned nvar;
7604 int *signs;
7605 int r;
7607 if (!set)
7608 return -1;
7609 if (isl_set_plain_is_empty(set))
7610 return 0;
7612 nparam = isl_set_dim(set, isl_dim_param);
7613 nvar = isl_set_dim(set, isl_dim_set);
7615 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
7617 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
7618 fn, user);
7620 free(signs);
7622 return r;
7625 int isl_set_is_equal(struct isl_set *set1, struct isl_set *set2)
7627 return isl_map_is_equal((struct isl_map *)set1, (struct isl_map *)set2);
7630 int isl_basic_map_is_subset(
7631 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7633 int is_subset;
7634 struct isl_map *map1;
7635 struct isl_map *map2;
7637 if (!bmap1 || !bmap2)
7638 return -1;
7640 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
7641 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
7643 is_subset = isl_map_is_subset(map1, map2);
7645 isl_map_free(map1);
7646 isl_map_free(map2);
7648 return is_subset;
7651 int isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
7652 __isl_keep isl_basic_set *bset2)
7654 return isl_basic_map_is_subset(bset1, bset2);
7657 int isl_basic_map_is_equal(
7658 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7660 int is_subset;
7662 if (!bmap1 || !bmap2)
7663 return -1;
7664 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
7665 if (is_subset != 1)
7666 return is_subset;
7667 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
7668 return is_subset;
7671 int isl_basic_set_is_equal(
7672 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
7674 return isl_basic_map_is_equal(
7675 (struct isl_basic_map *)bset1, (struct isl_basic_map *)bset2);
7678 int isl_map_is_empty(struct isl_map *map)
7680 int i;
7681 int is_empty;
7683 if (!map)
7684 return -1;
7685 for (i = 0; i < map->n; ++i) {
7686 is_empty = isl_basic_map_is_empty(map->p[i]);
7687 if (is_empty < 0)
7688 return -1;
7689 if (!is_empty)
7690 return 0;
7692 return 1;
7695 int isl_map_plain_is_empty(__isl_keep isl_map *map)
7697 return map ? map->n == 0 : -1;
7700 int isl_map_fast_is_empty(__isl_keep isl_map *map)
7702 return isl_map_plain_is_empty(map);
7705 int isl_set_plain_is_empty(struct isl_set *set)
7707 return set ? set->n == 0 : -1;
7710 int isl_set_fast_is_empty(__isl_keep isl_set *set)
7712 return isl_set_plain_is_empty(set);
7715 int isl_set_is_empty(struct isl_set *set)
7717 return isl_map_is_empty((struct isl_map *)set);
7720 int isl_map_has_equal_space(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7722 if (!map1 || !map2)
7723 return -1;
7725 return isl_space_is_equal(map1->dim, map2->dim);
7728 int isl_set_has_equal_space(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
7730 if (!set1 || !set2)
7731 return -1;
7733 return isl_space_is_equal(set1->dim, set2->dim);
7736 static int map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7738 int is_subset;
7740 if (!map1 || !map2)
7741 return -1;
7742 is_subset = isl_map_is_subset(map1, map2);
7743 if (is_subset != 1)
7744 return is_subset;
7745 is_subset = isl_map_is_subset(map2, map1);
7746 return is_subset;
7749 int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7751 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
7754 int isl_basic_map_is_strict_subset(
7755 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7757 int is_subset;
7759 if (!bmap1 || !bmap2)
7760 return -1;
7761 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
7762 if (is_subset != 1)
7763 return is_subset;
7764 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
7765 if (is_subset == -1)
7766 return is_subset;
7767 return !is_subset;
7770 int isl_map_is_strict_subset(struct isl_map *map1, struct isl_map *map2)
7772 int is_subset;
7774 if (!map1 || !map2)
7775 return -1;
7776 is_subset = isl_map_is_subset(map1, map2);
7777 if (is_subset != 1)
7778 return is_subset;
7779 is_subset = isl_map_is_subset(map2, map1);
7780 if (is_subset == -1)
7781 return is_subset;
7782 return !is_subset;
7785 int isl_set_is_strict_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
7787 return isl_map_is_strict_subset((isl_map *)set1, (isl_map *)set2);
7790 int isl_basic_map_is_universe(struct isl_basic_map *bmap)
7792 if (!bmap)
7793 return -1;
7794 return bmap->n_eq == 0 && bmap->n_ineq == 0;
7797 int isl_basic_set_is_universe(struct isl_basic_set *bset)
7799 if (!bset)
7800 return -1;
7801 return bset->n_eq == 0 && bset->n_ineq == 0;
7804 int isl_map_plain_is_universe(__isl_keep isl_map *map)
7806 int i;
7808 if (!map)
7809 return -1;
7811 for (i = 0; i < map->n; ++i) {
7812 int r = isl_basic_map_is_universe(map->p[i]);
7813 if (r < 0 || r)
7814 return r;
7817 return 0;
7820 int isl_set_plain_is_universe(__isl_keep isl_set *set)
7822 return isl_map_plain_is_universe((isl_map *) set);
7825 int isl_set_fast_is_universe(__isl_keep isl_set *set)
7827 return isl_set_plain_is_universe(set);
7830 int isl_basic_map_is_empty(struct isl_basic_map *bmap)
7832 struct isl_basic_set *bset = NULL;
7833 struct isl_vec *sample = NULL;
7834 int empty;
7835 unsigned total;
7837 if (!bmap)
7838 return -1;
7840 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
7841 return 1;
7843 if (isl_basic_map_is_universe(bmap))
7844 return 0;
7846 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
7847 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
7848 copy = isl_basic_map_remove_redundancies(copy);
7849 empty = isl_basic_map_plain_is_empty(copy);
7850 isl_basic_map_free(copy);
7851 return empty;
7854 total = 1 + isl_basic_map_total_dim(bmap);
7855 if (bmap->sample && bmap->sample->size == total) {
7856 int contains = isl_basic_map_contains(bmap, bmap->sample);
7857 if (contains < 0)
7858 return -1;
7859 if (contains)
7860 return 0;
7862 isl_vec_free(bmap->sample);
7863 bmap->sample = NULL;
7864 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
7865 if (!bset)
7866 return -1;
7867 sample = isl_basic_set_sample_vec(bset);
7868 if (!sample)
7869 return -1;
7870 empty = sample->size == 0;
7871 isl_vec_free(bmap->sample);
7872 bmap->sample = sample;
7873 if (empty)
7874 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
7876 return empty;
7879 int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
7881 if (!bmap)
7882 return -1;
7883 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
7886 int isl_basic_map_fast_is_empty(__isl_keep isl_basic_map *bmap)
7888 return isl_basic_map_plain_is_empty(bmap);
7891 int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
7893 if (!bset)
7894 return -1;
7895 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
7898 int isl_basic_set_fast_is_empty(__isl_keep isl_basic_set *bset)
7900 return isl_basic_set_plain_is_empty(bset);
7903 int isl_basic_set_is_empty(struct isl_basic_set *bset)
7905 return isl_basic_map_is_empty((struct isl_basic_map *)bset);
7908 struct isl_map *isl_basic_map_union(
7909 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7911 struct isl_map *map;
7912 if (!bmap1 || !bmap2)
7913 goto error;
7915 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
7917 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
7918 if (!map)
7919 goto error;
7920 map = isl_map_add_basic_map(map, bmap1);
7921 map = isl_map_add_basic_map(map, bmap2);
7922 return map;
7923 error:
7924 isl_basic_map_free(bmap1);
7925 isl_basic_map_free(bmap2);
7926 return NULL;
7929 struct isl_set *isl_basic_set_union(
7930 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
7932 return (struct isl_set *)isl_basic_map_union(
7933 (struct isl_basic_map *)bset1,
7934 (struct isl_basic_map *)bset2);
7937 /* Order divs such that any div only depends on previous divs */
7938 struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap)
7940 int i;
7941 unsigned off;
7943 if (!bmap)
7944 return NULL;
7946 off = isl_space_dim(bmap->dim, isl_dim_all);
7948 for (i = 0; i < bmap->n_div; ++i) {
7949 int pos;
7950 if (isl_int_is_zero(bmap->div[i][0]))
7951 continue;
7952 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
7953 bmap->n_div-i);
7954 if (pos == -1)
7955 continue;
7956 isl_basic_map_swap_div(bmap, i, i + pos);
7957 --i;
7959 return bmap;
7962 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
7964 return (struct isl_basic_set *)
7965 isl_basic_map_order_divs((struct isl_basic_map *)bset);
7968 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
7970 int i;
7972 if (!map)
7973 return 0;
7975 for (i = 0; i < map->n; ++i) {
7976 map->p[i] = isl_basic_map_order_divs(map->p[i]);
7977 if (!map->p[i])
7978 goto error;
7981 return map;
7982 error:
7983 isl_map_free(map);
7984 return NULL;
7987 /* Apply the expansion computed by isl_merge_divs.
7988 * The expansion itself is given by "exp" while the resulting
7989 * list of divs is given by "div".
7991 __isl_give isl_basic_set *isl_basic_set_expand_divs(
7992 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
7994 int i, j;
7995 int n_div;
7997 bset = isl_basic_set_cow(bset);
7998 if (!bset || !div)
7999 goto error;
8001 if (div->n_row < bset->n_div)
8002 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8003 "not an expansion", goto error);
8005 n_div = bset->n_div;
8006 bset = isl_basic_map_extend_space(bset, isl_space_copy(bset->dim),
8007 div->n_row - n_div, 0,
8008 2 * (div->n_row - n_div));
8010 for (i = n_div; i < div->n_row; ++i)
8011 if (isl_basic_set_alloc_div(bset) < 0)
8012 goto error;
8014 j = n_div - 1;
8015 for (i = div->n_row - 1; i >= 0; --i) {
8016 if (j >= 0 && exp[j] == i) {
8017 if (i != j)
8018 isl_basic_map_swap_div(bset, i, j);
8019 j--;
8020 } else {
8021 isl_seq_cpy(bset->div[i], div->row[i], div->n_col);
8022 if (isl_basic_map_add_div_constraints(bset, i) < 0)
8023 goto error;
8027 isl_mat_free(div);
8028 return bset;
8029 error:
8030 isl_basic_set_free(bset);
8031 isl_mat_free(div);
8032 return NULL;
8035 /* Look for a div in dst that corresponds to the div "div" in src.
8036 * The divs before "div" in src and dst are assumed to be the same.
8038 * Returns -1 if no corresponding div was found and the position
8039 * of the corresponding div in dst otherwise.
8041 static int find_div(struct isl_basic_map *dst,
8042 struct isl_basic_map *src, unsigned div)
8044 int i;
8046 unsigned total = isl_space_dim(src->dim, isl_dim_all);
8048 isl_assert(dst->ctx, div <= dst->n_div, return -1);
8049 for (i = div; i < dst->n_div; ++i)
8050 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8051 isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8052 dst->n_div - div) == -1)
8053 return i;
8054 return -1;
8057 struct isl_basic_map *isl_basic_map_align_divs(
8058 struct isl_basic_map *dst, struct isl_basic_map *src)
8060 int i;
8061 unsigned total;
8063 if (!dst || !src)
8064 goto error;
8066 if (src->n_div == 0)
8067 return dst;
8069 for (i = 0; i < src->n_div; ++i)
8070 isl_assert(src->ctx, !isl_int_is_zero(src->div[i][0]), goto error);
8072 src = isl_basic_map_order_divs(src);
8073 dst = isl_basic_map_cow(dst);
8074 if (!dst)
8075 return NULL;
8076 dst = isl_basic_map_extend_space(dst, isl_space_copy(dst->dim),
8077 src->n_div, 0, 2 * src->n_div);
8078 if (!dst)
8079 return NULL;
8080 total = isl_space_dim(src->dim, isl_dim_all);
8081 for (i = 0; i < src->n_div; ++i) {
8082 int j = find_div(dst, src, i);
8083 if (j < 0) {
8084 j = isl_basic_map_alloc_div(dst);
8085 if (j < 0)
8086 goto error;
8087 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8088 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8089 if (isl_basic_map_add_div_constraints(dst, j) < 0)
8090 goto error;
8092 if (j != i)
8093 isl_basic_map_swap_div(dst, i, j);
8095 return dst;
8096 error:
8097 isl_basic_map_free(dst);
8098 return NULL;
8101 struct isl_basic_set *isl_basic_set_align_divs(
8102 struct isl_basic_set *dst, struct isl_basic_set *src)
8104 return (struct isl_basic_set *)isl_basic_map_align_divs(
8105 (struct isl_basic_map *)dst, (struct isl_basic_map *)src);
8108 struct isl_map *isl_map_align_divs(struct isl_map *map)
8110 int i;
8112 if (!map)
8113 return NULL;
8114 if (map->n == 0)
8115 return map;
8116 map = isl_map_compute_divs(map);
8117 map = isl_map_cow(map);
8118 if (!map)
8119 return NULL;
8121 for (i = 1; i < map->n; ++i)
8122 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8123 for (i = 1; i < map->n; ++i) {
8124 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8125 if (!map->p[i])
8126 return isl_map_free(map);
8129 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
8130 return map;
8133 struct isl_set *isl_set_align_divs(struct isl_set *set)
8135 return (struct isl_set *)isl_map_align_divs((struct isl_map *)set);
8138 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
8139 __isl_take isl_map *map)
8141 if (!set || !map)
8142 goto error;
8143 isl_assert(set->ctx, isl_map_compatible_domain(map, set), goto error);
8144 map = isl_map_intersect_domain(map, set);
8145 set = isl_map_range(map);
8146 return set;
8147 error:
8148 isl_set_free(set);
8149 isl_map_free(map);
8150 return NULL;
8153 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
8154 __isl_take isl_map *map)
8156 return isl_map_align_params_map_map_and(set, map, &set_apply);
8159 /* There is no need to cow as removing empty parts doesn't change
8160 * the meaning of the set.
8162 struct isl_map *isl_map_remove_empty_parts(struct isl_map *map)
8164 int i;
8166 if (!map)
8167 return NULL;
8169 for (i = map->n - 1; i >= 0; --i)
8170 remove_if_empty(map, i);
8172 return map;
8175 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
8177 return (struct isl_set *)
8178 isl_map_remove_empty_parts((struct isl_map *)set);
8181 struct isl_basic_map *isl_map_copy_basic_map(struct isl_map *map)
8183 struct isl_basic_map *bmap;
8184 if (!map || map->n == 0)
8185 return NULL;
8186 bmap = map->p[map->n-1];
8187 isl_assert(map->ctx, ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL), return NULL);
8188 return isl_basic_map_copy(bmap);
8191 struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set)
8193 return (struct isl_basic_set *)
8194 isl_map_copy_basic_map((struct isl_map *)set);
8197 __isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map,
8198 __isl_keep isl_basic_map *bmap)
8200 int i;
8202 if (!map || !bmap)
8203 goto error;
8204 for (i = map->n-1; i >= 0; --i) {
8205 if (map->p[i] != bmap)
8206 continue;
8207 map = isl_map_cow(map);
8208 if (!map)
8209 goto error;
8210 isl_basic_map_free(map->p[i]);
8211 if (i != map->n-1) {
8212 ISL_F_CLR(map, ISL_SET_NORMALIZED);
8213 map->p[i] = map->p[map->n-1];
8215 map->n--;
8216 return map;
8218 return map;
8219 error:
8220 isl_map_free(map);
8221 return NULL;
8224 struct isl_set *isl_set_drop_basic_set(struct isl_set *set,
8225 struct isl_basic_set *bset)
8227 return (struct isl_set *)isl_map_drop_basic_map((struct isl_map *)set,
8228 (struct isl_basic_map *)bset);
8231 /* Given two basic sets bset1 and bset2, compute the maximal difference
8232 * between the values of dimension pos in bset1 and those in bset2
8233 * for any common value of the parameters and dimensions preceding pos.
8235 static enum isl_lp_result basic_set_maximal_difference_at(
8236 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
8237 int pos, isl_int *opt)
8239 isl_space *dims;
8240 struct isl_basic_map *bmap1 = NULL;
8241 struct isl_basic_map *bmap2 = NULL;
8242 struct isl_ctx *ctx;
8243 struct isl_vec *obj;
8244 unsigned total;
8245 unsigned nparam;
8246 unsigned dim1, dim2;
8247 enum isl_lp_result res;
8249 if (!bset1 || !bset2)
8250 return isl_lp_error;
8252 nparam = isl_basic_set_n_param(bset1);
8253 dim1 = isl_basic_set_n_dim(bset1);
8254 dim2 = isl_basic_set_n_dim(bset2);
8255 dims = isl_space_alloc(bset1->ctx, nparam, pos, dim1 - pos);
8256 bmap1 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset1), dims);
8257 dims = isl_space_alloc(bset2->ctx, nparam, pos, dim2 - pos);
8258 bmap2 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset2), dims);
8259 if (!bmap1 || !bmap2)
8260 goto error;
8261 bmap1 = isl_basic_map_cow(bmap1);
8262 bmap1 = isl_basic_map_extend(bmap1, nparam,
8263 pos, (dim1 - pos) + (dim2 - pos),
8264 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
8265 bmap1 = add_constraints(bmap1, bmap2, 0, dim1 - pos);
8266 if (!bmap1)
8267 goto error;
8268 total = isl_basic_map_total_dim(bmap1);
8269 ctx = bmap1->ctx;
8270 obj = isl_vec_alloc(ctx, 1 + total);
8271 if (!obj)
8272 goto error2;
8273 isl_seq_clr(obj->block.data, 1 + total);
8274 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
8275 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
8276 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
8277 opt, NULL, NULL);
8278 isl_basic_map_free(bmap1);
8279 isl_vec_free(obj);
8280 return res;
8281 error:
8282 isl_basic_map_free(bmap2);
8283 error2:
8284 isl_basic_map_free(bmap1);
8285 return isl_lp_error;
8288 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
8289 * for any common value of the parameters and dimensions preceding pos
8290 * in both basic sets, the values of dimension pos in bset1 are
8291 * smaller or larger than those in bset2.
8293 * Returns
8294 * 1 if bset1 follows bset2
8295 * -1 if bset1 precedes bset2
8296 * 0 if bset1 and bset2 are incomparable
8297 * -2 if some error occurred.
8299 int isl_basic_set_compare_at(struct isl_basic_set *bset1,
8300 struct isl_basic_set *bset2, int pos)
8302 isl_int opt;
8303 enum isl_lp_result res;
8304 int cmp;
8306 isl_int_init(opt);
8308 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8310 if (res == isl_lp_empty)
8311 cmp = 0;
8312 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8313 res == isl_lp_unbounded)
8314 cmp = 1;
8315 else if (res == isl_lp_ok && isl_int_is_neg(opt))
8316 cmp = -1;
8317 else
8318 cmp = -2;
8320 isl_int_clear(opt);
8321 return cmp;
8324 /* Given two basic sets bset1 and bset2, check whether
8325 * for any common value of the parameters and dimensions preceding pos
8326 * there is a value of dimension pos in bset1 that is larger
8327 * than a value of the same dimension in bset2.
8329 * Return
8330 * 1 if there exists such a pair
8331 * 0 if there is no such pair, but there is a pair of equal values
8332 * -1 otherwise
8333 * -2 if some error occurred.
8335 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
8336 __isl_keep isl_basic_set *bset2, int pos)
8338 isl_int opt;
8339 enum isl_lp_result res;
8340 int cmp;
8342 isl_int_init(opt);
8344 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8346 if (res == isl_lp_empty)
8347 cmp = -1;
8348 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8349 res == isl_lp_unbounded)
8350 cmp = 1;
8351 else if (res == isl_lp_ok && isl_int_is_neg(opt))
8352 cmp = -1;
8353 else if (res == isl_lp_ok)
8354 cmp = 0;
8355 else
8356 cmp = -2;
8358 isl_int_clear(opt);
8359 return cmp;
8362 /* Given two sets set1 and set2, check whether
8363 * for any common value of the parameters and dimensions preceding pos
8364 * there is a value of dimension pos in set1 that is larger
8365 * than a value of the same dimension in set2.
8367 * Return
8368 * 1 if there exists such a pair
8369 * 0 if there is no such pair, but there is a pair of equal values
8370 * -1 otherwise
8371 * -2 if some error occurred.
8373 int isl_set_follows_at(__isl_keep isl_set *set1,
8374 __isl_keep isl_set *set2, int pos)
8376 int i, j;
8377 int follows = -1;
8379 if (!set1 || !set2)
8380 return -2;
8382 for (i = 0; i < set1->n; ++i)
8383 for (j = 0; j < set2->n; ++j) {
8384 int f;
8385 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
8386 if (f == 1 || f == -2)
8387 return f;
8388 if (f > follows)
8389 follows = f;
8392 return follows;
8395 static int isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map *bmap,
8396 unsigned pos, isl_int *val)
8398 int i;
8399 int d;
8400 unsigned total;
8402 if (!bmap)
8403 return -1;
8404 total = isl_basic_map_total_dim(bmap);
8405 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
8406 for (; d+1 > pos; --d)
8407 if (!isl_int_is_zero(bmap->eq[i][1+d]))
8408 break;
8409 if (d != pos)
8410 continue;
8411 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
8412 return 0;
8413 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
8414 return 0;
8415 if (!isl_int_is_one(bmap->eq[i][1+d]))
8416 return 0;
8417 if (val)
8418 isl_int_neg(*val, bmap->eq[i][0]);
8419 return 1;
8421 return 0;
8424 static int isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
8425 unsigned pos, isl_int *val)
8427 int i;
8428 isl_int v;
8429 isl_int tmp;
8430 int fixed;
8432 if (!map)
8433 return -1;
8434 if (map->n == 0)
8435 return 0;
8436 if (map->n == 1)
8437 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
8438 isl_int_init(v);
8439 isl_int_init(tmp);
8440 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
8441 for (i = 1; fixed == 1 && i < map->n; ++i) {
8442 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
8443 if (fixed == 1 && isl_int_ne(tmp, v))
8444 fixed = 0;
8446 if (val)
8447 isl_int_set(*val, v);
8448 isl_int_clear(tmp);
8449 isl_int_clear(v);
8450 return fixed;
8453 static int isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set *bset,
8454 unsigned pos, isl_int *val)
8456 return isl_basic_map_plain_has_fixed_var((struct isl_basic_map *)bset,
8457 pos, val);
8460 static int isl_set_plain_has_fixed_var(__isl_keep isl_set *set, unsigned pos,
8461 isl_int *val)
8463 return isl_map_plain_has_fixed_var((struct isl_map *)set, pos, val);
8466 int isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
8467 enum isl_dim_type type, unsigned pos, isl_int *val)
8469 if (pos >= isl_basic_map_dim(bmap, type))
8470 return -1;
8471 return isl_basic_map_plain_has_fixed_var(bmap,
8472 isl_basic_map_offset(bmap, type) - 1 + pos, val);
8475 /* If "bmap" obviously lies on a hyperplane where the given dimension
8476 * has a fixed value, then return that value.
8477 * Otherwise return NaN.
8479 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
8480 __isl_keep isl_basic_map *bmap,
8481 enum isl_dim_type type, unsigned pos)
8483 isl_ctx *ctx;
8484 isl_val *v;
8485 int fixed;
8487 if (!bmap)
8488 return NULL;
8489 ctx = isl_basic_map_get_ctx(bmap);
8490 v = isl_val_alloc(ctx);
8491 if (!v)
8492 return NULL;
8493 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
8494 if (fixed < 0)
8495 return isl_val_free(v);
8496 if (fixed) {
8497 isl_int_set_si(v->d, 1);
8498 return v;
8500 isl_val_free(v);
8501 return isl_val_nan(ctx);
8504 int isl_map_plain_is_fixed(__isl_keep isl_map *map,
8505 enum isl_dim_type type, unsigned pos, isl_int *val)
8507 if (pos >= isl_map_dim(map, type))
8508 return -1;
8509 return isl_map_plain_has_fixed_var(map,
8510 map_offset(map, type) - 1 + pos, val);
8513 /* If "map" obviously lies on a hyperplane where the given dimension
8514 * has a fixed value, then return that value.
8515 * Otherwise return NaN.
8517 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
8518 enum isl_dim_type type, unsigned pos)
8520 isl_ctx *ctx;
8521 isl_val *v;
8522 int fixed;
8524 if (!map)
8525 return NULL;
8526 ctx = isl_map_get_ctx(map);
8527 v = isl_val_alloc(ctx);
8528 if (!v)
8529 return NULL;
8530 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
8531 if (fixed < 0)
8532 return isl_val_free(v);
8533 if (fixed) {
8534 isl_int_set_si(v->d, 1);
8535 return v;
8537 isl_val_free(v);
8538 return isl_val_nan(ctx);
8541 /* If "set" obviously lies on a hyperplane where the given dimension
8542 * has a fixed value, then return that value.
8543 * Otherwise return NaN.
8545 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
8546 enum isl_dim_type type, unsigned pos)
8548 return isl_map_plain_get_val_if_fixed(set, type, pos);
8551 int isl_set_plain_is_fixed(__isl_keep isl_set *set,
8552 enum isl_dim_type type, unsigned pos, isl_int *val)
8554 return isl_map_plain_is_fixed(set, type, pos, val);
8557 int isl_map_fast_is_fixed(__isl_keep isl_map *map,
8558 enum isl_dim_type type, unsigned pos, isl_int *val)
8560 return isl_map_plain_is_fixed(map, type, pos, val);
8563 /* Check if dimension dim has fixed value and if so and if val is not NULL,
8564 * then return this fixed value in *val.
8566 int isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
8567 unsigned dim, isl_int *val)
8569 return isl_basic_set_plain_has_fixed_var(bset,
8570 isl_basic_set_n_param(bset) + dim, val);
8573 /* Check if dimension dim has fixed value and if so and if val is not NULL,
8574 * then return this fixed value in *val.
8576 int isl_set_plain_dim_is_fixed(__isl_keep isl_set *set,
8577 unsigned dim, isl_int *val)
8579 return isl_set_plain_has_fixed_var(set, isl_set_n_param(set) + dim, val);
8582 int isl_set_fast_dim_is_fixed(__isl_keep isl_set *set,
8583 unsigned dim, isl_int *val)
8585 return isl_set_plain_dim_is_fixed(set, dim, val);
8588 /* Check if input variable in has fixed value and if so and if val is not NULL,
8589 * then return this fixed value in *val.
8591 int isl_map_plain_input_is_fixed(__isl_keep isl_map *map,
8592 unsigned in, isl_int *val)
8594 return isl_map_plain_has_fixed_var(map, isl_map_n_param(map) + in, val);
8597 /* Check if dimension dim has an (obvious) fixed lower bound and if so
8598 * and if val is not NULL, then return this lower bound in *val.
8600 int isl_basic_set_plain_dim_has_fixed_lower_bound(
8601 __isl_keep isl_basic_set *bset, unsigned dim, isl_int *val)
8603 int i, i_eq = -1, i_ineq = -1;
8604 isl_int *c;
8605 unsigned total;
8606 unsigned nparam;
8608 if (!bset)
8609 return -1;
8610 total = isl_basic_set_total_dim(bset);
8611 nparam = isl_basic_set_n_param(bset);
8612 for (i = 0; i < bset->n_eq; ++i) {
8613 if (isl_int_is_zero(bset->eq[i][1+nparam+dim]))
8614 continue;
8615 if (i_eq != -1)
8616 return 0;
8617 i_eq = i;
8619 for (i = 0; i < bset->n_ineq; ++i) {
8620 if (!isl_int_is_pos(bset->ineq[i][1+nparam+dim]))
8621 continue;
8622 if (i_eq != -1 || i_ineq != -1)
8623 return 0;
8624 i_ineq = i;
8626 if (i_eq == -1 && i_ineq == -1)
8627 return 0;
8628 c = i_eq != -1 ? bset->eq[i_eq] : bset->ineq[i_ineq];
8629 /* The coefficient should always be one due to normalization. */
8630 if (!isl_int_is_one(c[1+nparam+dim]))
8631 return 0;
8632 if (isl_seq_first_non_zero(c+1, nparam+dim) != -1)
8633 return 0;
8634 if (isl_seq_first_non_zero(c+1+nparam+dim+1,
8635 total - nparam - dim - 1) != -1)
8636 return 0;
8637 if (val)
8638 isl_int_neg(*val, c[0]);
8639 return 1;
8642 int isl_set_plain_dim_has_fixed_lower_bound(__isl_keep isl_set *set,
8643 unsigned dim, isl_int *val)
8645 int i;
8646 isl_int v;
8647 isl_int tmp;
8648 int fixed;
8650 if (!set)
8651 return -1;
8652 if (set->n == 0)
8653 return 0;
8654 if (set->n == 1)
8655 return isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0],
8656 dim, val);
8657 isl_int_init(v);
8658 isl_int_init(tmp);
8659 fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0],
8660 dim, &v);
8661 for (i = 1; fixed == 1 && i < set->n; ++i) {
8662 fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[i],
8663 dim, &tmp);
8664 if (fixed == 1 && isl_int_ne(tmp, v))
8665 fixed = 0;
8667 if (val)
8668 isl_int_set(*val, v);
8669 isl_int_clear(tmp);
8670 isl_int_clear(v);
8671 return fixed;
8674 struct constraint {
8675 unsigned size;
8676 isl_int *c;
8679 /* uset_gist depends on constraints without existentially quantified
8680 * variables sorting first.
8682 static int qsort_constraint_cmp(const void *p1, const void *p2)
8684 const struct constraint *c1 = (const struct constraint *)p1;
8685 const struct constraint *c2 = (const struct constraint *)p2;
8686 int l1, l2;
8687 unsigned size = isl_min(c1->size, c2->size);
8689 l1 = isl_seq_last_non_zero(c1->c + 1, size);
8690 l2 = isl_seq_last_non_zero(c2->c + 1, size);
8692 if (l1 != l2)
8693 return l1 - l2;
8695 return isl_seq_cmp(c1->c + 1, c2->c + 1, size);
8698 static struct isl_basic_map *isl_basic_map_sort_constraints(
8699 struct isl_basic_map *bmap)
8701 int i;
8702 struct constraint *c;
8703 unsigned total;
8705 if (!bmap)
8706 return NULL;
8707 total = isl_basic_map_total_dim(bmap);
8708 c = isl_alloc_array(bmap->ctx, struct constraint, bmap->n_ineq);
8709 if (!c)
8710 goto error;
8711 for (i = 0; i < bmap->n_ineq; ++i) {
8712 c[i].size = total;
8713 c[i].c = bmap->ineq[i];
8715 qsort(c, bmap->n_ineq, sizeof(struct constraint), qsort_constraint_cmp);
8716 for (i = 0; i < bmap->n_ineq; ++i)
8717 bmap->ineq[i] = c[i].c;
8718 free(c);
8719 return bmap;
8720 error:
8721 isl_basic_map_free(bmap);
8722 return NULL;
8725 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
8726 __isl_take isl_basic_set *bset)
8728 return (struct isl_basic_set *)isl_basic_map_sort_constraints(
8729 (struct isl_basic_map *)bset);
8732 struct isl_basic_map *isl_basic_map_normalize(struct isl_basic_map *bmap)
8734 if (!bmap)
8735 return NULL;
8736 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
8737 return bmap;
8738 bmap = isl_basic_map_remove_redundancies(bmap);
8739 bmap = isl_basic_map_sort_constraints(bmap);
8740 if (bmap)
8741 ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
8742 return bmap;
8745 struct isl_basic_set *isl_basic_set_normalize(struct isl_basic_set *bset)
8747 return (struct isl_basic_set *)isl_basic_map_normalize(
8748 (struct isl_basic_map *)bset);
8751 int isl_basic_map_plain_cmp(const __isl_keep isl_basic_map *bmap1,
8752 const __isl_keep isl_basic_map *bmap2)
8754 int i, cmp;
8755 unsigned total;
8757 if (bmap1 == bmap2)
8758 return 0;
8759 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
8760 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
8761 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
8762 if (isl_basic_map_n_param(bmap1) != isl_basic_map_n_param(bmap2))
8763 return isl_basic_map_n_param(bmap1) - isl_basic_map_n_param(bmap2);
8764 if (isl_basic_map_n_in(bmap1) != isl_basic_map_n_in(bmap2))
8765 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
8766 if (isl_basic_map_n_out(bmap1) != isl_basic_map_n_out(bmap2))
8767 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
8768 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
8769 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
8770 return 0;
8771 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
8772 return 1;
8773 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
8774 return -1;
8775 if (bmap1->n_eq != bmap2->n_eq)
8776 return bmap1->n_eq - bmap2->n_eq;
8777 if (bmap1->n_ineq != bmap2->n_ineq)
8778 return bmap1->n_ineq - bmap2->n_ineq;
8779 if (bmap1->n_div != bmap2->n_div)
8780 return bmap1->n_div - bmap2->n_div;
8781 total = isl_basic_map_total_dim(bmap1);
8782 for (i = 0; i < bmap1->n_eq; ++i) {
8783 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
8784 if (cmp)
8785 return cmp;
8787 for (i = 0; i < bmap1->n_ineq; ++i) {
8788 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
8789 if (cmp)
8790 return cmp;
8792 for (i = 0; i < bmap1->n_div; ++i) {
8793 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
8794 if (cmp)
8795 return cmp;
8797 return 0;
8800 int isl_basic_set_plain_cmp(const __isl_keep isl_basic_set *bset1,
8801 const __isl_keep isl_basic_set *bset2)
8803 return isl_basic_map_plain_cmp(bset1, bset2);
8806 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8808 int i, cmp;
8810 if (set1 == set2)
8811 return 0;
8812 if (set1->n != set2->n)
8813 return set1->n - set2->n;
8815 for (i = 0; i < set1->n; ++i) {
8816 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
8817 if (cmp)
8818 return cmp;
8821 return 0;
8824 int isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
8825 __isl_keep isl_basic_map *bmap2)
8827 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
8830 int isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
8831 __isl_keep isl_basic_set *bset2)
8833 return isl_basic_map_plain_is_equal((isl_basic_map *)bset1,
8834 (isl_basic_map *)bset2);
8837 static int qsort_bmap_cmp(const void *p1, const void *p2)
8839 const struct isl_basic_map *bmap1 = *(const struct isl_basic_map **)p1;
8840 const struct isl_basic_map *bmap2 = *(const struct isl_basic_map **)p2;
8842 return isl_basic_map_plain_cmp(bmap1, bmap2);
8845 /* We normalize in place, but if anything goes wrong we need
8846 * to return NULL, so we need to make sure we don't change the
8847 * meaning of any possible other copies of map.
8849 struct isl_map *isl_map_normalize(struct isl_map *map)
8851 int i, j;
8852 struct isl_basic_map *bmap;
8854 if (!map)
8855 return NULL;
8856 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
8857 return map;
8858 for (i = 0; i < map->n; ++i) {
8859 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
8860 if (!bmap)
8861 goto error;
8862 isl_basic_map_free(map->p[i]);
8863 map->p[i] = bmap;
8865 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
8866 ISL_F_SET(map, ISL_MAP_NORMALIZED);
8867 map = isl_map_remove_empty_parts(map);
8868 if (!map)
8869 return NULL;
8870 for (i = map->n - 1; i >= 1; --i) {
8871 if (!isl_basic_map_plain_is_equal(map->p[i-1], map->p[i]))
8872 continue;
8873 isl_basic_map_free(map->p[i-1]);
8874 for (j = i; j < map->n; ++j)
8875 map->p[j-1] = map->p[j];
8876 map->n--;
8878 return map;
8879 error:
8880 isl_map_free(map);
8881 return NULL;
8885 struct isl_set *isl_set_normalize(struct isl_set *set)
8887 return (struct isl_set *)isl_map_normalize((struct isl_map *)set);
8890 int isl_map_plain_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8892 int i;
8893 int equal;
8895 if (!map1 || !map2)
8896 return -1;
8898 if (map1 == map2)
8899 return 1;
8900 if (!isl_space_is_equal(map1->dim, map2->dim))
8901 return 0;
8903 map1 = isl_map_copy(map1);
8904 map2 = isl_map_copy(map2);
8905 map1 = isl_map_normalize(map1);
8906 map2 = isl_map_normalize(map2);
8907 if (!map1 || !map2)
8908 goto error;
8909 equal = map1->n == map2->n;
8910 for (i = 0; equal && i < map1->n; ++i) {
8911 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
8912 if (equal < 0)
8913 goto error;
8915 isl_map_free(map1);
8916 isl_map_free(map2);
8917 return equal;
8918 error:
8919 isl_map_free(map1);
8920 isl_map_free(map2);
8921 return -1;
8924 int isl_map_fast_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8926 return isl_map_plain_is_equal(map1, map2);
8929 int isl_set_plain_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8931 return isl_map_plain_is_equal((struct isl_map *)set1,
8932 (struct isl_map *)set2);
8935 int isl_set_fast_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8937 return isl_set_plain_is_equal(set1, set2);
8940 /* Return an interval that ranges from min to max (inclusive)
8942 struct isl_basic_set *isl_basic_set_interval(struct isl_ctx *ctx,
8943 isl_int min, isl_int max)
8945 int k;
8946 struct isl_basic_set *bset = NULL;
8948 bset = isl_basic_set_alloc(ctx, 0, 1, 0, 0, 2);
8949 if (!bset)
8950 goto error;
8952 k = isl_basic_set_alloc_inequality(bset);
8953 if (k < 0)
8954 goto error;
8955 isl_int_set_si(bset->ineq[k][1], 1);
8956 isl_int_neg(bset->ineq[k][0], min);
8958 k = isl_basic_set_alloc_inequality(bset);
8959 if (k < 0)
8960 goto error;
8961 isl_int_set_si(bset->ineq[k][1], -1);
8962 isl_int_set(bset->ineq[k][0], max);
8964 return bset;
8965 error:
8966 isl_basic_set_free(bset);
8967 return NULL;
8970 /* Return the Cartesian product of the basic sets in list (in the given order).
8972 __isl_give isl_basic_set *isl_basic_set_list_product(
8973 __isl_take struct isl_basic_set_list *list)
8975 int i;
8976 unsigned dim;
8977 unsigned nparam;
8978 unsigned extra;
8979 unsigned n_eq;
8980 unsigned n_ineq;
8981 struct isl_basic_set *product = NULL;
8983 if (!list)
8984 goto error;
8985 isl_assert(list->ctx, list->n > 0, goto error);
8986 isl_assert(list->ctx, list->p[0], goto error);
8987 nparam = isl_basic_set_n_param(list->p[0]);
8988 dim = isl_basic_set_n_dim(list->p[0]);
8989 extra = list->p[0]->n_div;
8990 n_eq = list->p[0]->n_eq;
8991 n_ineq = list->p[0]->n_ineq;
8992 for (i = 1; i < list->n; ++i) {
8993 isl_assert(list->ctx, list->p[i], goto error);
8994 isl_assert(list->ctx,
8995 nparam == isl_basic_set_n_param(list->p[i]), goto error);
8996 dim += isl_basic_set_n_dim(list->p[i]);
8997 extra += list->p[i]->n_div;
8998 n_eq += list->p[i]->n_eq;
8999 n_ineq += list->p[i]->n_ineq;
9001 product = isl_basic_set_alloc(list->ctx, nparam, dim, extra,
9002 n_eq, n_ineq);
9003 if (!product)
9004 goto error;
9005 dim = 0;
9006 for (i = 0; i < list->n; ++i) {
9007 isl_basic_set_add_constraints(product,
9008 isl_basic_set_copy(list->p[i]), dim);
9009 dim += isl_basic_set_n_dim(list->p[i]);
9011 isl_basic_set_list_free(list);
9012 return product;
9013 error:
9014 isl_basic_set_free(product);
9015 isl_basic_set_list_free(list);
9016 return NULL;
9019 struct isl_basic_map *isl_basic_map_product(
9020 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
9022 isl_space *dim_result = NULL;
9023 struct isl_basic_map *bmap;
9024 unsigned in1, in2, out1, out2, nparam, total, pos;
9025 struct isl_dim_map *dim_map1, *dim_map2;
9027 if (!bmap1 || !bmap2)
9028 goto error;
9030 isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
9031 bmap2->dim, isl_dim_param), goto error);
9032 dim_result = isl_space_product(isl_space_copy(bmap1->dim),
9033 isl_space_copy(bmap2->dim));
9035 in1 = isl_basic_map_n_in(bmap1);
9036 in2 = isl_basic_map_n_in(bmap2);
9037 out1 = isl_basic_map_n_out(bmap1);
9038 out2 = isl_basic_map_n_out(bmap2);
9039 nparam = isl_basic_map_n_param(bmap1);
9041 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9042 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9043 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9044 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9045 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9046 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9047 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9048 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9049 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9050 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9051 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9053 bmap = isl_basic_map_alloc_space(dim_result,
9054 bmap1->n_div + bmap2->n_div,
9055 bmap1->n_eq + bmap2->n_eq,
9056 bmap1->n_ineq + bmap2->n_ineq);
9057 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9058 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9059 bmap = isl_basic_map_simplify(bmap);
9060 return isl_basic_map_finalize(bmap);
9061 error:
9062 isl_basic_map_free(bmap1);
9063 isl_basic_map_free(bmap2);
9064 return NULL;
9067 __isl_give isl_basic_map *isl_basic_map_flat_product(
9068 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9070 isl_basic_map *prod;
9072 prod = isl_basic_map_product(bmap1, bmap2);
9073 prod = isl_basic_map_flatten(prod);
9074 return prod;
9077 __isl_give isl_basic_set *isl_basic_set_flat_product(
9078 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9080 return isl_basic_map_flat_range_product(bset1, bset2);
9083 __isl_give isl_basic_map *isl_basic_map_domain_product(
9084 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9086 isl_space *space_result = NULL;
9087 isl_basic_map *bmap;
9088 unsigned in1, in2, out, nparam, total, pos;
9089 struct isl_dim_map *dim_map1, *dim_map2;
9091 if (!bmap1 || !bmap2)
9092 goto error;
9094 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9095 isl_space_copy(bmap2->dim));
9097 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9098 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9099 out = isl_basic_map_dim(bmap1, isl_dim_out);
9100 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9102 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9103 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9104 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9105 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9106 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9107 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9108 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9109 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9110 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9111 isl_dim_map_div(dim_map1, bmap1, pos += out);
9112 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9114 bmap = isl_basic_map_alloc_space(space_result,
9115 bmap1->n_div + bmap2->n_div,
9116 bmap1->n_eq + bmap2->n_eq,
9117 bmap1->n_ineq + bmap2->n_ineq);
9118 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9119 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9120 bmap = isl_basic_map_simplify(bmap);
9121 return isl_basic_map_finalize(bmap);
9122 error:
9123 isl_basic_map_free(bmap1);
9124 isl_basic_map_free(bmap2);
9125 return NULL;
9128 __isl_give isl_basic_map *isl_basic_map_range_product(
9129 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9131 isl_space *dim_result = NULL;
9132 isl_basic_map *bmap;
9133 unsigned in, out1, out2, nparam, total, pos;
9134 struct isl_dim_map *dim_map1, *dim_map2;
9136 if (!bmap1 || !bmap2)
9137 goto error;
9139 if (!isl_space_match(bmap1->dim, isl_dim_param,
9140 bmap2->dim, isl_dim_param))
9141 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
9142 "parameters don't match", goto error);
9144 dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
9145 isl_space_copy(bmap2->dim));
9147 in = isl_basic_map_dim(bmap1, isl_dim_in);
9148 out1 = isl_basic_map_n_out(bmap1);
9149 out2 = isl_basic_map_n_out(bmap2);
9150 nparam = isl_basic_map_n_param(bmap1);
9152 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
9153 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9154 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9155 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9156 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9157 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9158 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
9159 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
9160 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9161 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9162 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9164 bmap = isl_basic_map_alloc_space(dim_result,
9165 bmap1->n_div + bmap2->n_div,
9166 bmap1->n_eq + bmap2->n_eq,
9167 bmap1->n_ineq + bmap2->n_ineq);
9168 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9169 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9170 bmap = isl_basic_map_simplify(bmap);
9171 return isl_basic_map_finalize(bmap);
9172 error:
9173 isl_basic_map_free(bmap1);
9174 isl_basic_map_free(bmap2);
9175 return NULL;
9178 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
9179 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9181 isl_basic_map *prod;
9183 prod = isl_basic_map_range_product(bmap1, bmap2);
9184 prod = isl_basic_map_flatten_range(prod);
9185 return prod;
9188 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
9189 __isl_take isl_map *map2,
9190 __isl_give isl_space *(*dim_product)(__isl_take isl_space *left,
9191 __isl_take isl_space *right),
9192 __isl_give isl_basic_map *(*basic_map_product)(
9193 __isl_take isl_basic_map *left, __isl_take isl_basic_map *right))
9195 unsigned flags = 0;
9196 struct isl_map *result;
9197 int i, j;
9199 if (!map1 || !map2)
9200 goto error;
9202 isl_assert(map1->ctx, isl_space_match(map1->dim, isl_dim_param,
9203 map2->dim, isl_dim_param), goto error);
9205 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
9206 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
9207 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
9209 result = isl_map_alloc_space(dim_product(isl_space_copy(map1->dim),
9210 isl_space_copy(map2->dim)),
9211 map1->n * map2->n, flags);
9212 if (!result)
9213 goto error;
9214 for (i = 0; i < map1->n; ++i)
9215 for (j = 0; j < map2->n; ++j) {
9216 struct isl_basic_map *part;
9217 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
9218 isl_basic_map_copy(map2->p[j]));
9219 if (isl_basic_map_is_empty(part))
9220 isl_basic_map_free(part);
9221 else
9222 result = isl_map_add_basic_map(result, part);
9223 if (!result)
9224 goto error;
9226 isl_map_free(map1);
9227 isl_map_free(map2);
9228 return result;
9229 error:
9230 isl_map_free(map1);
9231 isl_map_free(map2);
9232 return NULL;
9235 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
9237 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
9238 __isl_take isl_map *map2)
9240 return map_product(map1, map2, &isl_space_product, &isl_basic_map_product);
9243 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
9244 __isl_take isl_map *map2)
9246 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
9249 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
9251 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
9252 __isl_take isl_map *map2)
9254 isl_map *prod;
9256 prod = isl_map_product(map1, map2);
9257 prod = isl_map_flatten(prod);
9258 return prod;
9261 /* Given two set A and B, construct its Cartesian product A x B.
9263 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
9265 return isl_map_range_product(set1, set2);
9268 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
9269 __isl_take isl_set *set2)
9271 return isl_map_flat_range_product(set1, set2);
9274 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
9276 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
9277 __isl_take isl_map *map2)
9279 return map_product(map1, map2, &isl_space_domain_product,
9280 &isl_basic_map_domain_product);
9283 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
9285 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
9286 __isl_take isl_map *map2)
9288 return map_product(map1, map2, &isl_space_range_product,
9289 &isl_basic_map_range_product);
9292 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
9293 __isl_take isl_map *map2)
9295 return isl_map_align_params_map_map_and(map1, map2,
9296 &map_domain_product_aligned);
9299 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
9300 __isl_take isl_map *map2)
9302 return isl_map_align_params_map_map_and(map1, map2,
9303 &map_range_product_aligned);
9306 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
9308 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
9309 __isl_take isl_map *map2)
9311 isl_map *prod;
9313 prod = isl_map_domain_product(map1, map2);
9314 prod = isl_map_flatten_domain(prod);
9315 return prod;
9318 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
9320 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
9321 __isl_take isl_map *map2)
9323 isl_map *prod;
9325 prod = isl_map_range_product(map1, map2);
9326 prod = isl_map_flatten_range(prod);
9327 return prod;
9330 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
9332 int i;
9333 uint32_t hash = isl_hash_init();
9334 unsigned total;
9336 if (!bmap)
9337 return 0;
9338 bmap = isl_basic_map_copy(bmap);
9339 bmap = isl_basic_map_normalize(bmap);
9340 if (!bmap)
9341 return 0;
9342 total = isl_basic_map_total_dim(bmap);
9343 isl_hash_byte(hash, bmap->n_eq & 0xFF);
9344 for (i = 0; i < bmap->n_eq; ++i) {
9345 uint32_t c_hash;
9346 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
9347 isl_hash_hash(hash, c_hash);
9349 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
9350 for (i = 0; i < bmap->n_ineq; ++i) {
9351 uint32_t c_hash;
9352 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
9353 isl_hash_hash(hash, c_hash);
9355 isl_hash_byte(hash, bmap->n_div & 0xFF);
9356 for (i = 0; i < bmap->n_div; ++i) {
9357 uint32_t c_hash;
9358 if (isl_int_is_zero(bmap->div[i][0]))
9359 continue;
9360 isl_hash_byte(hash, i & 0xFF);
9361 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
9362 isl_hash_hash(hash, c_hash);
9364 isl_basic_map_free(bmap);
9365 return hash;
9368 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
9370 return isl_basic_map_get_hash((isl_basic_map *)bset);
9373 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
9375 int i;
9376 uint32_t hash;
9378 if (!map)
9379 return 0;
9380 map = isl_map_copy(map);
9381 map = isl_map_normalize(map);
9382 if (!map)
9383 return 0;
9385 hash = isl_hash_init();
9386 for (i = 0; i < map->n; ++i) {
9387 uint32_t bmap_hash;
9388 bmap_hash = isl_basic_map_get_hash(map->p[i]);
9389 isl_hash_hash(hash, bmap_hash);
9392 isl_map_free(map);
9394 return hash;
9397 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
9399 return isl_map_get_hash((isl_map *)set);
9402 /* Check if the value for dimension dim is completely determined
9403 * by the values of the other parameters and variables.
9404 * That is, check if dimension dim is involved in an equality.
9406 int isl_basic_set_dim_is_unique(struct isl_basic_set *bset, unsigned dim)
9408 int i;
9409 unsigned nparam;
9411 if (!bset)
9412 return -1;
9413 nparam = isl_basic_set_n_param(bset);
9414 for (i = 0; i < bset->n_eq; ++i)
9415 if (!isl_int_is_zero(bset->eq[i][1 + nparam + dim]))
9416 return 1;
9417 return 0;
9420 /* Check if the value for dimension dim is completely determined
9421 * by the values of the other parameters and variables.
9422 * That is, check if dimension dim is involved in an equality
9423 * for each of the subsets.
9425 int isl_set_dim_is_unique(struct isl_set *set, unsigned dim)
9427 int i;
9429 if (!set)
9430 return -1;
9431 for (i = 0; i < set->n; ++i) {
9432 int unique;
9433 unique = isl_basic_set_dim_is_unique(set->p[i], dim);
9434 if (unique != 1)
9435 return unique;
9437 return 1;
9440 int isl_set_n_basic_set(__isl_keep isl_set *set)
9442 return set ? set->n : 0;
9445 int isl_map_foreach_basic_map(__isl_keep isl_map *map,
9446 int (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
9448 int i;
9450 if (!map)
9451 return -1;
9453 for (i = 0; i < map->n; ++i)
9454 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
9455 return -1;
9457 return 0;
9460 int isl_set_foreach_basic_set(__isl_keep isl_set *set,
9461 int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
9463 int i;
9465 if (!set)
9466 return -1;
9468 for (i = 0; i < set->n; ++i)
9469 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
9470 return -1;
9472 return 0;
9475 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
9477 isl_space *dim;
9479 if (!bset)
9480 return NULL;
9482 bset = isl_basic_set_cow(bset);
9483 if (!bset)
9484 return NULL;
9486 dim = isl_basic_set_get_space(bset);
9487 dim = isl_space_lift(dim, bset->n_div);
9488 if (!dim)
9489 goto error;
9490 isl_space_free(bset->dim);
9491 bset->dim = dim;
9492 bset->extra -= bset->n_div;
9493 bset->n_div = 0;
9495 bset = isl_basic_set_finalize(bset);
9497 return bset;
9498 error:
9499 isl_basic_set_free(bset);
9500 return NULL;
9503 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
9505 int i;
9506 isl_space *dim;
9507 unsigned n_div;
9509 set = isl_set_align_divs(set);
9511 if (!set)
9512 return NULL;
9514 set = isl_set_cow(set);
9515 if (!set)
9516 return NULL;
9518 n_div = set->p[0]->n_div;
9519 dim = isl_set_get_space(set);
9520 dim = isl_space_lift(dim, n_div);
9521 if (!dim)
9522 goto error;
9523 isl_space_free(set->dim);
9524 set->dim = dim;
9526 for (i = 0; i < set->n; ++i) {
9527 set->p[i] = isl_basic_set_lift(set->p[i]);
9528 if (!set->p[i])
9529 goto error;
9532 return set;
9533 error:
9534 isl_set_free(set);
9535 return NULL;
9538 __isl_give isl_map *isl_set_lifting(__isl_take isl_set *set)
9540 isl_space *dim;
9541 struct isl_basic_map *bmap;
9542 unsigned n_set;
9543 unsigned n_div;
9544 unsigned n_param;
9545 unsigned total;
9546 int i, k, l;
9548 set = isl_set_align_divs(set);
9550 if (!set)
9551 return NULL;
9553 dim = isl_set_get_space(set);
9554 if (set->n == 0 || set->p[0]->n_div == 0) {
9555 isl_set_free(set);
9556 return isl_map_identity(isl_space_map_from_set(dim));
9559 n_div = set->p[0]->n_div;
9560 dim = isl_space_map_from_set(dim);
9561 n_param = isl_space_dim(dim, isl_dim_param);
9562 n_set = isl_space_dim(dim, isl_dim_in);
9563 dim = isl_space_extend(dim, n_param, n_set, n_set + n_div);
9564 bmap = isl_basic_map_alloc_space(dim, 0, n_set, 2 * n_div);
9565 for (i = 0; i < n_set; ++i)
9566 bmap = var_equal(bmap, i);
9568 total = n_param + n_set + n_set + n_div;
9569 for (i = 0; i < n_div; ++i) {
9570 k = isl_basic_map_alloc_inequality(bmap);
9571 if (k < 0)
9572 goto error;
9573 isl_seq_cpy(bmap->ineq[k], set->p[0]->div[i]+1, 1+n_param);
9574 isl_seq_clr(bmap->ineq[k]+1+n_param, n_set);
9575 isl_seq_cpy(bmap->ineq[k]+1+n_param+n_set,
9576 set->p[0]->div[i]+1+1+n_param, n_set + n_div);
9577 isl_int_neg(bmap->ineq[k][1+n_param+n_set+n_set+i],
9578 set->p[0]->div[i][0]);
9580 l = isl_basic_map_alloc_inequality(bmap);
9581 if (l < 0)
9582 goto error;
9583 isl_seq_neg(bmap->ineq[l], bmap->ineq[k], 1 + total);
9584 isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0],
9585 set->p[0]->div[i][0]);
9586 isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
9589 isl_set_free(set);
9590 bmap = isl_basic_map_simplify(bmap);
9591 bmap = isl_basic_map_finalize(bmap);
9592 return isl_map_from_basic_map(bmap);
9593 error:
9594 isl_set_free(set);
9595 isl_basic_map_free(bmap);
9596 return NULL;
9599 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
9601 unsigned dim;
9602 int size = 0;
9604 if (!bset)
9605 return -1;
9607 dim = isl_basic_set_total_dim(bset);
9608 size += bset->n_eq * (1 + dim);
9609 size += bset->n_ineq * (1 + dim);
9610 size += bset->n_div * (2 + dim);
9612 return size;
9615 int isl_set_size(__isl_keep isl_set *set)
9617 int i;
9618 int size = 0;
9620 if (!set)
9621 return -1;
9623 for (i = 0; i < set->n; ++i)
9624 size += isl_basic_set_size(set->p[i]);
9626 return size;
9629 /* Check if there is any lower bound (if lower == 0) and/or upper
9630 * bound (if upper == 0) on the specified dim.
9632 static int basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
9633 enum isl_dim_type type, unsigned pos, int lower, int upper)
9635 int i;
9637 if (!bmap)
9638 return -1;
9640 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), return -1);
9642 pos += isl_basic_map_offset(bmap, type);
9644 for (i = 0; i < bmap->n_div; ++i) {
9645 if (isl_int_is_zero(bmap->div[i][0]))
9646 continue;
9647 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
9648 return 1;
9651 for (i = 0; i < bmap->n_eq; ++i)
9652 if (!isl_int_is_zero(bmap->eq[i][pos]))
9653 return 1;
9655 for (i = 0; i < bmap->n_ineq; ++i) {
9656 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
9657 if (sgn > 0)
9658 lower = 1;
9659 if (sgn < 0)
9660 upper = 1;
9663 return lower && upper;
9666 int isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
9667 enum isl_dim_type type, unsigned pos)
9669 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
9672 int isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
9673 enum isl_dim_type type, unsigned pos)
9675 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
9678 int isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
9679 enum isl_dim_type type, unsigned pos)
9681 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
9684 int isl_map_dim_is_bounded(__isl_keep isl_map *map,
9685 enum isl_dim_type type, unsigned pos)
9687 int i;
9689 if (!map)
9690 return -1;
9692 for (i = 0; i < map->n; ++i) {
9693 int bounded;
9694 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
9695 if (bounded < 0 || !bounded)
9696 return bounded;
9699 return 1;
9702 /* Return 1 if the specified dim is involved in both an upper bound
9703 * and a lower bound.
9705 int isl_set_dim_is_bounded(__isl_keep isl_set *set,
9706 enum isl_dim_type type, unsigned pos)
9708 return isl_map_dim_is_bounded((isl_map *)set, type, pos);
9711 /* Does "map" have a bound (according to "fn") for any of its basic maps?
9713 static int has_any_bound(__isl_keep isl_map *map,
9714 enum isl_dim_type type, unsigned pos,
9715 int (*fn)(__isl_keep isl_basic_map *bmap,
9716 enum isl_dim_type type, unsigned pos))
9718 int i;
9720 if (!map)
9721 return -1;
9723 for (i = 0; i < map->n; ++i) {
9724 int bounded;
9725 bounded = fn(map->p[i], type, pos);
9726 if (bounded < 0 || bounded)
9727 return bounded;
9730 return 0;
9733 /* Return 1 if the specified dim is involved in any lower bound.
9735 int isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
9736 enum isl_dim_type type, unsigned pos)
9738 return has_any_bound(set, type, pos,
9739 &isl_basic_map_dim_has_lower_bound);
9742 /* Return 1 if the specified dim is involved in any upper bound.
9744 int isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
9745 enum isl_dim_type type, unsigned pos)
9747 return has_any_bound(set, type, pos,
9748 &isl_basic_map_dim_has_upper_bound);
9751 /* Does "map" have a bound (according to "fn") for all of its basic maps?
9753 static int has_bound(__isl_keep isl_map *map,
9754 enum isl_dim_type type, unsigned pos,
9755 int (*fn)(__isl_keep isl_basic_map *bmap,
9756 enum isl_dim_type type, unsigned pos))
9758 int i;
9760 if (!map)
9761 return -1;
9763 for (i = 0; i < map->n; ++i) {
9764 int bounded;
9765 bounded = fn(map->p[i], type, pos);
9766 if (bounded < 0 || !bounded)
9767 return bounded;
9770 return 1;
9773 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
9775 int isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
9776 enum isl_dim_type type, unsigned pos)
9778 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
9781 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
9783 int isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
9784 enum isl_dim_type type, unsigned pos)
9786 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
9789 /* For each of the "n" variables starting at "first", determine
9790 * the sign of the variable and put the results in the first "n"
9791 * elements of the array "signs".
9792 * Sign
9793 * 1 means that the variable is non-negative
9794 * -1 means that the variable is non-positive
9795 * 0 means the variable attains both positive and negative values.
9797 int isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
9798 unsigned first, unsigned n, int *signs)
9800 isl_vec *bound = NULL;
9801 struct isl_tab *tab = NULL;
9802 struct isl_tab_undo *snap;
9803 int i;
9805 if (!bset || !signs)
9806 return -1;
9808 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
9809 tab = isl_tab_from_basic_set(bset, 0);
9810 if (!bound || !tab)
9811 goto error;
9813 isl_seq_clr(bound->el, bound->size);
9814 isl_int_set_si(bound->el[0], -1);
9816 snap = isl_tab_snap(tab);
9817 for (i = 0; i < n; ++i) {
9818 int empty;
9820 isl_int_set_si(bound->el[1 + first + i], -1);
9821 if (isl_tab_add_ineq(tab, bound->el) < 0)
9822 goto error;
9823 empty = tab->empty;
9824 isl_int_set_si(bound->el[1 + first + i], 0);
9825 if (isl_tab_rollback(tab, snap) < 0)
9826 goto error;
9828 if (empty) {
9829 signs[i] = 1;
9830 continue;
9833 isl_int_set_si(bound->el[1 + first + i], 1);
9834 if (isl_tab_add_ineq(tab, bound->el) < 0)
9835 goto error;
9836 empty = tab->empty;
9837 isl_int_set_si(bound->el[1 + first + i], 0);
9838 if (isl_tab_rollback(tab, snap) < 0)
9839 goto error;
9841 signs[i] = empty ? -1 : 0;
9844 isl_tab_free(tab);
9845 isl_vec_free(bound);
9846 return 0;
9847 error:
9848 isl_tab_free(tab);
9849 isl_vec_free(bound);
9850 return -1;
9853 int isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
9854 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
9856 if (!bset || !signs)
9857 return -1;
9858 isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
9859 return -1);
9861 first += pos(bset->dim, type) - 1;
9862 return isl_basic_set_vars_get_sign(bset, first, n, signs);
9865 /* Check if the given basic map is obviously single-valued.
9866 * In particular, for each output dimension, check that there is
9867 * an equality that defines the output dimension in terms of
9868 * earlier dimensions.
9870 int isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
9872 int i, j;
9873 unsigned total;
9874 unsigned n_out;
9875 unsigned o_out;
9877 if (!bmap)
9878 return -1;
9880 total = 1 + isl_basic_map_total_dim(bmap);
9881 n_out = isl_basic_map_dim(bmap, isl_dim_out);
9882 o_out = isl_basic_map_offset(bmap, isl_dim_out);
9884 for (i = 0; i < n_out; ++i) {
9885 for (j = 0; j < bmap->n_eq; ++j) {
9886 if (isl_int_is_zero(bmap->eq[j][o_out + i]))
9887 continue;
9888 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + i + 1,
9889 total - (o_out + i + 1)) == -1)
9890 break;
9892 if (j >= bmap->n_eq)
9893 return 0;
9896 return 1;
9899 /* Check if the given basic map is single-valued.
9900 * We simply compute
9902 * M \circ M^-1
9904 * and check if the result is a subset of the identity mapping.
9906 int isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
9908 isl_space *space;
9909 isl_basic_map *test;
9910 isl_basic_map *id;
9911 int sv;
9913 sv = isl_basic_map_plain_is_single_valued(bmap);
9914 if (sv < 0 || sv)
9915 return sv;
9917 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
9918 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
9920 space = isl_basic_map_get_space(bmap);
9921 space = isl_space_map_from_set(isl_space_range(space));
9922 id = isl_basic_map_identity(space);
9924 sv = isl_basic_map_is_subset(test, id);
9926 isl_basic_map_free(test);
9927 isl_basic_map_free(id);
9929 return sv;
9932 /* Check if the given map is obviously single-valued.
9934 int isl_map_plain_is_single_valued(__isl_keep isl_map *map)
9936 if (!map)
9937 return -1;
9938 if (map->n == 0)
9939 return 1;
9940 if (map->n >= 2)
9941 return 0;
9943 return isl_basic_map_plain_is_single_valued(map->p[0]);
9946 /* Check if the given map is single-valued.
9947 * We simply compute
9949 * M \circ M^-1
9951 * and check if the result is a subset of the identity mapping.
9953 int isl_map_is_single_valued(__isl_keep isl_map *map)
9955 isl_space *dim;
9956 isl_map *test;
9957 isl_map *id;
9958 int sv;
9960 sv = isl_map_plain_is_single_valued(map);
9961 if (sv < 0 || sv)
9962 return sv;
9964 test = isl_map_reverse(isl_map_copy(map));
9965 test = isl_map_apply_range(test, isl_map_copy(map));
9967 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
9968 id = isl_map_identity(dim);
9970 sv = isl_map_is_subset(test, id);
9972 isl_map_free(test);
9973 isl_map_free(id);
9975 return sv;
9978 int isl_map_is_injective(__isl_keep isl_map *map)
9980 int in;
9982 map = isl_map_copy(map);
9983 map = isl_map_reverse(map);
9984 in = isl_map_is_single_valued(map);
9985 isl_map_free(map);
9987 return in;
9990 /* Check if the given map is obviously injective.
9992 int isl_map_plain_is_injective(__isl_keep isl_map *map)
9994 int in;
9996 map = isl_map_copy(map);
9997 map = isl_map_reverse(map);
9998 in = isl_map_plain_is_single_valued(map);
9999 isl_map_free(map);
10001 return in;
10004 int isl_map_is_bijective(__isl_keep isl_map *map)
10006 int sv;
10008 sv = isl_map_is_single_valued(map);
10009 if (sv < 0 || !sv)
10010 return sv;
10012 return isl_map_is_injective(map);
10015 int isl_set_is_singleton(__isl_keep isl_set *set)
10017 return isl_map_is_single_valued((isl_map *)set);
10020 int isl_map_is_translation(__isl_keep isl_map *map)
10022 int ok;
10023 isl_set *delta;
10025 delta = isl_map_deltas(isl_map_copy(map));
10026 ok = isl_set_is_singleton(delta);
10027 isl_set_free(delta);
10029 return ok;
10032 static int unique(isl_int *p, unsigned pos, unsigned len)
10034 if (isl_seq_first_non_zero(p, pos) != -1)
10035 return 0;
10036 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
10037 return 0;
10038 return 1;
10041 int isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
10043 int i, j;
10044 unsigned nvar;
10045 unsigned ovar;
10047 if (!bset)
10048 return -1;
10050 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
10051 return 0;
10053 nvar = isl_basic_set_dim(bset, isl_dim_set);
10054 ovar = isl_space_offset(bset->dim, isl_dim_set);
10055 for (j = 0; j < nvar; ++j) {
10056 int lower = 0, upper = 0;
10057 for (i = 0; i < bset->n_eq; ++i) {
10058 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
10059 continue;
10060 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
10061 return 0;
10062 break;
10064 if (i < bset->n_eq)
10065 continue;
10066 for (i = 0; i < bset->n_ineq; ++i) {
10067 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
10068 continue;
10069 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
10070 return 0;
10071 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
10072 lower = 1;
10073 else
10074 upper = 1;
10076 if (!lower || !upper)
10077 return 0;
10080 return 1;
10083 int isl_set_is_box(__isl_keep isl_set *set)
10085 if (!set)
10086 return -1;
10087 if (set->n != 1)
10088 return 0;
10090 return isl_basic_set_is_box(set->p[0]);
10093 int isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
10095 if (!bset)
10096 return -1;
10098 return isl_space_is_wrapping(bset->dim);
10101 int isl_set_is_wrapping(__isl_keep isl_set *set)
10103 if (!set)
10104 return -1;
10106 return isl_space_is_wrapping(set->dim);
10109 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
10111 bmap = isl_basic_map_cow(bmap);
10112 if (!bmap)
10113 return NULL;
10115 bmap->dim = isl_space_wrap(bmap->dim);
10116 if (!bmap->dim)
10117 goto error;
10119 bmap = isl_basic_map_finalize(bmap);
10121 return (isl_basic_set *)bmap;
10122 error:
10123 isl_basic_map_free(bmap);
10124 return NULL;
10127 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
10129 int i;
10131 map = isl_map_cow(map);
10132 if (!map)
10133 return NULL;
10135 for (i = 0; i < map->n; ++i) {
10136 map->p[i] = (isl_basic_map *)isl_basic_map_wrap(map->p[i]);
10137 if (!map->p[i])
10138 goto error;
10140 map->dim = isl_space_wrap(map->dim);
10141 if (!map->dim)
10142 goto error;
10144 return (isl_set *)map;
10145 error:
10146 isl_map_free(map);
10147 return NULL;
10150 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
10152 bset = isl_basic_set_cow(bset);
10153 if (!bset)
10154 return NULL;
10156 bset->dim = isl_space_unwrap(bset->dim);
10157 if (!bset->dim)
10158 goto error;
10160 bset = isl_basic_set_finalize(bset);
10162 return (isl_basic_map *)bset;
10163 error:
10164 isl_basic_set_free(bset);
10165 return NULL;
10168 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
10170 int i;
10172 if (!set)
10173 return NULL;
10175 if (!isl_set_is_wrapping(set))
10176 isl_die(set->ctx, isl_error_invalid, "not a wrapping set",
10177 goto error);
10179 set = isl_set_cow(set);
10180 if (!set)
10181 return NULL;
10183 for (i = 0; i < set->n; ++i) {
10184 set->p[i] = (isl_basic_set *)isl_basic_set_unwrap(set->p[i]);
10185 if (!set->p[i])
10186 goto error;
10189 set->dim = isl_space_unwrap(set->dim);
10190 if (!set->dim)
10191 goto error;
10193 return (isl_map *)set;
10194 error:
10195 isl_set_free(set);
10196 return NULL;
10199 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
10200 enum isl_dim_type type)
10202 if (!bmap)
10203 return NULL;
10205 if (!isl_space_is_named_or_nested(bmap->dim, type))
10206 return bmap;
10208 bmap = isl_basic_map_cow(bmap);
10209 if (!bmap)
10210 return NULL;
10212 bmap->dim = isl_space_reset(bmap->dim, type);
10213 if (!bmap->dim)
10214 goto error;
10216 bmap = isl_basic_map_finalize(bmap);
10218 return bmap;
10219 error:
10220 isl_basic_map_free(bmap);
10221 return NULL;
10224 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
10225 enum isl_dim_type type)
10227 int i;
10229 if (!map)
10230 return NULL;
10232 if (!isl_space_is_named_or_nested(map->dim, type))
10233 return map;
10235 map = isl_map_cow(map);
10236 if (!map)
10237 return NULL;
10239 for (i = 0; i < map->n; ++i) {
10240 map->p[i] = isl_basic_map_reset(map->p[i], type);
10241 if (!map->p[i])
10242 goto error;
10244 map->dim = isl_space_reset(map->dim, type);
10245 if (!map->dim)
10246 goto error;
10248 return map;
10249 error:
10250 isl_map_free(map);
10251 return NULL;
10254 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
10256 if (!bmap)
10257 return NULL;
10259 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
10260 return bmap;
10262 bmap = isl_basic_map_cow(bmap);
10263 if (!bmap)
10264 return NULL;
10266 bmap->dim = isl_space_flatten(bmap->dim);
10267 if (!bmap->dim)
10268 goto error;
10270 bmap = isl_basic_map_finalize(bmap);
10272 return bmap;
10273 error:
10274 isl_basic_map_free(bmap);
10275 return NULL;
10278 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
10280 return (isl_basic_set *)isl_basic_map_flatten((isl_basic_map *)bset);
10283 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
10284 __isl_take isl_basic_map *bmap)
10286 if (!bmap)
10287 return NULL;
10289 if (!bmap->dim->nested[0])
10290 return bmap;
10292 bmap = isl_basic_map_cow(bmap);
10293 if (!bmap)
10294 return NULL;
10296 bmap->dim = isl_space_flatten_domain(bmap->dim);
10297 if (!bmap->dim)
10298 goto error;
10300 bmap = isl_basic_map_finalize(bmap);
10302 return bmap;
10303 error:
10304 isl_basic_map_free(bmap);
10305 return NULL;
10308 __isl_give isl_basic_map *isl_basic_map_flatten_range(
10309 __isl_take isl_basic_map *bmap)
10311 if (!bmap)
10312 return NULL;
10314 if (!bmap->dim->nested[1])
10315 return bmap;
10317 bmap = isl_basic_map_cow(bmap);
10318 if (!bmap)
10319 return NULL;
10321 bmap->dim = isl_space_flatten_range(bmap->dim);
10322 if (!bmap->dim)
10323 goto error;
10325 bmap = isl_basic_map_finalize(bmap);
10327 return bmap;
10328 error:
10329 isl_basic_map_free(bmap);
10330 return NULL;
10333 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
10335 int i;
10337 if (!map)
10338 return NULL;
10340 if (!map->dim->nested[0] && !map->dim->nested[1])
10341 return map;
10343 map = isl_map_cow(map);
10344 if (!map)
10345 return NULL;
10347 for (i = 0; i < map->n; ++i) {
10348 map->p[i] = isl_basic_map_flatten(map->p[i]);
10349 if (!map->p[i])
10350 goto error;
10352 map->dim = isl_space_flatten(map->dim);
10353 if (!map->dim)
10354 goto error;
10356 return map;
10357 error:
10358 isl_map_free(map);
10359 return NULL;
10362 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
10364 return (isl_set *)isl_map_flatten((isl_map *)set);
10367 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
10369 isl_space *dim, *flat_dim;
10370 isl_map *map;
10372 dim = isl_set_get_space(set);
10373 flat_dim = isl_space_flatten(isl_space_copy(dim));
10374 map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
10375 map = isl_map_intersect_domain(map, set);
10377 return map;
10380 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
10382 int i;
10384 if (!map)
10385 return NULL;
10387 if (!map->dim->nested[0])
10388 return map;
10390 map = isl_map_cow(map);
10391 if (!map)
10392 return NULL;
10394 for (i = 0; i < map->n; ++i) {
10395 map->p[i] = isl_basic_map_flatten_domain(map->p[i]);
10396 if (!map->p[i])
10397 goto error;
10399 map->dim = isl_space_flatten_domain(map->dim);
10400 if (!map->dim)
10401 goto error;
10403 return map;
10404 error:
10405 isl_map_free(map);
10406 return NULL;
10409 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
10411 int i;
10413 if (!map)
10414 return NULL;
10416 if (!map->dim->nested[1])
10417 return map;
10419 map = isl_map_cow(map);
10420 if (!map)
10421 return NULL;
10423 for (i = 0; i < map->n; ++i) {
10424 map->p[i] = isl_basic_map_flatten_range(map->p[i]);
10425 if (!map->p[i])
10426 goto error;
10428 map->dim = isl_space_flatten_range(map->dim);
10429 if (!map->dim)
10430 goto error;
10432 return map;
10433 error:
10434 isl_map_free(map);
10435 return NULL;
10438 /* Reorder the dimensions of "bmap" according to the given dim_map
10439 * and set the dimension specification to "dim".
10441 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
10442 __isl_take isl_space *dim, __isl_take struct isl_dim_map *dim_map)
10444 isl_basic_map *res;
10445 unsigned flags;
10447 bmap = isl_basic_map_cow(bmap);
10448 if (!bmap || !dim || !dim_map)
10449 goto error;
10451 flags = bmap->flags;
10452 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
10453 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
10454 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
10455 res = isl_basic_map_alloc_space(dim,
10456 bmap->n_div, bmap->n_eq, bmap->n_ineq);
10457 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
10458 if (res)
10459 res->flags = flags;
10460 res = isl_basic_map_finalize(res);
10461 return res;
10462 error:
10463 free(dim_map);
10464 isl_basic_map_free(bmap);
10465 isl_space_free(dim);
10466 return NULL;
10469 /* Reorder the dimensions of "map" according to given reordering.
10471 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
10472 __isl_take isl_reordering *r)
10474 int i;
10475 struct isl_dim_map *dim_map;
10477 map = isl_map_cow(map);
10478 dim_map = isl_dim_map_from_reordering(r);
10479 if (!map || !r || !dim_map)
10480 goto error;
10482 for (i = 0; i < map->n; ++i) {
10483 struct isl_dim_map *dim_map_i;
10485 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
10487 map->p[i] = isl_basic_map_realign(map->p[i],
10488 isl_space_copy(r->dim), dim_map_i);
10490 if (!map->p[i])
10491 goto error;
10494 map = isl_map_reset_space(map, isl_space_copy(r->dim));
10496 isl_reordering_free(r);
10497 free(dim_map);
10498 return map;
10499 error:
10500 free(dim_map);
10501 isl_map_free(map);
10502 isl_reordering_free(r);
10503 return NULL;
10506 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
10507 __isl_take isl_reordering *r)
10509 return (isl_set *)isl_map_realign((isl_map *)set, r);
10512 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
10513 __isl_take isl_space *model)
10515 isl_ctx *ctx;
10517 if (!map || !model)
10518 goto error;
10520 ctx = isl_space_get_ctx(model);
10521 if (!isl_space_has_named_params(model))
10522 isl_die(ctx, isl_error_invalid,
10523 "model has unnamed parameters", goto error);
10524 if (!isl_space_has_named_params(map->dim))
10525 isl_die(ctx, isl_error_invalid,
10526 "relation has unnamed parameters", goto error);
10527 if (!isl_space_match(map->dim, isl_dim_param, model, isl_dim_param)) {
10528 isl_reordering *exp;
10530 model = isl_space_drop_dims(model, isl_dim_in,
10531 0, isl_space_dim(model, isl_dim_in));
10532 model = isl_space_drop_dims(model, isl_dim_out,
10533 0, isl_space_dim(model, isl_dim_out));
10534 exp = isl_parameter_alignment_reordering(map->dim, model);
10535 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
10536 map = isl_map_realign(map, exp);
10539 isl_space_free(model);
10540 return map;
10541 error:
10542 isl_space_free(model);
10543 isl_map_free(map);
10544 return NULL;
10547 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
10548 __isl_take isl_space *model)
10550 return isl_map_align_params(set, model);
10553 /* Align the parameters of "bmap" to those of "model", introducing
10554 * additional parameters if needed.
10556 __isl_give isl_basic_map *isl_basic_map_align_params(
10557 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
10559 isl_ctx *ctx;
10561 if (!bmap || !model)
10562 goto error;
10564 ctx = isl_space_get_ctx(model);
10565 if (!isl_space_has_named_params(model))
10566 isl_die(ctx, isl_error_invalid,
10567 "model has unnamed parameters", goto error);
10568 if (!isl_space_has_named_params(bmap->dim))
10569 isl_die(ctx, isl_error_invalid,
10570 "relation has unnamed parameters", goto error);
10571 if (!isl_space_match(bmap->dim, isl_dim_param, model, isl_dim_param)) {
10572 isl_reordering *exp;
10573 struct isl_dim_map *dim_map;
10575 model = isl_space_drop_dims(model, isl_dim_in,
10576 0, isl_space_dim(model, isl_dim_in));
10577 model = isl_space_drop_dims(model, isl_dim_out,
10578 0, isl_space_dim(model, isl_dim_out));
10579 exp = isl_parameter_alignment_reordering(bmap->dim, model);
10580 exp = isl_reordering_extend_space(exp,
10581 isl_basic_map_get_space(bmap));
10582 dim_map = isl_dim_map_from_reordering(exp);
10583 bmap = isl_basic_map_realign(bmap,
10584 exp ? isl_space_copy(exp->dim) : NULL,
10585 isl_dim_map_extend(dim_map, bmap));
10586 isl_reordering_free(exp);
10587 free(dim_map);
10590 isl_space_free(model);
10591 return bmap;
10592 error:
10593 isl_space_free(model);
10594 isl_basic_map_free(bmap);
10595 return NULL;
10598 /* Align the parameters of "bset" to those of "model", introducing
10599 * additional parameters if needed.
10601 __isl_give isl_basic_set *isl_basic_set_align_params(
10602 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
10604 return isl_basic_map_align_params(bset, model);
10607 __isl_give isl_mat *isl_basic_map_equalities_matrix(
10608 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
10609 enum isl_dim_type c2, enum isl_dim_type c3,
10610 enum isl_dim_type c4, enum isl_dim_type c5)
10612 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
10613 struct isl_mat *mat;
10614 int i, j, k;
10615 int pos;
10617 if (!bmap)
10618 return NULL;
10619 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
10620 isl_basic_map_total_dim(bmap) + 1);
10621 if (!mat)
10622 return NULL;
10623 for (i = 0; i < bmap->n_eq; ++i)
10624 for (j = 0, pos = 0; j < 5; ++j) {
10625 int off = isl_basic_map_offset(bmap, c[j]);
10626 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
10627 isl_int_set(mat->row[i][pos],
10628 bmap->eq[i][off + k]);
10629 ++pos;
10633 return mat;
10636 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
10637 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
10638 enum isl_dim_type c2, enum isl_dim_type c3,
10639 enum isl_dim_type c4, enum isl_dim_type c5)
10641 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
10642 struct isl_mat *mat;
10643 int i, j, k;
10644 int pos;
10646 if (!bmap)
10647 return NULL;
10648 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
10649 isl_basic_map_total_dim(bmap) + 1);
10650 if (!mat)
10651 return NULL;
10652 for (i = 0; i < bmap->n_ineq; ++i)
10653 for (j = 0, pos = 0; j < 5; ++j) {
10654 int off = isl_basic_map_offset(bmap, c[j]);
10655 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
10656 isl_int_set(mat->row[i][pos],
10657 bmap->ineq[i][off + k]);
10658 ++pos;
10662 return mat;
10665 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
10666 __isl_take isl_space *dim,
10667 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
10668 enum isl_dim_type c2, enum isl_dim_type c3,
10669 enum isl_dim_type c4, enum isl_dim_type c5)
10671 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
10672 isl_basic_map *bmap;
10673 unsigned total;
10674 unsigned extra;
10675 int i, j, k, l;
10676 int pos;
10678 if (!dim || !eq || !ineq)
10679 goto error;
10681 if (eq->n_col != ineq->n_col)
10682 isl_die(dim->ctx, isl_error_invalid,
10683 "equalities and inequalities matrices should have "
10684 "same number of columns", goto error);
10686 total = 1 + isl_space_dim(dim, isl_dim_all);
10688 if (eq->n_col < total)
10689 isl_die(dim->ctx, isl_error_invalid,
10690 "number of columns too small", goto error);
10692 extra = eq->n_col - total;
10694 bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
10695 eq->n_row, ineq->n_row);
10696 if (!bmap)
10697 goto error;
10698 for (i = 0; i < extra; ++i) {
10699 k = isl_basic_map_alloc_div(bmap);
10700 if (k < 0)
10701 goto error;
10702 isl_int_set_si(bmap->div[k][0], 0);
10704 for (i = 0; i < eq->n_row; ++i) {
10705 l = isl_basic_map_alloc_equality(bmap);
10706 if (l < 0)
10707 goto error;
10708 for (j = 0, pos = 0; j < 5; ++j) {
10709 int off = isl_basic_map_offset(bmap, c[j]);
10710 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
10711 isl_int_set(bmap->eq[l][off + k],
10712 eq->row[i][pos]);
10713 ++pos;
10717 for (i = 0; i < ineq->n_row; ++i) {
10718 l = isl_basic_map_alloc_inequality(bmap);
10719 if (l < 0)
10720 goto error;
10721 for (j = 0, pos = 0; j < 5; ++j) {
10722 int off = isl_basic_map_offset(bmap, c[j]);
10723 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
10724 isl_int_set(bmap->ineq[l][off + k],
10725 ineq->row[i][pos]);
10726 ++pos;
10731 isl_space_free(dim);
10732 isl_mat_free(eq);
10733 isl_mat_free(ineq);
10735 bmap = isl_basic_map_simplify(bmap);
10736 return isl_basic_map_finalize(bmap);
10737 error:
10738 isl_space_free(dim);
10739 isl_mat_free(eq);
10740 isl_mat_free(ineq);
10741 return NULL;
10744 __isl_give isl_mat *isl_basic_set_equalities_matrix(
10745 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
10746 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
10748 return isl_basic_map_equalities_matrix((isl_basic_map *)bset,
10749 c1, c2, c3, c4, isl_dim_in);
10752 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
10753 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
10754 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
10756 return isl_basic_map_inequalities_matrix((isl_basic_map *)bset,
10757 c1, c2, c3, c4, isl_dim_in);
10760 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
10761 __isl_take isl_space *dim,
10762 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
10763 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
10765 return (isl_basic_set*)
10766 isl_basic_map_from_constraint_matrices(dim, eq, ineq,
10767 c1, c2, c3, c4, isl_dim_in);
10770 int isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
10772 if (!bmap)
10773 return -1;
10775 return isl_space_can_zip(bmap->dim);
10778 int isl_map_can_zip(__isl_keep isl_map *map)
10780 if (!map)
10781 return -1;
10783 return isl_space_can_zip(map->dim);
10786 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
10787 * (A -> C) -> (B -> D).
10789 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
10791 unsigned pos;
10792 unsigned n1;
10793 unsigned n2;
10795 if (!bmap)
10796 return NULL;
10798 if (!isl_basic_map_can_zip(bmap))
10799 isl_die(bmap->ctx, isl_error_invalid,
10800 "basic map cannot be zipped", goto error);
10801 pos = isl_basic_map_offset(bmap, isl_dim_in) +
10802 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
10803 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
10804 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
10805 bmap = isl_basic_map_cow(bmap);
10806 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
10807 if (!bmap)
10808 return NULL;
10809 bmap->dim = isl_space_zip(bmap->dim);
10810 if (!bmap->dim)
10811 goto error;
10812 return bmap;
10813 error:
10814 isl_basic_map_free(bmap);
10815 return NULL;
10818 /* Given a map (A -> B) -> (C -> D), return the corresponding map
10819 * (A -> C) -> (B -> D).
10821 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
10823 int i;
10825 if (!map)
10826 return NULL;
10828 if (!isl_map_can_zip(map))
10829 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
10830 goto error);
10832 map = isl_map_cow(map);
10833 if (!map)
10834 return NULL;
10836 for (i = 0; i < map->n; ++i) {
10837 map->p[i] = isl_basic_map_zip(map->p[i]);
10838 if (!map->p[i])
10839 goto error;
10842 map->dim = isl_space_zip(map->dim);
10843 if (!map->dim)
10844 goto error;
10846 return map;
10847 error:
10848 isl_map_free(map);
10849 return NULL;
10852 /* Can we apply isl_basic_map_curry to "bmap"?
10853 * That is, does it have a nested relation in its domain?
10855 int isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
10857 if (!bmap)
10858 return -1;
10860 return isl_space_can_curry(bmap->dim);
10863 /* Can we apply isl_map_curry to "map"?
10864 * That is, does it have a nested relation in its domain?
10866 int isl_map_can_curry(__isl_keep isl_map *map)
10868 if (!map)
10869 return -1;
10871 return isl_space_can_curry(map->dim);
10874 /* Given a basic map (A -> B) -> C, return the corresponding basic map
10875 * A -> (B -> C).
10877 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
10880 if (!bmap)
10881 return NULL;
10883 if (!isl_basic_map_can_curry(bmap))
10884 isl_die(bmap->ctx, isl_error_invalid,
10885 "basic map cannot be curried", goto error);
10886 bmap = isl_basic_map_cow(bmap);
10887 if (!bmap)
10888 return NULL;
10889 bmap->dim = isl_space_curry(bmap->dim);
10890 if (!bmap->dim)
10891 goto error;
10892 return bmap;
10893 error:
10894 isl_basic_map_free(bmap);
10895 return NULL;
10898 /* Given a map (A -> B) -> C, return the corresponding map
10899 * A -> (B -> C).
10901 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
10903 int i;
10905 if (!map)
10906 return NULL;
10908 if (!isl_map_can_curry(map))
10909 isl_die(map->ctx, isl_error_invalid, "map cannot be curried",
10910 goto error);
10912 map = isl_map_cow(map);
10913 if (!map)
10914 return NULL;
10916 for (i = 0; i < map->n; ++i) {
10917 map->p[i] = isl_basic_map_curry(map->p[i]);
10918 if (!map->p[i])
10919 goto error;
10922 map->dim = isl_space_curry(map->dim);
10923 if (!map->dim)
10924 goto error;
10926 return map;
10927 error:
10928 isl_map_free(map);
10929 return NULL;
10932 /* Can we apply isl_basic_map_uncurry to "bmap"?
10933 * That is, does it have a nested relation in its domain?
10935 int isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
10937 if (!bmap)
10938 return -1;
10940 return isl_space_can_uncurry(bmap->dim);
10943 /* Can we apply isl_map_uncurry to "map"?
10944 * That is, does it have a nested relation in its domain?
10946 int isl_map_can_uncurry(__isl_keep isl_map *map)
10948 if (!map)
10949 return -1;
10951 return isl_space_can_uncurry(map->dim);
10954 /* Given a basic map A -> (B -> C), return the corresponding basic map
10955 * (A -> B) -> C.
10957 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
10960 if (!bmap)
10961 return NULL;
10963 if (!isl_basic_map_can_uncurry(bmap))
10964 isl_die(bmap->ctx, isl_error_invalid,
10965 "basic map cannot be uncurried",
10966 return isl_basic_map_free(bmap));
10967 bmap = isl_basic_map_cow(bmap);
10968 if (!bmap)
10969 return NULL;
10970 bmap->dim = isl_space_uncurry(bmap->dim);
10971 if (!bmap->dim)
10972 return isl_basic_map_free(bmap);
10973 return bmap;
10976 /* Given a map A -> (B -> C), return the corresponding map
10977 * (A -> B) -> C.
10979 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
10981 int i;
10983 if (!map)
10984 return NULL;
10986 if (!isl_map_can_uncurry(map))
10987 isl_die(map->ctx, isl_error_invalid, "map cannot be uncurried",
10988 return isl_map_free(map));
10990 map = isl_map_cow(map);
10991 if (!map)
10992 return NULL;
10994 for (i = 0; i < map->n; ++i) {
10995 map->p[i] = isl_basic_map_uncurry(map->p[i]);
10996 if (!map->p[i])
10997 return isl_map_free(map);
11000 map->dim = isl_space_uncurry(map->dim);
11001 if (!map->dim)
11002 return isl_map_free(map);
11004 return map;
11007 /* Construct a basic map mapping the domain of the affine expression
11008 * to a one-dimensional range prescribed by the affine expression.
11010 __isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff)
11012 int k;
11013 int pos;
11014 isl_local_space *ls;
11015 isl_basic_map *bmap;
11017 if (!aff)
11018 return NULL;
11020 ls = isl_aff_get_local_space(aff);
11021 bmap = isl_basic_map_from_local_space(ls);
11022 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
11023 k = isl_basic_map_alloc_equality(bmap);
11024 if (k < 0)
11025 goto error;
11027 pos = isl_basic_map_offset(bmap, isl_dim_out);
11028 isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos);
11029 isl_int_neg(bmap->eq[k][pos], aff->v->el[0]);
11030 isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos,
11031 aff->v->size - (pos + 1));
11033 isl_aff_free(aff);
11034 bmap = isl_basic_map_finalize(bmap);
11035 return bmap;
11036 error:
11037 isl_aff_free(aff);
11038 isl_basic_map_free(bmap);
11039 return NULL;
11042 /* Construct a map mapping the domain of the affine expression
11043 * to a one-dimensional range prescribed by the affine expression.
11045 __isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff)
11047 isl_basic_map *bmap;
11049 bmap = isl_basic_map_from_aff(aff);
11050 return isl_map_from_basic_map(bmap);
11053 /* Construct a basic map mapping the domain the multi-affine expression
11054 * to its range, with each dimension in the range equated to the
11055 * corresponding affine expression.
11057 __isl_give isl_basic_map *isl_basic_map_from_multi_aff(
11058 __isl_take isl_multi_aff *maff)
11060 int i;
11061 isl_space *space;
11062 isl_basic_map *bmap;
11064 if (!maff)
11065 return NULL;
11067 if (isl_space_dim(maff->space, isl_dim_out) != maff->n)
11068 isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal,
11069 "invalid space", return isl_multi_aff_free(maff));
11071 space = isl_space_domain(isl_multi_aff_get_space(maff));
11072 bmap = isl_basic_map_universe(isl_space_from_domain(space));
11074 for (i = 0; i < maff->n; ++i) {
11075 isl_aff *aff;
11076 isl_basic_map *bmap_i;
11078 aff = isl_aff_copy(maff->p[i]);
11079 bmap_i = isl_basic_map_from_aff(aff);
11081 bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11084 bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff));
11086 isl_multi_aff_free(maff);
11087 return bmap;
11090 /* Construct a map mapping the domain the multi-affine expression
11091 * to its range, with each dimension in the range equated to the
11092 * corresponding affine expression.
11094 __isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff)
11096 isl_basic_map *bmap;
11098 bmap = isl_basic_map_from_multi_aff(maff);
11099 return isl_map_from_basic_map(bmap);
11102 /* Construct a basic map mapping a domain in the given space to
11103 * to an n-dimensional range, with n the number of elements in the list,
11104 * where each coordinate in the range is prescribed by the
11105 * corresponding affine expression.
11106 * The domains of all affine expressions in the list are assumed to match
11107 * domain_dim.
11109 __isl_give isl_basic_map *isl_basic_map_from_aff_list(
11110 __isl_take isl_space *domain_dim, __isl_take isl_aff_list *list)
11112 int i;
11113 isl_space *dim;
11114 isl_basic_map *bmap;
11116 if (!list)
11117 return NULL;
11119 dim = isl_space_from_domain(domain_dim);
11120 bmap = isl_basic_map_universe(dim);
11122 for (i = 0; i < list->n; ++i) {
11123 isl_aff *aff;
11124 isl_basic_map *bmap_i;
11126 aff = isl_aff_copy(list->p[i]);
11127 bmap_i = isl_basic_map_from_aff(aff);
11129 bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11132 isl_aff_list_free(list);
11133 return bmap;
11136 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
11137 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11139 return isl_map_equate(set, type1, pos1, type2, pos2);
11142 /* Construct a basic map where the given dimensions are equal to each other.
11144 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
11145 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11147 isl_basic_map *bmap = NULL;
11148 int i;
11150 if (!space)
11151 return NULL;
11153 if (pos1 >= isl_space_dim(space, type1))
11154 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11155 "index out of bounds", goto error);
11156 if (pos2 >= isl_space_dim(space, type2))
11157 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11158 "index out of bounds", goto error);
11160 if (type1 == type2 && pos1 == pos2)
11161 return isl_basic_map_universe(space);
11163 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
11164 i = isl_basic_map_alloc_equality(bmap);
11165 if (i < 0)
11166 goto error;
11167 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11168 pos1 += isl_basic_map_offset(bmap, type1);
11169 pos2 += isl_basic_map_offset(bmap, type2);
11170 isl_int_set_si(bmap->eq[i][pos1], -1);
11171 isl_int_set_si(bmap->eq[i][pos2], 1);
11172 bmap = isl_basic_map_finalize(bmap);
11173 isl_space_free(space);
11174 return bmap;
11175 error:
11176 isl_space_free(space);
11177 isl_basic_map_free(bmap);
11178 return NULL;
11181 /* Add a constraint imposing that the given two dimensions are equal.
11183 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
11184 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11186 isl_basic_map *eq;
11188 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
11190 bmap = isl_basic_map_intersect(bmap, eq);
11192 return bmap;
11195 /* Add a constraint imposing that the given two dimensions are equal.
11197 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
11198 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11200 isl_basic_map *bmap;
11202 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
11204 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11206 return map;
11209 /* Add a constraint imposing that the given two dimensions have opposite values.
11211 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
11212 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11214 isl_basic_map *bmap = NULL;
11215 int i;
11217 if (!map)
11218 return NULL;
11220 if (pos1 >= isl_map_dim(map, type1))
11221 isl_die(map->ctx, isl_error_invalid,
11222 "index out of bounds", goto error);
11223 if (pos2 >= isl_map_dim(map, type2))
11224 isl_die(map->ctx, isl_error_invalid,
11225 "index out of bounds", goto error);
11227 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
11228 i = isl_basic_map_alloc_equality(bmap);
11229 if (i < 0)
11230 goto error;
11231 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11232 pos1 += isl_basic_map_offset(bmap, type1);
11233 pos2 += isl_basic_map_offset(bmap, type2);
11234 isl_int_set_si(bmap->eq[i][pos1], 1);
11235 isl_int_set_si(bmap->eq[i][pos2], 1);
11236 bmap = isl_basic_map_finalize(bmap);
11238 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11240 return map;
11241 error:
11242 isl_basic_map_free(bmap);
11243 isl_map_free(map);
11244 return NULL;
11247 /* Add a constraint imposing that the value of the first dimension is
11248 * greater than or equal to that of the second.
11250 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
11251 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11253 isl_constraint *c;
11254 isl_local_space *ls;
11256 if (!bmap)
11257 return NULL;
11259 if (pos1 >= isl_basic_map_dim(bmap, type1))
11260 isl_die(bmap->ctx, isl_error_invalid,
11261 "index out of bounds", return isl_basic_map_free(bmap));
11262 if (pos2 >= isl_basic_map_dim(bmap, type2))
11263 isl_die(bmap->ctx, isl_error_invalid,
11264 "index out of bounds", return isl_basic_map_free(bmap));
11266 if (type1 == type2 && pos1 == pos2)
11267 return bmap;
11269 ls = isl_local_space_from_space(isl_basic_map_get_space(bmap));
11270 c = isl_inequality_alloc(ls);
11271 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
11272 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
11273 bmap = isl_basic_map_add_constraint(bmap, c);
11275 return bmap;
11278 /* Construct a basic map where the value of the first dimension is
11279 * greater than that of the second.
11281 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
11282 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11284 isl_basic_map *bmap = NULL;
11285 int i;
11287 if (!space)
11288 return NULL;
11290 if (pos1 >= isl_space_dim(space, type1))
11291 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11292 "index out of bounds", goto error);
11293 if (pos2 >= isl_space_dim(space, type2))
11294 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11295 "index out of bounds", goto error);
11297 if (type1 == type2 && pos1 == pos2)
11298 return isl_basic_map_empty(space);
11300 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
11301 i = isl_basic_map_alloc_inequality(bmap);
11302 if (i < 0)
11303 goto error;
11304 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
11305 pos1 += isl_basic_map_offset(bmap, type1);
11306 pos2 += isl_basic_map_offset(bmap, type2);
11307 isl_int_set_si(bmap->ineq[i][pos1], 1);
11308 isl_int_set_si(bmap->ineq[i][pos2], -1);
11309 isl_int_set_si(bmap->ineq[i][0], -1);
11310 bmap = isl_basic_map_finalize(bmap);
11312 return bmap;
11313 error:
11314 isl_space_free(space);
11315 isl_basic_map_free(bmap);
11316 return NULL;
11319 /* Add a constraint imposing that the value of the first dimension is
11320 * greater than that of the second.
11322 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
11323 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11325 isl_basic_map *gt;
11327 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
11329 bmap = isl_basic_map_intersect(bmap, gt);
11331 return bmap;
11334 /* Add a constraint imposing that the value of the first dimension is
11335 * greater than that of the second.
11337 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
11338 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11340 isl_basic_map *bmap;
11342 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
11344 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11346 return map;
11349 /* Add a constraint imposing that the value of the first dimension is
11350 * smaller than that of the second.
11352 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
11353 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11355 return isl_map_order_gt(map, type2, pos2, type1, pos1);
11358 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
11359 int pos)
11361 isl_aff *div;
11362 isl_local_space *ls;
11364 if (!bmap)
11365 return NULL;
11367 if (!isl_basic_map_divs_known(bmap))
11368 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
11369 "some divs are unknown", return NULL);
11371 ls = isl_basic_map_get_local_space(bmap);
11372 div = isl_local_space_get_div(ls, pos);
11373 isl_local_space_free(ls);
11375 return div;
11378 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
11379 int pos)
11381 return isl_basic_map_get_div(bset, pos);
11384 /* Plug in "subs" for dimension "type", "pos" of "bset".
11386 * Let i be the dimension to replace and let "subs" be of the form
11388 * f/d
11390 * Any integer division with a non-zero coefficient for i,
11392 * floor((a i + g)/m)
11394 * is replaced by
11396 * floor((a f + d g)/(m d))
11398 * Constraints of the form
11400 * a i + g
11402 * are replaced by
11404 * a f + d g
11406 * We currently require that "subs" is an integral expression.
11407 * Handling rational expressions may require us to add stride constraints
11408 * as we do in isl_basic_set_preimage_multi_aff.
11410 __isl_give isl_basic_set *isl_basic_set_substitute(
11411 __isl_take isl_basic_set *bset,
11412 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
11414 int i;
11415 isl_int v;
11416 isl_ctx *ctx;
11418 if (bset && isl_basic_set_plain_is_empty(bset))
11419 return bset;
11421 bset = isl_basic_set_cow(bset);
11422 if (!bset || !subs)
11423 goto error;
11425 ctx = isl_basic_set_get_ctx(bset);
11426 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
11427 isl_die(ctx, isl_error_invalid,
11428 "spaces don't match", goto error);
11429 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
11430 isl_die(ctx, isl_error_unsupported,
11431 "cannot handle divs yet", goto error);
11432 if (!isl_int_is_one(subs->v->el[0]))
11433 isl_die(ctx, isl_error_invalid,
11434 "can only substitute integer expressions", goto error);
11436 pos += isl_basic_set_offset(bset, type);
11438 isl_int_init(v);
11440 for (i = 0; i < bset->n_eq; ++i) {
11441 if (isl_int_is_zero(bset->eq[i][pos]))
11442 continue;
11443 isl_int_set(v, bset->eq[i][pos]);
11444 isl_int_set_si(bset->eq[i][pos], 0);
11445 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
11446 v, subs->v->el + 1, subs->v->size - 1);
11449 for (i = 0; i < bset->n_ineq; ++i) {
11450 if (isl_int_is_zero(bset->ineq[i][pos]))
11451 continue;
11452 isl_int_set(v, bset->ineq[i][pos]);
11453 isl_int_set_si(bset->ineq[i][pos], 0);
11454 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
11455 v, subs->v->el + 1, subs->v->size - 1);
11458 for (i = 0; i < bset->n_div; ++i) {
11459 if (isl_int_is_zero(bset->div[i][1 + pos]))
11460 continue;
11461 isl_int_set(v, bset->div[i][1 + pos]);
11462 isl_int_set_si(bset->div[i][1 + pos], 0);
11463 isl_seq_combine(bset->div[i] + 1,
11464 subs->v->el[0], bset->div[i] + 1,
11465 v, subs->v->el + 1, subs->v->size - 1);
11466 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
11469 isl_int_clear(v);
11471 bset = isl_basic_set_simplify(bset);
11472 return isl_basic_set_finalize(bset);
11473 error:
11474 isl_basic_set_free(bset);
11475 return NULL;
11478 /* Plug in "subs" for dimension "type", "pos" of "set".
11480 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
11481 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
11483 int i;
11485 if (set && isl_set_plain_is_empty(set))
11486 return set;
11488 set = isl_set_cow(set);
11489 if (!set || !subs)
11490 goto error;
11492 for (i = set->n - 1; i >= 0; --i) {
11493 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
11494 if (remove_if_empty(set, i) < 0)
11495 goto error;
11498 return set;
11499 error:
11500 isl_set_free(set);
11501 return NULL;
11504 /* Check if the range of "ma" is compatible with the domain or range
11505 * (depending on "type") of "bmap".
11506 * Return -1 if anything is wrong.
11508 static int check_basic_map_compatible_range_multi_aff(
11509 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
11510 __isl_keep isl_multi_aff *ma)
11512 int m;
11513 isl_space *ma_space;
11515 ma_space = isl_multi_aff_get_space(ma);
11516 m = isl_space_tuple_match(bmap->dim, type, ma_space, isl_dim_out);
11517 isl_space_free(ma_space);
11518 if (m >= 0 && !m)
11519 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
11520 "spaces don't match", return -1);
11521 return m;
11524 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
11525 * coefficients before the transformed range of dimensions,
11526 * the "n_after" coefficients after the transformed range of dimensions
11527 * and the coefficients of the other divs in "bmap".
11529 static int set_ma_divs(__isl_keep isl_basic_map *bmap,
11530 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
11532 int i;
11533 int n_param;
11534 int n_set;
11535 isl_local_space *ls;
11537 if (n_div == 0)
11538 return 0;
11540 ls = isl_aff_get_domain_local_space(ma->p[0]);
11541 if (!ls)
11542 return -1;
11544 n_param = isl_local_space_dim(ls, isl_dim_param);
11545 n_set = isl_local_space_dim(ls, isl_dim_set);
11546 for (i = 0; i < n_div; ++i) {
11547 int o_bmap = 0, o_ls = 0;
11549 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
11550 o_bmap += 1 + 1 + n_param;
11551 o_ls += 1 + 1 + n_param;
11552 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
11553 o_bmap += n_before;
11554 isl_seq_cpy(bmap->div[i] + o_bmap,
11555 ls->div->row[i] + o_ls, n_set);
11556 o_bmap += n_set;
11557 o_ls += n_set;
11558 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
11559 o_bmap += n_after;
11560 isl_seq_cpy(bmap->div[i] + o_bmap,
11561 ls->div->row[i] + o_ls, n_div);
11562 o_bmap += n_div;
11563 o_ls += n_div;
11564 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
11565 if (isl_basic_set_add_div_constraints(bmap, i) < 0)
11566 goto error;
11569 isl_local_space_free(ls);
11570 return 0;
11571 error:
11572 isl_local_space_free(ls);
11573 return -1;
11576 /* How many stride constraints does "ma" enforce?
11577 * That is, how many of the affine expressions have a denominator
11578 * different from one?
11580 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
11582 int i;
11583 int strides = 0;
11585 for (i = 0; i < ma->n; ++i)
11586 if (!isl_int_is_one(ma->p[i]->v->el[0]))
11587 strides++;
11589 return strides;
11592 /* For each affine expression in ma of the form
11594 * x_i = (f_i y + h_i)/m_i
11596 * with m_i different from one, add a constraint to "bmap"
11597 * of the form
11599 * f_i y + h_i = m_i alpha_i
11601 * with alpha_i an additional existentially quantified variable.
11603 static __isl_give isl_basic_map *add_ma_strides(
11604 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
11605 int n_before, int n_after)
11607 int i, k;
11608 int div;
11609 int total;
11610 int n_param;
11611 int n_in;
11612 int n_div;
11614 total = isl_basic_map_total_dim(bmap);
11615 n_param = isl_multi_aff_dim(ma, isl_dim_param);
11616 n_in = isl_multi_aff_dim(ma, isl_dim_in);
11617 n_div = isl_multi_aff_dim(ma, isl_dim_div);
11618 for (i = 0; i < ma->n; ++i) {
11619 int o_bmap = 0, o_ma = 1;
11621 if (isl_int_is_one(ma->p[i]->v->el[0]))
11622 continue;
11623 div = isl_basic_map_alloc_div(bmap);
11624 k = isl_basic_map_alloc_equality(bmap);
11625 if (div < 0 || k < 0)
11626 goto error;
11627 isl_int_set_si(bmap->div[div][0], 0);
11628 isl_seq_cpy(bmap->eq[k] + o_bmap,
11629 ma->p[i]->v->el + o_ma, 1 + n_param);
11630 o_bmap += 1 + n_param;
11631 o_ma += 1 + n_param;
11632 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
11633 o_bmap += n_before;
11634 isl_seq_cpy(bmap->eq[k] + o_bmap,
11635 ma->p[i]->v->el + o_ma, n_in);
11636 o_bmap += n_in;
11637 o_ma += n_in;
11638 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
11639 o_bmap += n_after;
11640 isl_seq_cpy(bmap->eq[k] + o_bmap,
11641 ma->p[i]->v->el + o_ma, n_div);
11642 o_bmap += n_div;
11643 o_ma += n_div;
11644 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
11645 isl_int_neg(bmap->eq[k][1 + total], ma->p[i]->v->el[0]);
11646 total++;
11649 return bmap;
11650 error:
11651 isl_basic_map_free(bmap);
11652 return NULL;
11655 /* Replace the domain or range space (depending on "type) of "space" by "set".
11657 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
11658 enum isl_dim_type type, __isl_take isl_space *set)
11660 if (type == isl_dim_in) {
11661 space = isl_space_range(space);
11662 space = isl_space_map_from_domain_and_range(set, space);
11663 } else {
11664 space = isl_space_domain(space);
11665 space = isl_space_map_from_domain_and_range(space, set);
11668 return space;
11671 /* Compute the preimage of the domain or range (depending on "type")
11672 * of "bmap" under the function represented by "ma".
11673 * In other words, plug in "ma" in the domain or range of "bmap".
11674 * The result is a basic map that lives in the same space as "bmap"
11675 * except that the domain or range has been replaced by
11676 * the domain space of "ma".
11678 * If bmap is represented by
11680 * A(p) + S u + B x + T v + C(divs) >= 0,
11682 * where u and x are input and output dimensions if type == isl_dim_out
11683 * while x and v are input and output dimensions if type == isl_dim_in,
11684 * and ma is represented by
11686 * x = D(p) + F(y) + G(divs')
11688 * then the result is
11690 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
11692 * The divs in the input set are similarly adjusted.
11693 * In particular
11695 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
11697 * becomes
11699 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
11700 * B_i G(divs') + c_i(divs))/n_i)
11702 * If bmap is not a rational map and if F(y) involves any denominators
11704 * x_i = (f_i y + h_i)/m_i
11706 * then additional constraints are added to ensure that we only
11707 * map back integer points. That is we enforce
11709 * f_i y + h_i = m_i alpha_i
11711 * with alpha_i an additional existentially quantified variable.
11713 * We first copy over the divs from "ma".
11714 * Then we add the modified constraints and divs from "bmap".
11715 * Finally, we add the stride constraints, if needed.
11717 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
11718 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
11719 __isl_take isl_multi_aff *ma)
11721 int i, k;
11722 isl_space *space;
11723 isl_basic_map *res = NULL;
11724 int n_before, n_after, n_div_bmap, n_div_ma;
11725 isl_int f, c1, c2, g;
11726 int rational, strides;
11728 isl_int_init(f);
11729 isl_int_init(c1);
11730 isl_int_init(c2);
11731 isl_int_init(g);
11733 ma = isl_multi_aff_align_divs(ma);
11734 if (!bmap || !ma)
11735 goto error;
11736 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
11737 goto error;
11739 if (type == isl_dim_in) {
11740 n_before = 0;
11741 n_after = isl_basic_map_dim(bmap, isl_dim_out);
11742 } else {
11743 n_before = isl_basic_map_dim(bmap, isl_dim_in);
11744 n_after = 0;
11746 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
11747 n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
11749 space = isl_multi_aff_get_domain_space(ma);
11750 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
11751 rational = isl_basic_map_is_rational(bmap);
11752 strides = rational ? 0 : multi_aff_strides(ma);
11753 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
11754 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
11755 if (rational)
11756 res = isl_basic_map_set_rational(res);
11758 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
11759 if (isl_basic_map_alloc_div(res) < 0)
11760 goto error;
11762 if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
11763 goto error;
11765 for (i = 0; i < bmap->n_eq; ++i) {
11766 k = isl_basic_map_alloc_equality(res);
11767 if (k < 0)
11768 goto error;
11769 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
11770 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
11773 for (i = 0; i < bmap->n_ineq; ++i) {
11774 k = isl_basic_map_alloc_inequality(res);
11775 if (k < 0)
11776 goto error;
11777 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
11778 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
11781 for (i = 0; i < bmap->n_div; ++i) {
11782 if (isl_int_is_zero(bmap->div[i][0])) {
11783 isl_int_set_si(res->div[n_div_ma + i][0], 0);
11784 continue;
11786 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
11787 n_before, n_after, n_div_ma, n_div_bmap,
11788 f, c1, c2, g, 1);
11791 if (strides)
11792 res = add_ma_strides(res, ma, n_before, n_after);
11794 isl_int_clear(f);
11795 isl_int_clear(c1);
11796 isl_int_clear(c2);
11797 isl_int_clear(g);
11798 isl_basic_map_free(bmap);
11799 isl_multi_aff_free(ma);
11800 res = isl_basic_set_simplify(res);
11801 return isl_basic_map_finalize(res);
11802 error:
11803 isl_int_clear(f);
11804 isl_int_clear(c1);
11805 isl_int_clear(c2);
11806 isl_int_clear(g);
11807 isl_basic_map_free(bmap);
11808 isl_multi_aff_free(ma);
11809 isl_basic_map_free(res);
11810 return NULL;
11813 /* Compute the preimage of "bset" under the function represented by "ma".
11814 * In other words, plug in "ma" in "bset". The result is a basic set
11815 * that lives in the domain space of "ma".
11817 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
11818 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
11820 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
11823 /* Check if the range of "ma" is compatible with the domain or range
11824 * (depending on "type") of "map".
11825 * Return -1 if anything is wrong.
11827 static int check_map_compatible_range_multi_aff(
11828 __isl_keep isl_map *map, enum isl_dim_type type,
11829 __isl_keep isl_multi_aff *ma)
11831 int m;
11832 isl_space *ma_space;
11834 ma_space = isl_multi_aff_get_space(ma);
11835 m = isl_space_tuple_match(map->dim, type, ma_space, isl_dim_out);
11836 isl_space_free(ma_space);
11837 if (m >= 0 && !m)
11838 isl_die(isl_map_get_ctx(map), isl_error_invalid,
11839 "spaces don't match", return -1);
11840 return m;
11843 /* Compute the preimage of the domain or range (depending on "type")
11844 * of "map" under the function represented by "ma".
11845 * In other words, plug in "ma" in the domain or range of "map".
11846 * The result is a map that lives in the same space as "map"
11847 * except that the domain or range has been replaced by
11848 * the domain space of "ma".
11850 * The parameters are assumed to have been aligned.
11852 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
11853 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
11855 int i;
11856 isl_space *space;
11858 map = isl_map_cow(map);
11859 ma = isl_multi_aff_align_divs(ma);
11860 if (!map || !ma)
11861 goto error;
11862 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
11863 goto error;
11865 for (i = 0; i < map->n; ++i) {
11866 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
11867 isl_multi_aff_copy(ma));
11868 if (!map->p[i])
11869 goto error;
11872 space = isl_multi_aff_get_domain_space(ma);
11873 space = isl_space_set(isl_map_get_space(map), type, space);
11875 isl_space_free(map->dim);
11876 map->dim = space;
11877 if (!map->dim)
11878 goto error;
11880 isl_multi_aff_free(ma);
11881 if (map->n > 1)
11882 ISL_F_CLR(map, ISL_MAP_DISJOINT);
11883 ISL_F_CLR(map, ISL_SET_NORMALIZED);
11884 return map;
11885 error:
11886 isl_multi_aff_free(ma);
11887 isl_map_free(map);
11888 return NULL;
11891 /* Compute the preimage of the domain or range (depending on "type")
11892 * of "map" under the function represented by "ma".
11893 * In other words, plug in "ma" in the domain or range of "map".
11894 * The result is a map that lives in the same space as "map"
11895 * except that the domain or range has been replaced by
11896 * the domain space of "ma".
11898 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
11899 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
11901 if (!map || !ma)
11902 goto error;
11904 if (isl_space_match(map->dim, isl_dim_param, ma->space, isl_dim_param))
11905 return map_preimage_multi_aff(map, type, ma);
11907 if (!isl_space_has_named_params(map->dim) ||
11908 !isl_space_has_named_params(ma->space))
11909 isl_die(map->ctx, isl_error_invalid,
11910 "unaligned unnamed parameters", goto error);
11911 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
11912 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
11914 return map_preimage_multi_aff(map, type, ma);
11915 error:
11916 isl_multi_aff_free(ma);
11917 return isl_map_free(map);
11920 /* Compute the preimage of "set" under the function represented by "ma".
11921 * In other words, plug in "ma" "set". The result is a set
11922 * that lives in the domain space of "ma".
11924 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
11925 __isl_take isl_multi_aff *ma)
11927 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
11930 /* Compute the preimage of the domain of "map" under the function
11931 * represented by "ma".
11932 * In other words, plug in "ma" in the domain of "map".
11933 * The result is a map that lives in the same space as "map"
11934 * except that the domain has been replaced by the domain space of "ma".
11936 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
11937 __isl_take isl_multi_aff *ma)
11939 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
11942 /* Compute the preimage of "set" under the function represented by "pma".
11943 * In other words, plug in "pma" in "set. The result is a set
11944 * that lives in the domain space of "pma".
11946 static __isl_give isl_set *set_preimage_pw_multi_aff(__isl_take isl_set *set,
11947 __isl_take isl_pw_multi_aff *pma)
11949 int i;
11950 isl_set *res;
11952 if (!pma)
11953 goto error;
11955 if (pma->n == 0) {
11956 isl_pw_multi_aff_free(pma);
11957 res = isl_set_empty(isl_set_get_space(set));
11958 isl_set_free(set);
11959 return res;
11962 res = isl_set_preimage_multi_aff(isl_set_copy(set),
11963 isl_multi_aff_copy(pma->p[0].maff));
11964 res = isl_set_intersect(res, isl_set_copy(pma->p[0].set));
11966 for (i = 1; i < pma->n; ++i) {
11967 isl_set *res_i;
11969 res_i = isl_set_preimage_multi_aff(isl_set_copy(set),
11970 isl_multi_aff_copy(pma->p[i].maff));
11971 res_i = isl_set_intersect(res_i, isl_set_copy(pma->p[i].set));
11972 res = isl_set_union(res, res_i);
11975 isl_pw_multi_aff_free(pma);
11976 isl_set_free(set);
11977 return res;
11978 error:
11979 isl_pw_multi_aff_free(pma);
11980 isl_set_free(set);
11981 return NULL;
11984 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
11985 __isl_take isl_pw_multi_aff *pma)
11987 if (!set || !pma)
11988 goto error;
11990 if (isl_space_match(set->dim, isl_dim_param, pma->dim, isl_dim_param))
11991 return set_preimage_pw_multi_aff(set, pma);
11993 if (!isl_space_has_named_params(set->dim) ||
11994 !isl_space_has_named_params(pma->dim))
11995 isl_die(set->ctx, isl_error_invalid,
11996 "unaligned unnamed parameters", goto error);
11997 set = isl_set_align_params(set, isl_pw_multi_aff_get_space(pma));
11998 pma = isl_pw_multi_aff_align_params(pma, isl_set_get_space(set));
12000 return set_preimage_pw_multi_aff(set, pma);
12001 error:
12002 isl_pw_multi_aff_free(pma);
12003 return isl_set_free(set);