blob: 8f021c09e667b561e043161bca438aed2e0e7926 [file] [log] [blame]
Tobias Grosser52a25232015-02-04 20:55:43 +00001/*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2014 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
6 *
7 * Use of this software is governed by the MIT license
8 *
9 * Written by Sven Verdoolaege, K.U.Leuven, Departement
10 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
11 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
12 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
13 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
14 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
15 * B.P. 105 - 78153 Le Chesnay, France
16 */
17
18#include <string.h>
19#include <isl_ctx_private.h>
20#include <isl_map_private.h>
21#include <isl_blk.h>
22#include "isl_space_private.h"
23#include "isl_equalities.h"
24#include <isl_lp_private.h>
25#include <isl_seq.h>
26#include <isl/set.h>
27#include <isl/map.h>
28#include <isl_reordering.h>
29#include "isl_sample.h"
30#include <isl_sort.h>
31#include "isl_tab.h"
32#include <isl/vec.h>
33#include <isl_mat_private.h>
34#include <isl_vec_private.h>
35#include <isl_dim_map.h>
36#include <isl_local_space_private.h>
37#include <isl_aff_private.h>
38#include <isl_options_private.h>
39#include <isl_morph.h>
40#include <isl_val_private.h>
41#include <isl/deprecated/map_int.h>
42#include <isl/deprecated/set_int.h>
43
44static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
45{
46 switch (type) {
47 case isl_dim_param: return dim->nparam;
48 case isl_dim_in: return dim->n_in;
49 case isl_dim_out: return dim->n_out;
50 case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
51 default: return 0;
52 }
53}
54
55static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
56{
57 switch (type) {
58 case isl_dim_param: return 1;
59 case isl_dim_in: return 1 + dim->nparam;
60 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
61 default: return 0;
62 }
63}
64
65unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
66 enum isl_dim_type type)
67{
68 if (!bmap)
69 return 0;
70 switch (type) {
71 case isl_dim_cst: return 1;
72 case isl_dim_param:
73 case isl_dim_in:
74 case isl_dim_out: return isl_space_dim(bmap->dim, type);
75 case isl_dim_div: return bmap->n_div;
76 case isl_dim_all: return isl_basic_map_total_dim(bmap);
77 default: return 0;
78 }
79}
80
81unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
82{
83 return map ? n(map->dim, type) : 0;
84}
85
86unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
87{
88 return set ? n(set->dim, type) : 0;
89}
90
91unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
92 enum isl_dim_type type)
93{
94 isl_space *dim = bmap->dim;
95 switch (type) {
96 case isl_dim_cst: return 0;
97 case isl_dim_param: return 1;
98 case isl_dim_in: return 1 + dim->nparam;
99 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
100 case isl_dim_div: return 1 + dim->nparam + dim->n_in + dim->n_out;
101 default: return 0;
102 }
103}
104
105unsigned isl_basic_set_offset(struct isl_basic_set *bset,
106 enum isl_dim_type type)
107{
108 return isl_basic_map_offset(bset, type);
109}
110
111static unsigned map_offset(struct isl_map *map, enum isl_dim_type type)
112{
113 return pos(map->dim, type);
114}
115
116unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
117 enum isl_dim_type type)
118{
119 return isl_basic_map_dim(bset, type);
120}
121
122unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
123{
124 return isl_basic_set_dim(bset, isl_dim_set);
125}
126
127unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
128{
129 return isl_basic_set_dim(bset, isl_dim_param);
130}
131
132unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset)
133{
134 if (!bset)
135 return 0;
136 return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
137}
138
139unsigned isl_set_n_dim(__isl_keep isl_set *set)
140{
141 return isl_set_dim(set, isl_dim_set);
142}
143
144unsigned isl_set_n_param(__isl_keep isl_set *set)
145{
146 return isl_set_dim(set, isl_dim_param);
147}
148
149unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap)
150{
151 return bmap ? bmap->dim->n_in : 0;
152}
153
154unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap)
155{
156 return bmap ? bmap->dim->n_out : 0;
157}
158
159unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap)
160{
161 return bmap ? bmap->dim->nparam : 0;
162}
163
164unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap)
165{
166 return bmap ? bmap->n_div : 0;
167}
168
169unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap)
170{
171 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
172}
173
174unsigned isl_map_n_in(const struct isl_map *map)
175{
176 return map ? map->dim->n_in : 0;
177}
178
179unsigned isl_map_n_out(const struct isl_map *map)
180{
181 return map ? map->dim->n_out : 0;
182}
183
184unsigned isl_map_n_param(const struct isl_map *map)
185{
186 return map ? map->dim->nparam : 0;
187}
188
189int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set)
190{
191 int m;
192 if (!map || !set)
193 return -1;
194 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
195 if (m < 0 || !m)
196 return m;
197 return isl_space_tuple_is_equal(map->dim, isl_dim_in,
198 set->dim, isl_dim_set);
199}
200
201int isl_basic_map_compatible_domain(struct isl_basic_map *bmap,
202 struct isl_basic_set *bset)
203{
204 int m;
205 if (!bmap || !bset)
206 return -1;
207 m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
208 if (m < 0 || !m)
209 return m;
210 return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
211 bset->dim, isl_dim_set);
212}
213
214int isl_map_compatible_range(__isl_keep isl_map *map, __isl_keep isl_set *set)
215{
216 int m;
217 if (!map || !set)
218 return -1;
219 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
220 if (m < 0 || !m)
221 return m;
222 return isl_space_tuple_is_equal(map->dim, isl_dim_out,
223 set->dim, isl_dim_set);
224}
225
226int isl_basic_map_compatible_range(struct isl_basic_map *bmap,
227 struct isl_basic_set *bset)
228{
229 int m;
230 if (!bmap || !bset)
231 return -1;
232 m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
233 if (m < 0 || !m)
234 return m;
235 return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
236 bset->dim, isl_dim_set);
237}
238
239isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
240{
241 return bmap ? bmap->ctx : NULL;
242}
243
244isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
245{
246 return bset ? bset->ctx : NULL;
247}
248
249isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
250{
251 return map ? map->ctx : NULL;
252}
253
254isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
255{
256 return set ? set->ctx : NULL;
257}
258
259__isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
260{
261 if (!bmap)
262 return NULL;
263 return isl_space_copy(bmap->dim);
264}
265
266__isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
267{
268 if (!bset)
269 return NULL;
270 return isl_space_copy(bset->dim);
271}
272
273/* Extract the divs in "bmap" as a matrix.
274 */
275__isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
276{
277 int i;
278 isl_ctx *ctx;
279 isl_mat *div;
280 unsigned total;
281 unsigned cols;
282
283 if (!bmap)
284 return NULL;
285
286 ctx = isl_basic_map_get_ctx(bmap);
287 total = isl_space_dim(bmap->dim, isl_dim_all);
288 cols = 1 + 1 + total + bmap->n_div;
289 div = isl_mat_alloc(ctx, bmap->n_div, cols);
290 if (!div)
291 return NULL;
292
293 for (i = 0; i < bmap->n_div; ++i)
294 isl_seq_cpy(div->row[i], bmap->div[i], cols);
295
296 return div;
297}
298
299/* Extract the divs in "bset" as a matrix.
300 */
301__isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
302{
303 return isl_basic_map_get_divs(bset);
304}
305
306__isl_give isl_local_space *isl_basic_map_get_local_space(
307 __isl_keep isl_basic_map *bmap)
308{
309 isl_mat *div;
310
311 if (!bmap)
312 return NULL;
313
314 div = isl_basic_map_get_divs(bmap);
315 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
316}
317
318__isl_give isl_local_space *isl_basic_set_get_local_space(
319 __isl_keep isl_basic_set *bset)
320{
321 return isl_basic_map_get_local_space(bset);
322}
323
324__isl_give isl_basic_map *isl_basic_map_from_local_space(
325 __isl_take isl_local_space *ls)
326{
327 int i;
328 int n_div;
329 isl_basic_map *bmap;
330
331 if (!ls)
332 return NULL;
333
334 n_div = isl_local_space_dim(ls, isl_dim_div);
335 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
336 n_div, 0, 2 * n_div);
337
338 for (i = 0; i < n_div; ++i)
339 if (isl_basic_map_alloc_div(bmap) < 0)
340 goto error;
341
342 for (i = 0; i < n_div; ++i) {
343 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
344 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
345 goto error;
346 }
347
348 isl_local_space_free(ls);
349 return bmap;
350error:
351 isl_local_space_free(ls);
352 isl_basic_map_free(bmap);
353 return NULL;
354}
355
356__isl_give isl_basic_set *isl_basic_set_from_local_space(
357 __isl_take isl_local_space *ls)
358{
359 return isl_basic_map_from_local_space(ls);
360}
361
362__isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
363{
364 if (!map)
365 return NULL;
366 return isl_space_copy(map->dim);
367}
368
369__isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
370{
371 if (!set)
372 return NULL;
373 return isl_space_copy(set->dim);
374}
375
376__isl_give isl_basic_map *isl_basic_map_set_tuple_name(
377 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
378{
379 bmap = isl_basic_map_cow(bmap);
380 if (!bmap)
381 return NULL;
382 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
383 if (!bmap->dim)
384 goto error;
385 bmap = isl_basic_map_finalize(bmap);
386 return bmap;
387error:
388 isl_basic_map_free(bmap);
389 return NULL;
390}
391
392__isl_give isl_basic_set *isl_basic_set_set_tuple_name(
393 __isl_take isl_basic_set *bset, const char *s)
394{
395 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
396}
397
398const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
399 enum isl_dim_type type)
400{
401 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
402}
403
404__isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
405 enum isl_dim_type type, const char *s)
406{
407 int i;
408
409 map = isl_map_cow(map);
410 if (!map)
411 return NULL;
412
413 map->dim = isl_space_set_tuple_name(map->dim, type, s);
414 if (!map->dim)
415 goto error;
416
417 for (i = 0; i < map->n; ++i) {
418 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
419 if (!map->p[i])
420 goto error;
421 }
422
423 return map;
424error:
425 isl_map_free(map);
426 return NULL;
427}
428
429/* Replace the identifier of the tuple of type "type" by "id".
430 */
431__isl_give isl_basic_map *isl_basic_map_set_tuple_id(
432 __isl_take isl_basic_map *bmap,
433 enum isl_dim_type type, __isl_take isl_id *id)
434{
435 bmap = isl_basic_map_cow(bmap);
436 if (!bmap)
437 goto error;
438 bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
439 if (!bmap->dim)
440 return isl_basic_map_free(bmap);
441 bmap = isl_basic_map_finalize(bmap);
442 return bmap;
443error:
444 isl_id_free(id);
445 return NULL;
446}
447
448/* Replace the identifier of the tuple by "id".
449 */
450__isl_give isl_basic_set *isl_basic_set_set_tuple_id(
451 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
452{
453 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
454}
455
456/* Does the input or output tuple have a name?
457 */
458int isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
459{
460 return map ? isl_space_has_tuple_name(map->dim, type) : -1;
461}
462
463const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
464 enum isl_dim_type type)
465{
466 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
467}
468
469__isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
470 const char *s)
471{
472 return (isl_set *)isl_map_set_tuple_name((isl_map *)set, isl_dim_set, s);
473}
474
475__isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
476 enum isl_dim_type type, __isl_take isl_id *id)
477{
478 map = isl_map_cow(map);
479 if (!map)
480 goto error;
481
482 map->dim = isl_space_set_tuple_id(map->dim, type, id);
483
484 return isl_map_reset_space(map, isl_space_copy(map->dim));
485error:
486 isl_id_free(id);
487 return NULL;
488}
489
490__isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
491 __isl_take isl_id *id)
492{
493 return isl_map_set_tuple_id(set, isl_dim_set, id);
494}
495
496__isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
497 enum isl_dim_type type)
498{
499 map = isl_map_cow(map);
500 if (!map)
501 return NULL;
502
503 map->dim = isl_space_reset_tuple_id(map->dim, type);
504
505 return isl_map_reset_space(map, isl_space_copy(map->dim));
506}
507
508__isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
509{
510 return isl_map_reset_tuple_id(set, isl_dim_set);
511}
512
513int isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
514{
515 return map ? isl_space_has_tuple_id(map->dim, type) : -1;
516}
517
518__isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
519 enum isl_dim_type type)
520{
521 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
522}
523
524int isl_set_has_tuple_id(__isl_keep isl_set *set)
525{
526 return isl_map_has_tuple_id(set, isl_dim_set);
527}
528
529__isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
530{
531 return isl_map_get_tuple_id(set, isl_dim_set);
532}
533
534/* Does the set tuple have a name?
535 */
536int isl_set_has_tuple_name(__isl_keep isl_set *set)
537{
538 return set ? isl_space_has_tuple_name(set->dim, isl_dim_set) : -1;
539}
540
541
542const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
543{
544 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
545}
546
547const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
548{
549 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
550}
551
552const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
553 enum isl_dim_type type, unsigned pos)
554{
555 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
556}
557
558const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
559 enum isl_dim_type type, unsigned pos)
560{
561 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
562}
563
564/* Does the given dimension have a name?
565 */
566int isl_map_has_dim_name(__isl_keep isl_map *map,
567 enum isl_dim_type type, unsigned pos)
568{
569 return map ? isl_space_has_dim_name(map->dim, type, pos) : -1;
570}
571
572const char *isl_map_get_dim_name(__isl_keep isl_map *map,
573 enum isl_dim_type type, unsigned pos)
574{
575 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
576}
577
578const char *isl_set_get_dim_name(__isl_keep isl_set *set,
579 enum isl_dim_type type, unsigned pos)
580{
581 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
582}
583
584/* Does the given dimension have a name?
585 */
586int isl_set_has_dim_name(__isl_keep isl_set *set,
587 enum isl_dim_type type, unsigned pos)
588{
589 return set ? isl_space_has_dim_name(set->dim, type, pos) : -1;
590}
591
592__isl_give isl_basic_map *isl_basic_map_set_dim_name(
593 __isl_take isl_basic_map *bmap,
594 enum isl_dim_type type, unsigned pos, const char *s)
595{
596 bmap = isl_basic_map_cow(bmap);
597 if (!bmap)
598 return NULL;
599 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
600 if (!bmap->dim)
601 goto error;
602 return isl_basic_map_finalize(bmap);
603error:
604 isl_basic_map_free(bmap);
605 return NULL;
606}
607
608__isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
609 enum isl_dim_type type, unsigned pos, const char *s)
610{
611 int i;
612
613 map = isl_map_cow(map);
614 if (!map)
615 return NULL;
616
617 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
618 if (!map->dim)
619 goto error;
620
621 for (i = 0; i < map->n; ++i) {
622 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
623 if (!map->p[i])
624 goto error;
625 }
626
627 return map;
628error:
629 isl_map_free(map);
630 return NULL;
631}
632
633__isl_give isl_basic_set *isl_basic_set_set_dim_name(
634 __isl_take isl_basic_set *bset,
635 enum isl_dim_type type, unsigned pos, const char *s)
636{
637 return (isl_basic_set *)isl_basic_map_set_dim_name(
638 (isl_basic_map *)bset, type, pos, s);
639}
640
641__isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
642 enum isl_dim_type type, unsigned pos, const char *s)
643{
644 return (isl_set *)isl_map_set_dim_name((isl_map *)set, type, pos, s);
645}
646
647int isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
648 enum isl_dim_type type, unsigned pos)
649{
650 return bmap ? isl_space_has_dim_id(bmap->dim, type, pos) : -1;
651}
652
653__isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
654 enum isl_dim_type type, unsigned pos)
655{
656 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
657}
658
659int isl_map_has_dim_id(__isl_keep isl_map *map,
660 enum isl_dim_type type, unsigned pos)
661{
662 return map ? isl_space_has_dim_id(map->dim, type, pos) : -1;
663}
664
665__isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
666 enum isl_dim_type type, unsigned pos)
667{
668 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
669}
670
671int isl_set_has_dim_id(__isl_keep isl_set *set,
672 enum isl_dim_type type, unsigned pos)
673{
674 return isl_map_has_dim_id(set, type, pos);
675}
676
677__isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
678 enum isl_dim_type type, unsigned pos)
679{
680 return isl_map_get_dim_id(set, type, pos);
681}
682
683__isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
684 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
685{
686 map = isl_map_cow(map);
687 if (!map)
688 goto error;
689
690 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
691
692 return isl_map_reset_space(map, isl_space_copy(map->dim));
693error:
694 isl_id_free(id);
695 return NULL;
696}
697
698__isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
699 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
700{
701 return isl_map_set_dim_id(set, type, pos, id);
702}
703
704int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
705 __isl_keep isl_id *id)
706{
707 if (!map)
708 return -1;
709 return isl_space_find_dim_by_id(map->dim, type, id);
710}
711
712int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
713 __isl_keep isl_id *id)
714{
715 return isl_map_find_dim_by_id(set, type, id);
716}
717
718/* Return the position of the dimension of the given type and name
719 * in "bmap".
720 * Return -1 if no such dimension can be found.
721 */
722int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
723 enum isl_dim_type type, const char *name)
724{
725 if (!bmap)
726 return -1;
727 return isl_space_find_dim_by_name(bmap->dim, type, name);
728}
729
730int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
731 const char *name)
732{
733 if (!map)
734 return -1;
735 return isl_space_find_dim_by_name(map->dim, type, name);
736}
737
738int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
739 const char *name)
740{
741 return isl_map_find_dim_by_name(set, type, name);
742}
743
744/* Reset the user pointer on all identifiers of parameters and tuples
745 * of the space of "map".
746 */
747__isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
748{
749 isl_space *space;
750
751 space = isl_map_get_space(map);
752 space = isl_space_reset_user(space);
753 map = isl_map_reset_space(map, space);
754
755 return map;
756}
757
758/* Reset the user pointer on all identifiers of parameters and tuples
759 * of the space of "set".
760 */
761__isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
762{
763 return isl_map_reset_user(set);
764}
765
766int isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
767{
768 if (!bmap)
769 return -1;
770 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
771}
772
773int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
774{
775 return isl_basic_map_is_rational(bset);
776}
777
778/* Does "bmap" contain any rational points?
779 *
780 * If "bmap" has an equality for each dimension, equating the dimension
781 * to an integer constant, then it has no rational points, even if it
782 * is marked as rational.
783 */
784int isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
785{
786 int has_rational = 1;
787 unsigned total;
788
789 if (!bmap)
790 return -1;
791 if (isl_basic_map_plain_is_empty(bmap))
792 return 0;
793 if (!isl_basic_map_is_rational(bmap))
794 return 0;
795 bmap = isl_basic_map_copy(bmap);
796 bmap = isl_basic_map_implicit_equalities(bmap);
797 if (!bmap)
798 return -1;
799 total = isl_basic_map_total_dim(bmap);
800 if (bmap->n_eq == total) {
801 int i, j;
802 for (i = 0; i < bmap->n_eq; ++i) {
803 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
804 if (j < 0)
805 break;
806 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
807 !isl_int_is_negone(bmap->eq[i][1 + j]))
808 break;
809 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
810 total - j - 1);
811 if (j >= 0)
812 break;
813 }
814 if (i == bmap->n_eq)
815 has_rational = 0;
816 }
817 isl_basic_map_free(bmap);
818
819 return has_rational;
820}
821
822/* Does "map" contain any rational points?
823 */
824int isl_map_has_rational(__isl_keep isl_map *map)
825{
826 int i;
827 int has_rational;
828
829 if (!map)
830 return -1;
831 for (i = 0; i < map->n; ++i) {
832 has_rational = isl_basic_map_has_rational(map->p[i]);
833 if (has_rational < 0)
834 return -1;
835 if (has_rational)
836 return 1;
837 }
838 return 0;
839}
840
841/* Does "set" contain any rational points?
842 */
843int isl_set_has_rational(__isl_keep isl_set *set)
844{
845 return isl_map_has_rational(set);
846}
847
848/* Is this basic set a parameter domain?
849 */
850int isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
851{
852 if (!bset)
853 return -1;
854 return isl_space_is_params(bset->dim);
855}
856
857/* Is this set a parameter domain?
858 */
859int isl_set_is_params(__isl_keep isl_set *set)
860{
861 if (!set)
862 return -1;
863 return isl_space_is_params(set->dim);
864}
865
866/* Is this map actually a parameter domain?
867 * Users should never call this function. Outside of isl,
868 * a map can never be a parameter domain.
869 */
870int isl_map_is_params(__isl_keep isl_map *map)
871{
872 if (!map)
873 return -1;
874 return isl_space_is_params(map->dim);
875}
876
877static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
878 struct isl_basic_map *bmap, unsigned extra,
879 unsigned n_eq, unsigned n_ineq)
880{
881 int i;
882 size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
883
884 bmap->ctx = ctx;
885 isl_ctx_ref(ctx);
886
887 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
888 if (isl_blk_is_error(bmap->block))
889 goto error;
890
891 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
892 if ((n_ineq + n_eq) && !bmap->ineq)
893 goto error;
894
895 if (extra == 0) {
896 bmap->block2 = isl_blk_empty();
897 bmap->div = NULL;
898 } else {
899 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
900 if (isl_blk_is_error(bmap->block2))
901 goto error;
902
903 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
904 if (!bmap->div)
905 goto error;
906 }
907
908 for (i = 0; i < n_ineq + n_eq; ++i)
909 bmap->ineq[i] = bmap->block.data + i * row_size;
910
911 for (i = 0; i < extra; ++i)
912 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
913
914 bmap->ref = 1;
915 bmap->flags = 0;
916 bmap->c_size = n_eq + n_ineq;
917 bmap->eq = bmap->ineq + n_ineq;
918 bmap->extra = extra;
919 bmap->n_eq = 0;
920 bmap->n_ineq = 0;
921 bmap->n_div = 0;
922 bmap->sample = NULL;
923
924 return bmap;
925error:
926 isl_basic_map_free(bmap);
927 return NULL;
928}
929
930struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
931 unsigned nparam, unsigned dim, unsigned extra,
932 unsigned n_eq, unsigned n_ineq)
933{
934 struct isl_basic_map *bmap;
935 isl_space *space;
936
937 space = isl_space_set_alloc(ctx, nparam, dim);
938 if (!space)
939 return NULL;
940
941 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
942 return (struct isl_basic_set *)bmap;
943}
944
945struct isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
946 unsigned extra, unsigned n_eq, unsigned n_ineq)
947{
948 struct isl_basic_map *bmap;
949 if (!dim)
950 return NULL;
951 isl_assert(dim->ctx, dim->n_in == 0, goto error);
952 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
953 return (struct isl_basic_set *)bmap;
954error:
955 isl_space_free(dim);
956 return NULL;
957}
958
959struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
960 unsigned extra, unsigned n_eq, unsigned n_ineq)
961{
962 struct isl_basic_map *bmap;
963
964 if (!dim)
965 return NULL;
966 bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
967 if (!bmap)
968 goto error;
969 bmap->dim = dim;
970
971 return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
972error:
973 isl_space_free(dim);
974 return NULL;
975}
976
977struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
978 unsigned nparam, unsigned in, unsigned out, unsigned extra,
979 unsigned n_eq, unsigned n_ineq)
980{
981 struct isl_basic_map *bmap;
982 isl_space *dim;
983
984 dim = isl_space_alloc(ctx, nparam, in, out);
985 if (!dim)
986 return NULL;
987
988 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
989 return bmap;
990}
991
992static void dup_constraints(
993 struct isl_basic_map *dst, struct isl_basic_map *src)
994{
995 int i;
996 unsigned total = isl_basic_map_total_dim(src);
997
998 for (i = 0; i < src->n_eq; ++i) {
999 int j = isl_basic_map_alloc_equality(dst);
1000 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1001 }
1002
1003 for (i = 0; i < src->n_ineq; ++i) {
1004 int j = isl_basic_map_alloc_inequality(dst);
1005 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1006 }
1007
1008 for (i = 0; i < src->n_div; ++i) {
1009 int j = isl_basic_map_alloc_div(dst);
1010 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1011 }
1012 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1013}
1014
1015struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap)
1016{
1017 struct isl_basic_map *dup;
1018
1019 if (!bmap)
1020 return NULL;
1021 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1022 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1023 if (!dup)
1024 return NULL;
1025 dup_constraints(dup, bmap);
1026 dup->flags = bmap->flags;
1027 dup->sample = isl_vec_copy(bmap->sample);
1028 return dup;
1029}
1030
1031struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1032{
1033 struct isl_basic_map *dup;
1034
1035 dup = isl_basic_map_dup((struct isl_basic_map *)bset);
1036 return (struct isl_basic_set *)dup;
1037}
1038
1039struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset)
1040{
1041 if (!bset)
1042 return NULL;
1043
1044 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1045 bset->ref++;
1046 return bset;
1047 }
1048 return isl_basic_set_dup(bset);
1049}
1050
1051struct isl_set *isl_set_copy(struct isl_set *set)
1052{
1053 if (!set)
1054 return NULL;
1055
1056 set->ref++;
1057 return set;
1058}
1059
1060struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap)
1061{
1062 if (!bmap)
1063 return NULL;
1064
1065 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1066 bmap->ref++;
1067 return bmap;
1068 }
1069 bmap = isl_basic_map_dup(bmap);
1070 if (bmap)
1071 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1072 return bmap;
1073}
1074
1075struct isl_map *isl_map_copy(struct isl_map *map)
1076{
1077 if (!map)
1078 return NULL;
1079
1080 map->ref++;
1081 return map;
1082}
1083
1084__isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1085{
1086 if (!bmap)
1087 return NULL;
1088
1089 if (--bmap->ref > 0)
1090 return NULL;
1091
1092 isl_ctx_deref(bmap->ctx);
1093 free(bmap->div);
1094 isl_blk_free(bmap->ctx, bmap->block2);
1095 free(bmap->ineq);
1096 isl_blk_free(bmap->ctx, bmap->block);
1097 isl_vec_free(bmap->sample);
1098 isl_space_free(bmap->dim);
1099 free(bmap);
1100
1101 return NULL;
1102}
1103
1104__isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1105{
1106 return isl_basic_map_free((struct isl_basic_map *)bset);
1107}
1108
1109static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1110{
1111 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1112}
1113
1114__isl_give isl_map *isl_map_align_params_map_map_and(
1115 __isl_take isl_map *map1, __isl_take isl_map *map2,
1116 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1117 __isl_take isl_map *map2))
1118{
1119 if (!map1 || !map2)
1120 goto error;
1121 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1122 return fn(map1, map2);
1123 if (!isl_space_has_named_params(map1->dim) ||
1124 !isl_space_has_named_params(map2->dim))
1125 isl_die(map1->ctx, isl_error_invalid,
1126 "unaligned unnamed parameters", goto error);
1127 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1128 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1129 return fn(map1, map2);
1130error:
1131 isl_map_free(map1);
1132 isl_map_free(map2);
1133 return NULL;
1134}
1135
1136int isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1137 __isl_keep isl_map *map2,
1138 int (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1139{
1140 int r;
1141
1142 if (!map1 || !map2)
1143 return -1;
1144 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1145 return fn(map1, map2);
1146 if (!isl_space_has_named_params(map1->dim) ||
1147 !isl_space_has_named_params(map2->dim))
1148 isl_die(map1->ctx, isl_error_invalid,
1149 "unaligned unnamed parameters", return -1);
1150 map1 = isl_map_copy(map1);
1151 map2 = isl_map_copy(map2);
1152 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1153 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1154 r = fn(map1, map2);
1155 isl_map_free(map1);
1156 isl_map_free(map2);
1157 return r;
1158}
1159
1160int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1161{
1162 struct isl_ctx *ctx;
1163 if (!bmap)
1164 return -1;
1165 ctx = bmap->ctx;
1166 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1167 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1168 return -1);
1169 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1170 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1171 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1172 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1173 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1174 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1175 isl_int *t;
1176 int j = isl_basic_map_alloc_inequality(bmap);
1177 if (j < 0)
1178 return -1;
1179 t = bmap->ineq[j];
1180 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1181 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1182 bmap->eq[-1] = t;
1183 bmap->n_eq++;
1184 bmap->n_ineq--;
1185 bmap->eq--;
1186 return 0;
1187 }
1188 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1189 bmap->extra - bmap->n_div);
1190 return bmap->n_eq++;
1191}
1192
1193int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1194{
1195 return isl_basic_map_alloc_equality((struct isl_basic_map *)bset);
1196}
1197
1198int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1199{
1200 if (!bmap)
1201 return -1;
1202 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1203 bmap->n_eq -= n;
1204 return 0;
1205}
1206
1207int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1208{
1209 return isl_basic_map_free_equality((struct isl_basic_map *)bset, n);
1210}
1211
1212int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1213{
1214 isl_int *t;
1215 if (!bmap)
1216 return -1;
1217 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1218
1219 if (pos != bmap->n_eq - 1) {
1220 t = bmap->eq[pos];
1221 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1222 bmap->eq[bmap->n_eq - 1] = t;
1223 }
1224 bmap->n_eq--;
1225 return 0;
1226}
1227
1228int isl_basic_set_drop_equality(struct isl_basic_set *bset, unsigned pos)
1229{
1230 return isl_basic_map_drop_equality((struct isl_basic_map *)bset, pos);
1231}
1232
1233/* Turn inequality "pos" of "bmap" into an equality.
1234 *
1235 * In particular, we move the inequality in front of the equalities
1236 * and move the last inequality in the position of the moved inequality.
1237 * Note that isl_tab_make_equalities_explicit depends on this particular
1238 * change in the ordering of the constraints.
1239 */
1240void isl_basic_map_inequality_to_equality(
1241 struct isl_basic_map *bmap, unsigned pos)
1242{
1243 isl_int *t;
1244
1245 t = bmap->ineq[pos];
1246 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1247 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1248 bmap->eq[-1] = t;
1249 bmap->n_eq++;
1250 bmap->n_ineq--;
1251 bmap->eq--;
1252 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1253 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1254 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1255 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1256}
1257
1258static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1259{
1260 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1261}
1262
1263int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap)
1264{
1265 struct isl_ctx *ctx;
1266 if (!bmap)
1267 return -1;
1268 ctx = bmap->ctx;
1269 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1270 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1271 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1272 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1273 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1274 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1275 1 + isl_basic_map_total_dim(bmap),
1276 bmap->extra - bmap->n_div);
1277 return bmap->n_ineq++;
1278}
1279
1280int isl_basic_set_alloc_inequality(struct isl_basic_set *bset)
1281{
1282 return isl_basic_map_alloc_inequality((struct isl_basic_map *)bset);
1283}
1284
1285int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1286{
1287 if (!bmap)
1288 return -1;
1289 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1290 bmap->n_ineq -= n;
1291 return 0;
1292}
1293
1294int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1295{
1296 return isl_basic_map_free_inequality((struct isl_basic_map *)bset, n);
1297}
1298
1299int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1300{
1301 isl_int *t;
1302 if (!bmap)
1303 return -1;
1304 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1305
1306 if (pos != bmap->n_ineq - 1) {
1307 t = bmap->ineq[pos];
1308 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1309 bmap->ineq[bmap->n_ineq - 1] = t;
1310 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1311 }
1312 bmap->n_ineq--;
1313 return 0;
1314}
1315
1316int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1317{
1318 return isl_basic_map_drop_inequality((struct isl_basic_map *)bset, pos);
1319}
1320
1321__isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1322 isl_int *eq)
1323{
1324 int k;
1325
1326 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1327 if (!bmap)
1328 return NULL;
1329 k = isl_basic_map_alloc_equality(bmap);
1330 if (k < 0)
1331 goto error;
1332 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1333 return bmap;
1334error:
1335 isl_basic_map_free(bmap);
1336 return NULL;
1337}
1338
1339__isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1340 isl_int *eq)
1341{
1342 return (isl_basic_set *)
1343 isl_basic_map_add_eq((isl_basic_map *)bset, eq);
1344}
1345
1346__isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1347 isl_int *ineq)
1348{
1349 int k;
1350
1351 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1352 if (!bmap)
1353 return NULL;
1354 k = isl_basic_map_alloc_inequality(bmap);
1355 if (k < 0)
1356 goto error;
1357 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1358 return bmap;
1359error:
1360 isl_basic_map_free(bmap);
1361 return NULL;
1362}
1363
1364__isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1365 isl_int *ineq)
1366{
1367 return (isl_basic_set *)
1368 isl_basic_map_add_ineq((isl_basic_map *)bset, ineq);
1369}
1370
1371int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1372{
1373 if (!bmap)
1374 return -1;
1375 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1376 isl_seq_clr(bmap->div[bmap->n_div] +
1377 1 + 1 + isl_basic_map_total_dim(bmap),
1378 bmap->extra - bmap->n_div);
1379 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1380 return bmap->n_div++;
1381}
1382
1383int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1384{
1385 return isl_basic_map_alloc_div((struct isl_basic_map *)bset);
1386}
1387
1388int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1389{
1390 if (!bmap)
1391 return -1;
1392 isl_assert(bmap->ctx, n <= bmap->n_div, return -1);
1393 bmap->n_div -= n;
1394 return 0;
1395}
1396
1397int isl_basic_set_free_div(struct isl_basic_set *bset, unsigned n)
1398{
1399 return isl_basic_map_free_div((struct isl_basic_map *)bset, n);
1400}
1401
1402/* Copy constraint from src to dst, putting the vars of src at offset
1403 * dim_off in dst and the divs of src at offset div_off in dst.
1404 * If both sets are actually map, then dim_off applies to the input
1405 * variables.
1406 */
1407static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
1408 struct isl_basic_map *src_map, isl_int *src,
1409 unsigned in_off, unsigned out_off, unsigned div_off)
1410{
1411 unsigned src_nparam = isl_basic_map_n_param(src_map);
1412 unsigned dst_nparam = isl_basic_map_n_param(dst_map);
1413 unsigned src_in = isl_basic_map_n_in(src_map);
1414 unsigned dst_in = isl_basic_map_n_in(dst_map);
1415 unsigned src_out = isl_basic_map_n_out(src_map);
1416 unsigned dst_out = isl_basic_map_n_out(dst_map);
1417 isl_int_set(dst[0], src[0]);
1418 isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
1419 if (dst_nparam > src_nparam)
1420 isl_seq_clr(dst+1+src_nparam,
1421 dst_nparam - src_nparam);
1422 isl_seq_clr(dst+1+dst_nparam, in_off);
1423 isl_seq_cpy(dst+1+dst_nparam+in_off,
1424 src+1+src_nparam,
1425 isl_min(dst_in-in_off, src_in));
1426 if (dst_in-in_off > src_in)
1427 isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
1428 dst_in - in_off - src_in);
1429 isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
1430 isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
1431 src+1+src_nparam+src_in,
1432 isl_min(dst_out-out_off, src_out));
1433 if (dst_out-out_off > src_out)
1434 isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
1435 dst_out - out_off - src_out);
1436 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
1437 isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
1438 src+1+src_nparam+src_in+src_out,
1439 isl_min(dst_map->extra-div_off, src_map->n_div));
1440 if (dst_map->n_div-div_off > src_map->n_div)
1441 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
1442 div_off+src_map->n_div,
1443 dst_map->n_div - div_off - src_map->n_div);
1444}
1445
1446static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
1447 struct isl_basic_map *src_map, isl_int *src,
1448 unsigned in_off, unsigned out_off, unsigned div_off)
1449{
1450 isl_int_set(dst[0], src[0]);
1451 copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
1452}
1453
1454static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1,
1455 struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos)
1456{
1457 int i;
1458 unsigned div_off;
1459
1460 if (!bmap1 || !bmap2)
1461 goto error;
1462
1463 div_off = bmap1->n_div;
1464
1465 for (i = 0; i < bmap2->n_eq; ++i) {
1466 int i1 = isl_basic_map_alloc_equality(bmap1);
1467 if (i1 < 0)
1468 goto error;
1469 copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
1470 i_pos, o_pos, div_off);
1471 }
1472
1473 for (i = 0; i < bmap2->n_ineq; ++i) {
1474 int i1 = isl_basic_map_alloc_inequality(bmap1);
1475 if (i1 < 0)
1476 goto error;
1477 copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
1478 i_pos, o_pos, div_off);
1479 }
1480
1481 for (i = 0; i < bmap2->n_div; ++i) {
1482 int i1 = isl_basic_map_alloc_div(bmap1);
1483 if (i1 < 0)
1484 goto error;
1485 copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
1486 i_pos, o_pos, div_off);
1487 }
1488
1489 isl_basic_map_free(bmap2);
1490
1491 return bmap1;
1492
1493error:
1494 isl_basic_map_free(bmap1);
1495 isl_basic_map_free(bmap2);
1496 return NULL;
1497}
1498
1499struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1500 struct isl_basic_set *bset2, unsigned pos)
1501{
1502 return (struct isl_basic_set *)
1503 add_constraints((struct isl_basic_map *)bset1,
1504 (struct isl_basic_map *)bset2, 0, pos);
1505}
1506
1507struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base,
1508 __isl_take isl_space *dim, unsigned extra,
1509 unsigned n_eq, unsigned n_ineq)
1510{
1511 struct isl_basic_map *ext;
1512 unsigned flags;
1513 int dims_ok;
1514
1515 if (!dim)
1516 goto error;
1517
1518 if (!base)
1519 goto error;
1520
1521 dims_ok = isl_space_is_equal(base->dim, dim) &&
1522 base->extra >= base->n_div + extra;
1523
1524 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1525 room_for_ineq(base, n_ineq)) {
1526 isl_space_free(dim);
1527 return base;
1528 }
1529
1530 isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
1531 isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
1532 isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
1533 extra += base->extra;
1534 n_eq += base->n_eq;
1535 n_ineq += base->n_ineq;
1536
1537 ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1538 dim = NULL;
1539 if (!ext)
1540 goto error;
1541
1542 if (dims_ok)
1543 ext->sample = isl_vec_copy(base->sample);
1544 flags = base->flags;
1545 ext = add_constraints(ext, base, 0, 0);
1546 if (ext) {
1547 ext->flags = flags;
1548 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1549 }
1550
1551 return ext;
1552
1553error:
1554 isl_space_free(dim);
1555 isl_basic_map_free(base);
1556 return NULL;
1557}
1558
1559struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base,
1560 __isl_take isl_space *dim, unsigned extra,
1561 unsigned n_eq, unsigned n_ineq)
1562{
1563 return (struct isl_basic_set *)
1564 isl_basic_map_extend_space((struct isl_basic_map *)base, dim,
1565 extra, n_eq, n_ineq);
1566}
1567
1568struct isl_basic_map *isl_basic_map_extend_constraints(
1569 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1570{
1571 if (!base)
1572 return NULL;
1573 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1574 0, n_eq, n_ineq);
1575}
1576
1577struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1578 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1579 unsigned n_eq, unsigned n_ineq)
1580{
1581 struct isl_basic_map *bmap;
1582 isl_space *dim;
1583
1584 if (!base)
1585 return NULL;
1586 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1587 if (!dim)
1588 goto error;
1589
1590 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1591 return bmap;
1592error:
1593 isl_basic_map_free(base);
1594 return NULL;
1595}
1596
1597struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
1598 unsigned nparam, unsigned dim, unsigned extra,
1599 unsigned n_eq, unsigned n_ineq)
1600{
1601 return (struct isl_basic_set *)
1602 isl_basic_map_extend((struct isl_basic_map *)base,
1603 nparam, 0, dim, extra, n_eq, n_ineq);
1604}
1605
1606struct isl_basic_set *isl_basic_set_extend_constraints(
1607 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1608{
1609 return (struct isl_basic_set *)
1610 isl_basic_map_extend_constraints((struct isl_basic_map *)base,
1611 n_eq, n_ineq);
1612}
1613
1614struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset)
1615{
1616 return (struct isl_basic_set *)
1617 isl_basic_map_cow((struct isl_basic_map *)bset);
1618}
1619
1620struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap)
1621{
1622 if (!bmap)
1623 return NULL;
1624
1625 if (bmap->ref > 1) {
1626 bmap->ref--;
1627 bmap = isl_basic_map_dup(bmap);
1628 }
1629 if (bmap)
1630 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1631 return bmap;
1632}
1633
1634struct isl_set *isl_set_cow(struct isl_set *set)
1635{
1636 if (!set)
1637 return NULL;
1638
1639 if (set->ref == 1)
1640 return set;
1641 set->ref--;
1642 return isl_set_dup(set);
1643}
1644
1645struct isl_map *isl_map_cow(struct isl_map *map)
1646{
1647 if (!map)
1648 return NULL;
1649
1650 if (map->ref == 1)
1651 return map;
1652 map->ref--;
1653 return isl_map_dup(map);
1654}
1655
1656static void swap_vars(struct isl_blk blk, isl_int *a,
1657 unsigned a_len, unsigned b_len)
1658{
1659 isl_seq_cpy(blk.data, a+a_len, b_len);
1660 isl_seq_cpy(blk.data+b_len, a, a_len);
1661 isl_seq_cpy(a, blk.data, b_len+a_len);
1662}
1663
1664static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1665 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1666{
1667 int i;
1668 struct isl_blk blk;
1669
1670 if (!bmap)
1671 goto error;
1672
1673 isl_assert(bmap->ctx,
1674 pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
1675
1676 if (n1 == 0 || n2 == 0)
1677 return bmap;
1678
1679 bmap = isl_basic_map_cow(bmap);
1680 if (!bmap)
1681 return NULL;
1682
1683 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
1684 if (isl_blk_is_error(blk))
1685 goto error;
1686
1687 for (i = 0; i < bmap->n_eq; ++i)
1688 swap_vars(blk,
1689 bmap->eq[i] + pos, n1, n2);
1690
1691 for (i = 0; i < bmap->n_ineq; ++i)
1692 swap_vars(blk,
1693 bmap->ineq[i] + pos, n1, n2);
1694
1695 for (i = 0; i < bmap->n_div; ++i)
1696 swap_vars(blk,
1697 bmap->div[i]+1 + pos, n1, n2);
1698
1699 isl_blk_free(bmap->ctx, blk);
1700
1701 ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
1702 bmap = isl_basic_map_gauss(bmap, NULL);
1703 return isl_basic_map_finalize(bmap);
1704error:
1705 isl_basic_map_free(bmap);
1706 return NULL;
1707}
1708
1709static __isl_give isl_basic_set *isl_basic_set_swap_vars(
1710 __isl_take isl_basic_set *bset, unsigned n)
1711{
1712 unsigned dim;
1713 unsigned nparam;
1714
1715 if (!bset)
1716 return NULL;
1717
1718 nparam = isl_basic_set_n_param(bset);
1719 dim = isl_basic_set_n_dim(bset);
1720 isl_assert(bset->ctx, n <= dim, goto error);
1721
1722 return isl_basic_map_swap_vars(bset, 1 + nparam, n, dim - n);
1723error:
1724 isl_basic_set_free(bset);
1725 return NULL;
1726}
1727
1728struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap)
1729{
1730 int i = 0;
1731 unsigned total;
1732 if (!bmap)
1733 goto error;
1734 total = isl_basic_map_total_dim(bmap);
1735 isl_basic_map_free_div(bmap, bmap->n_div);
1736 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
1737 if (bmap->n_eq > 0)
1738 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
1739 else {
1740 i = isl_basic_map_alloc_equality(bmap);
1741 if (i < 0)
1742 goto error;
1743 }
1744 isl_int_set_si(bmap->eq[i][0], 1);
1745 isl_seq_clr(bmap->eq[i]+1, total);
1746 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
1747 isl_vec_free(bmap->sample);
1748 bmap->sample = NULL;
1749 return isl_basic_map_finalize(bmap);
1750error:
1751 isl_basic_map_free(bmap);
1752 return NULL;
1753}
1754
1755struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset)
1756{
1757 return (struct isl_basic_set *)
1758 isl_basic_map_set_to_empty((struct isl_basic_map *)bset);
1759}
1760
1761/* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
1762 * of "bmap").
1763 */
1764static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
1765{
1766 isl_int *t = bmap->div[a];
1767 bmap->div[a] = bmap->div[b];
1768 bmap->div[b] = t;
1769}
1770
1771/* Swap divs "a" and "b" in "bmap" and adjust the constraints and
1772 * div definitions accordingly.
1773 */
1774void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
1775{
1776 int i;
1777 unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
1778
1779 swap_div(bmap, a, b);
1780
1781 for (i = 0; i < bmap->n_eq; ++i)
1782 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
1783
1784 for (i = 0; i < bmap->n_ineq; ++i)
1785 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
1786
1787 for (i = 0; i < bmap->n_div; ++i)
1788 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
1789 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1790}
1791
1792/* Eliminate the specified n dimensions starting at first from the
1793 * constraints, without removing the dimensions from the space.
1794 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1795 */
1796__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
1797 enum isl_dim_type type, unsigned first, unsigned n)
1798{
1799 int i;
1800
1801 if (!map)
1802 return NULL;
1803 if (n == 0)
1804 return map;
1805
1806 if (first + n > isl_map_dim(map, type) || first + n < first)
1807 isl_die(map->ctx, isl_error_invalid,
1808 "index out of bounds", goto error);
1809
1810 map = isl_map_cow(map);
1811 if (!map)
1812 return NULL;
1813
1814 for (i = 0; i < map->n; ++i) {
1815 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
1816 if (!map->p[i])
1817 goto error;
1818 }
1819 return map;
1820error:
1821 isl_map_free(map);
1822 return NULL;
1823}
1824
1825/* Eliminate the specified n dimensions starting at first from the
1826 * constraints, without removing the dimensions from the space.
1827 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1828 */
1829__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
1830 enum isl_dim_type type, unsigned first, unsigned n)
1831{
1832 return (isl_set *)isl_map_eliminate((isl_map *)set, type, first, n);
1833}
1834
1835/* Eliminate the specified n dimensions starting at first from the
1836 * constraints, without removing the dimensions from the space.
1837 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1838 */
1839__isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
1840 unsigned first, unsigned n)
1841{
1842 return isl_set_eliminate(set, isl_dim_set, first, n);
1843}
1844
1845__isl_give isl_basic_map *isl_basic_map_remove_divs(
1846 __isl_take isl_basic_map *bmap)
1847{
1848 if (!bmap)
1849 return NULL;
1850 bmap = isl_basic_map_eliminate_vars(bmap,
1851 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
1852 if (!bmap)
1853 return NULL;
1854 bmap->n_div = 0;
1855 return isl_basic_map_finalize(bmap);
1856}
1857
1858__isl_give isl_basic_set *isl_basic_set_remove_divs(
1859 __isl_take isl_basic_set *bset)
1860{
1861 return (struct isl_basic_set *)isl_basic_map_remove_divs(
1862 (struct isl_basic_map *)bset);
1863}
1864
1865__isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
1866{
1867 int i;
1868
1869 if (!map)
1870 return NULL;
1871 if (map->n == 0)
1872 return map;
1873
1874 map = isl_map_cow(map);
1875 if (!map)
1876 return NULL;
1877
1878 for (i = 0; i < map->n; ++i) {
1879 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
1880 if (!map->p[i])
1881 goto error;
1882 }
1883 return map;
1884error:
1885 isl_map_free(map);
1886 return NULL;
1887}
1888
1889__isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
1890{
1891 return isl_map_remove_divs(set);
1892}
1893
1894struct isl_basic_map *isl_basic_map_remove_dims(struct isl_basic_map *bmap,
1895 enum isl_dim_type type, unsigned first, unsigned n)
1896{
1897 if (!bmap)
1898 return NULL;
1899 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
1900 goto error);
1901 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
1902 return bmap;
1903 bmap = isl_basic_map_eliminate_vars(bmap,
1904 isl_basic_map_offset(bmap, type) - 1 + first, n);
1905 if (!bmap)
1906 return bmap;
1907 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
1908 return bmap;
1909 bmap = isl_basic_map_drop(bmap, type, first, n);
1910 return bmap;
1911error:
1912 isl_basic_map_free(bmap);
1913 return NULL;
1914}
1915
1916/* Return true if the definition of the given div (recursively) involves
1917 * any of the given variables.
1918 */
1919static int div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
1920 unsigned first, unsigned n)
1921{
1922 int i;
1923 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
1924
1925 if (isl_int_is_zero(bmap->div[div][0]))
1926 return 0;
1927 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
1928 return 1;
1929
1930 for (i = bmap->n_div - 1; i >= 0; --i) {
1931 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
1932 continue;
1933 if (div_involves_vars(bmap, i, first, n))
1934 return 1;
1935 }
1936
1937 return 0;
1938}
1939
1940/* Try and add a lower and/or upper bound on "div" to "bmap"
1941 * based on inequality "i".
1942 * "total" is the total number of variables (excluding the divs).
1943 * "v" is a temporary object that can be used during the calculations.
1944 * If "lb" is set, then a lower bound should be constructed.
1945 * If "ub" is set, then an upper bound should be constructed.
1946 *
1947 * The calling function has already checked that the inequality does not
1948 * reference "div", but we still need to check that the inequality is
1949 * of the right form. We'll consider the case where we want to construct
1950 * a lower bound. The construction of upper bounds is similar.
1951 *
1952 * Let "div" be of the form
1953 *
1954 * q = floor((a + f(x))/d)
1955 *
1956 * We essentially check if constraint "i" is of the form
1957 *
1958 * b + f(x) >= 0
1959 *
1960 * so that we can use it to derive a lower bound on "div".
1961 * However, we allow a slightly more general form
1962 *
1963 * b + g(x) >= 0
1964 *
1965 * with the condition that the coefficients of g(x) - f(x) are all
1966 * divisible by d.
1967 * Rewriting this constraint as
1968 *
1969 * 0 >= -b - g(x)
1970 *
1971 * adding a + f(x) to both sides and dividing by d, we obtain
1972 *
1973 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
1974 *
1975 * Taking the floor on both sides, we obtain
1976 *
1977 * q >= floor((a-b)/d) + (f(x)-g(x))/d
1978 *
1979 * or
1980 *
1981 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
1982 *
1983 * In the case of an upper bound, we construct the constraint
1984 *
1985 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
1986 *
1987 */
1988static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
1989 __isl_take isl_basic_map *bmap, int div, int i,
1990 unsigned total, isl_int v, int lb, int ub)
1991{
1992 int j;
1993
1994 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
1995 if (lb) {
1996 isl_int_sub(v, bmap->ineq[i][1 + j],
1997 bmap->div[div][1 + 1 + j]);
1998 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
1999 }
2000 if (ub) {
2001 isl_int_add(v, bmap->ineq[i][1 + j],
2002 bmap->div[div][1 + 1 + j]);
2003 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2004 }
2005 }
2006 if (!lb && !ub)
2007 return bmap;
2008
2009 bmap = isl_basic_map_cow(bmap);
2010 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2011 if (lb) {
2012 int k = isl_basic_map_alloc_inequality(bmap);
2013 if (k < 0)
2014 goto error;
2015 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2016 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2017 bmap->div[div][1 + j]);
2018 isl_int_cdiv_q(bmap->ineq[k][j],
2019 bmap->ineq[k][j], bmap->div[div][0]);
2020 }
2021 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2022 }
2023 if (ub) {
2024 int k = isl_basic_map_alloc_inequality(bmap);
2025 if (k < 0)
2026 goto error;
2027 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2028 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2029 bmap->div[div][1 + j]);
2030 isl_int_fdiv_q(bmap->ineq[k][j],
2031 bmap->ineq[k][j], bmap->div[div][0]);
2032 }
2033 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2034 }
2035
2036 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2037 return bmap;
2038error:
2039 isl_basic_map_free(bmap);
2040 return NULL;
2041}
2042
2043/* This function is called right before "div" is eliminated from "bmap"
2044 * using Fourier-Motzkin.
2045 * Look through the constraints of "bmap" for constraints on the argument
2046 * of the integer division and use them to construct constraints on the
2047 * integer division itself. These constraints can then be combined
2048 * during the Fourier-Motzkin elimination.
2049 * Note that it is only useful to introduce lower bounds on "div"
2050 * if "bmap" already contains upper bounds on "div" as the newly
2051 * introduce lower bounds can then be combined with the pre-existing
2052 * upper bounds. Similarly for upper bounds.
2053 * We therefore first check if "bmap" contains any lower and/or upper bounds
2054 * on "div".
2055 *
2056 * It is interesting to note that the introduction of these constraints
2057 * can indeed lead to more accurate results, even when compared to
2058 * deriving constraints on the argument of "div" from constraints on "div".
2059 * Consider, for example, the set
2060 *
2061 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2062 *
2063 * The second constraint can be rewritten as
2064 *
2065 * 2 * [(-i-2j+3)/4] + k >= 0
2066 *
2067 * from which we can derive
2068 *
2069 * -i - 2j + 3 >= -2k
2070 *
2071 * or
2072 *
2073 * i + 2j <= 3 + 2k
2074 *
2075 * Combined with the first constraint, we obtain
2076 *
2077 * -3 <= 3 + 2k or k >= -3
2078 *
2079 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2080 * the first constraint, we obtain
2081 *
2082 * [(i + 2j)/4] >= [-3/4] = -1
2083 *
2084 * Combining this constraint with the second constraint, we obtain
2085 *
2086 * k >= -2
2087 */
2088static __isl_give isl_basic_map *insert_bounds_on_div(
2089 __isl_take isl_basic_map *bmap, int div)
2090{
2091 int i;
2092 int check_lb, check_ub;
2093 isl_int v;
2094 unsigned total;
2095
2096 if (!bmap)
2097 return NULL;
2098
2099 if (isl_int_is_zero(bmap->div[div][0]))
2100 return bmap;
2101
2102 total = isl_space_dim(bmap->dim, isl_dim_all);
2103
2104 check_lb = 0;
2105 check_ub = 0;
2106 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2107 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2108 if (s > 0)
2109 check_ub = 1;
2110 if (s < 0)
2111 check_lb = 1;
2112 }
2113
2114 if (!check_lb && !check_ub)
2115 return bmap;
2116
2117 isl_int_init(v);
2118
2119 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2120 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2121 continue;
2122
2123 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2124 check_lb, check_ub);
2125 }
2126
2127 isl_int_clear(v);
2128
2129 return bmap;
2130}
2131
2132/* Remove all divs (recursively) involving any of the given dimensions
2133 * in their definitions.
2134 */
2135__isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2136 __isl_take isl_basic_map *bmap,
2137 enum isl_dim_type type, unsigned first, unsigned n)
2138{
2139 int i;
2140
2141 if (!bmap)
2142 return NULL;
2143 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
2144 goto error);
2145 first += isl_basic_map_offset(bmap, type);
2146
2147 for (i = bmap->n_div - 1; i >= 0; --i) {
2148 if (!div_involves_vars(bmap, i, first, n))
2149 continue;
2150 bmap = insert_bounds_on_div(bmap, i);
2151 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2152 if (!bmap)
2153 return NULL;
2154 i = bmap->n_div;
2155 }
2156
2157 return bmap;
2158error:
2159 isl_basic_map_free(bmap);
2160 return NULL;
2161}
2162
2163__isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2164 __isl_take isl_basic_set *bset,
2165 enum isl_dim_type type, unsigned first, unsigned n)
2166{
2167 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2168}
2169
2170__isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2171 enum isl_dim_type type, unsigned first, unsigned n)
2172{
2173 int i;
2174
2175 if (!map)
2176 return NULL;
2177 if (map->n == 0)
2178 return map;
2179
2180 map = isl_map_cow(map);
2181 if (!map)
2182 return NULL;
2183
2184 for (i = 0; i < map->n; ++i) {
2185 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2186 type, first, n);
2187 if (!map->p[i])
2188 goto error;
2189 }
2190 return map;
2191error:
2192 isl_map_free(map);
2193 return NULL;
2194}
2195
2196__isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2197 enum isl_dim_type type, unsigned first, unsigned n)
2198{
2199 return (isl_set *)isl_map_remove_divs_involving_dims((isl_map *)set,
2200 type, first, n);
2201}
2202
2203/* Does the desciption of "bmap" depend on the specified dimensions?
2204 * We also check whether the dimensions appear in any of the div definitions.
2205 * In principle there is no need for this check. If the dimensions appear
2206 * in a div definition, they also appear in the defining constraints of that
2207 * div.
2208 */
2209int isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2210 enum isl_dim_type type, unsigned first, unsigned n)
2211{
2212 int i;
2213
2214 if (!bmap)
2215 return -1;
2216
2217 if (first + n > isl_basic_map_dim(bmap, type))
2218 isl_die(bmap->ctx, isl_error_invalid,
2219 "index out of bounds", return -1);
2220
2221 first += isl_basic_map_offset(bmap, type);
2222 for (i = 0; i < bmap->n_eq; ++i)
2223 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2224 return 1;
2225 for (i = 0; i < bmap->n_ineq; ++i)
2226 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2227 return 1;
2228 for (i = 0; i < bmap->n_div; ++i) {
2229 if (isl_int_is_zero(bmap->div[i][0]))
2230 continue;
2231 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2232 return 1;
2233 }
2234
2235 return 0;
2236}
2237
2238int isl_map_involves_dims(__isl_keep isl_map *map,
2239 enum isl_dim_type type, unsigned first, unsigned n)
2240{
2241 int i;
2242
2243 if (!map)
2244 return -1;
2245
2246 if (first + n > isl_map_dim(map, type))
2247 isl_die(map->ctx, isl_error_invalid,
2248 "index out of bounds", return -1);
2249
2250 for (i = 0; i < map->n; ++i) {
2251 int involves = isl_basic_map_involves_dims(map->p[i],
2252 type, first, n);
2253 if (involves < 0 || involves)
2254 return involves;
2255 }
2256
2257 return 0;
2258}
2259
2260int isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2261 enum isl_dim_type type, unsigned first, unsigned n)
2262{
2263 return isl_basic_map_involves_dims(bset, type, first, n);
2264}
2265
2266int isl_set_involves_dims(__isl_keep isl_set *set,
2267 enum isl_dim_type type, unsigned first, unsigned n)
2268{
2269 return isl_map_involves_dims(set, type, first, n);
2270}
2271
2272/* Return true if the definition of the given div is unknown or depends
2273 * on unknown divs.
2274 */
2275static int div_is_unknown(__isl_keep isl_basic_map *bmap, int div)
2276{
2277 int i;
2278 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2279
2280 if (isl_int_is_zero(bmap->div[div][0]))
2281 return 1;
2282
2283 for (i = bmap->n_div - 1; i >= 0; --i) {
2284 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2285 continue;
2286 if (div_is_unknown(bmap, i))
2287 return 1;
2288 }
2289
2290 return 0;
2291}
2292
2293/* Remove all divs that are unknown or defined in terms of unknown divs.
2294 */
2295__isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
2296 __isl_take isl_basic_map *bmap)
2297{
2298 int i;
2299
2300 if (!bmap)
2301 return NULL;
2302
2303 for (i = bmap->n_div - 1; i >= 0; --i) {
2304 if (!div_is_unknown(bmap, i))
2305 continue;
2306 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2307 if (!bmap)
2308 return NULL;
2309 i = bmap->n_div;
2310 }
2311
2312 return bmap;
2313}
2314
2315/* Remove all divs that are unknown or defined in terms of unknown divs.
2316 */
2317__isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
2318 __isl_take isl_basic_set *bset)
2319{
2320 return isl_basic_map_remove_unknown_divs(bset);
2321}
2322
2323__isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
2324{
2325 int i;
2326
2327 if (!map)
2328 return NULL;
2329 if (map->n == 0)
2330 return map;
2331
2332 map = isl_map_cow(map);
2333 if (!map)
2334 return NULL;
2335
2336 for (i = 0; i < map->n; ++i) {
2337 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
2338 if (!map->p[i])
2339 goto error;
2340 }
2341 return map;
2342error:
2343 isl_map_free(map);
2344 return NULL;
2345}
2346
2347__isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
2348{
2349 return (isl_set *)isl_map_remove_unknown_divs((isl_map *)set);
2350}
2351
2352__isl_give isl_basic_set *isl_basic_set_remove_dims(
2353 __isl_take isl_basic_set *bset,
2354 enum isl_dim_type type, unsigned first, unsigned n)
2355{
2356 return (isl_basic_set *)
2357 isl_basic_map_remove_dims((isl_basic_map *)bset, type, first, n);
2358}
2359
2360struct isl_map *isl_map_remove_dims(struct isl_map *map,
2361 enum isl_dim_type type, unsigned first, unsigned n)
2362{
2363 int i;
2364
2365 if (n == 0)
2366 return map;
2367
2368 map = isl_map_cow(map);
2369 if (!map)
2370 return NULL;
2371 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
2372
2373 for (i = 0; i < map->n; ++i) {
2374 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
2375 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
2376 if (!map->p[i])
2377 goto error;
2378 }
2379 map = isl_map_drop(map, type, first, n);
2380 return map;
2381error:
2382 isl_map_free(map);
2383 return NULL;
2384}
2385
2386__isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
2387 enum isl_dim_type type, unsigned first, unsigned n)
2388{
2389 return (isl_set *)isl_map_remove_dims((isl_map *)bset, type, first, n);
2390}
2391
2392/* Project out n inputs starting at first using Fourier-Motzkin */
2393struct isl_map *isl_map_remove_inputs(struct isl_map *map,
2394 unsigned first, unsigned n)
2395{
2396 return isl_map_remove_dims(map, isl_dim_in, first, n);
2397}
2398
2399static void dump_term(struct isl_basic_map *bmap,
2400 isl_int c, int pos, FILE *out)
2401{
2402 const char *name;
2403 unsigned in = isl_basic_map_n_in(bmap);
2404 unsigned dim = in + isl_basic_map_n_out(bmap);
2405 unsigned nparam = isl_basic_map_n_param(bmap);
2406 if (!pos)
2407 isl_int_print(out, c, 0);
2408 else {
2409 if (!isl_int_is_one(c))
2410 isl_int_print(out, c, 0);
2411 if (pos < 1 + nparam) {
2412 name = isl_space_get_dim_name(bmap->dim,
2413 isl_dim_param, pos - 1);
2414 if (name)
2415 fprintf(out, "%s", name);
2416 else
2417 fprintf(out, "p%d", pos - 1);
2418 } else if (pos < 1 + nparam + in)
2419 fprintf(out, "i%d", pos - 1 - nparam);
2420 else if (pos < 1 + nparam + dim)
2421 fprintf(out, "o%d", pos - 1 - nparam - in);
2422 else
2423 fprintf(out, "e%d", pos - 1 - nparam - dim);
2424 }
2425}
2426
2427static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
2428 int sign, FILE *out)
2429{
2430 int i;
2431 int first;
2432 unsigned len = 1 + isl_basic_map_total_dim(bmap);
2433 isl_int v;
2434
2435 isl_int_init(v);
2436 for (i = 0, first = 1; i < len; ++i) {
2437 if (isl_int_sgn(c[i]) * sign <= 0)
2438 continue;
2439 if (!first)
2440 fprintf(out, " + ");
2441 first = 0;
2442 isl_int_abs(v, c[i]);
2443 dump_term(bmap, v, i, out);
2444 }
2445 isl_int_clear(v);
2446 if (first)
2447 fprintf(out, "0");
2448}
2449
2450static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
2451 const char *op, FILE *out, int indent)
2452{
2453 int i;
2454
2455 fprintf(out, "%*s", indent, "");
2456
2457 dump_constraint_sign(bmap, c, 1, out);
2458 fprintf(out, " %s ", op);
2459 dump_constraint_sign(bmap, c, -1, out);
2460
2461 fprintf(out, "\n");
2462
2463 for (i = bmap->n_div; i < bmap->extra; ++i) {
2464 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
2465 continue;
2466 fprintf(out, "%*s", indent, "");
2467 fprintf(out, "ERROR: unused div coefficient not zero\n");
2468 abort();
2469 }
2470}
2471
2472static void dump_constraints(struct isl_basic_map *bmap,
2473 isl_int **c, unsigned n,
2474 const char *op, FILE *out, int indent)
2475{
2476 int i;
2477
2478 for (i = 0; i < n; ++i)
2479 dump_constraint(bmap, c[i], op, out, indent);
2480}
2481
2482static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
2483{
2484 int j;
2485 int first = 1;
2486 unsigned total = isl_basic_map_total_dim(bmap);
2487
2488 for (j = 0; j < 1 + total; ++j) {
2489 if (isl_int_is_zero(exp[j]))
2490 continue;
2491 if (!first && isl_int_is_pos(exp[j]))
2492 fprintf(out, "+");
2493 dump_term(bmap, exp[j], j, out);
2494 first = 0;
2495 }
2496}
2497
2498static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
2499{
2500 int i;
2501
2502 dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
2503 dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
2504
2505 for (i = 0; i < bmap->n_div; ++i) {
2506 fprintf(out, "%*s", indent, "");
2507 fprintf(out, "e%d = [(", i);
2508 dump_affine(bmap, bmap->div[i]+1, out);
2509 fprintf(out, ")/");
2510 isl_int_print(out, bmap->div[i][0], 0);
2511 fprintf(out, "]\n");
2512 }
2513}
2514
2515void isl_basic_set_print_internal(struct isl_basic_set *bset,
2516 FILE *out, int indent)
2517{
2518 if (!bset) {
2519 fprintf(out, "null basic set\n");
2520 return;
2521 }
2522
2523 fprintf(out, "%*s", indent, "");
2524 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
2525 bset->ref, bset->dim->nparam, bset->dim->n_out,
2526 bset->extra, bset->flags);
2527 dump((struct isl_basic_map *)bset, out, indent);
2528}
2529
2530void isl_basic_map_print_internal(struct isl_basic_map *bmap,
2531 FILE *out, int indent)
2532{
2533 if (!bmap) {
2534 fprintf(out, "null basic map\n");
2535 return;
2536 }
2537
2538 fprintf(out, "%*s", indent, "");
2539 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
2540 "flags: %x, n_name: %d\n",
2541 bmap->ref,
2542 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
2543 bmap->extra, bmap->flags, bmap->dim->n_id);
2544 dump(bmap, out, indent);
2545}
2546
2547int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
2548{
2549 unsigned total;
2550 if (!bmap)
2551 return -1;
2552 total = isl_basic_map_total_dim(bmap);
2553 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
2554 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
2555 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
2556 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2557 return 0;
2558}
2559
2560__isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *dim, int n,
2561 unsigned flags)
2562{
2563 struct isl_set *set;
2564
2565 if (!dim)
2566 return NULL;
2567 isl_assert(dim->ctx, dim->n_in == 0, goto error);
2568 isl_assert(dim->ctx, n >= 0, goto error);
2569 set = isl_alloc(dim->ctx, struct isl_set,
2570 sizeof(struct isl_set) +
2571 (n - 1) * sizeof(struct isl_basic_set *));
2572 if (!set)
2573 goto error;
2574
2575 set->ctx = dim->ctx;
2576 isl_ctx_ref(set->ctx);
2577 set->ref = 1;
2578 set->size = n;
2579 set->n = 0;
2580 set->dim = dim;
2581 set->flags = flags;
2582 return set;
2583error:
2584 isl_space_free(dim);
2585 return NULL;
2586}
2587
2588struct isl_set *isl_set_alloc(struct isl_ctx *ctx,
2589 unsigned nparam, unsigned dim, int n, unsigned flags)
2590{
2591 struct isl_set *set;
2592 isl_space *dims;
2593
2594 dims = isl_space_alloc(ctx, nparam, 0, dim);
2595 if (!dims)
2596 return NULL;
2597
2598 set = isl_set_alloc_space(dims, n, flags);
2599 return set;
2600}
2601
2602/* Make sure "map" has room for at least "n" more basic maps.
2603 */
2604struct isl_map *isl_map_grow(struct isl_map *map, int n)
2605{
2606 int i;
2607 struct isl_map *grown = NULL;
2608
2609 if (!map)
2610 return NULL;
2611 isl_assert(map->ctx, n >= 0, goto error);
2612 if (map->n + n <= map->size)
2613 return map;
2614 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
2615 if (!grown)
2616 goto error;
2617 for (i = 0; i < map->n; ++i) {
2618 grown->p[i] = isl_basic_map_copy(map->p[i]);
2619 if (!grown->p[i])
2620 goto error;
2621 grown->n++;
2622 }
2623 isl_map_free(map);
2624 return grown;
2625error:
2626 isl_map_free(grown);
2627 isl_map_free(map);
2628 return NULL;
2629}
2630
2631/* Make sure "set" has room for at least "n" more basic sets.
2632 */
2633struct isl_set *isl_set_grow(struct isl_set *set, int n)
2634{
2635 return (struct isl_set *)isl_map_grow((struct isl_map *)set, n);
2636}
2637
2638struct isl_set *isl_set_dup(struct isl_set *set)
2639{
2640 int i;
2641 struct isl_set *dup;
2642
2643 if (!set)
2644 return NULL;
2645
2646 dup = isl_set_alloc_space(isl_space_copy(set->dim), set->n, set->flags);
2647 if (!dup)
2648 return NULL;
2649 for (i = 0; i < set->n; ++i)
2650 dup = isl_set_add_basic_set(dup, isl_basic_set_copy(set->p[i]));
2651 return dup;
2652}
2653
2654struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset)
2655{
2656 return isl_map_from_basic_map(bset);
2657}
2658
2659struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap)
2660{
2661 struct isl_map *map;
2662
2663 if (!bmap)
2664 return NULL;
2665
2666 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
2667 return isl_map_add_basic_map(map, bmap);
2668}
2669
2670__isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
2671 __isl_take isl_basic_set *bset)
2672{
2673 return (struct isl_set *)isl_map_add_basic_map((struct isl_map *)set,
2674 (struct isl_basic_map *)bset);
2675}
2676
2677__isl_null isl_set *isl_set_free(__isl_take isl_set *set)
2678{
2679 int i;
2680
2681 if (!set)
2682 return NULL;
2683
2684 if (--set->ref > 0)
2685 return NULL;
2686
2687 isl_ctx_deref(set->ctx);
2688 for (i = 0; i < set->n; ++i)
2689 isl_basic_set_free(set->p[i]);
2690 isl_space_free(set->dim);
2691 free(set);
2692
2693 return NULL;
2694}
2695
2696void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
2697{
2698 int i;
2699
2700 if (!set) {
2701 fprintf(out, "null set\n");
2702 return;
2703 }
2704
2705 fprintf(out, "%*s", indent, "");
2706 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
2707 set->ref, set->n, set->dim->nparam, set->dim->n_out,
2708 set->flags);
2709 for (i = 0; i < set->n; ++i) {
2710 fprintf(out, "%*s", indent, "");
2711 fprintf(out, "basic set %d:\n", i);
2712 isl_basic_set_print_internal(set->p[i], out, indent+4);
2713 }
2714}
2715
2716void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
2717{
2718 int i;
2719
2720 if (!map) {
2721 fprintf(out, "null map\n");
2722 return;
2723 }
2724
2725 fprintf(out, "%*s", indent, "");
2726 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
2727 "flags: %x, n_name: %d\n",
2728 map->ref, map->n, map->dim->nparam, map->dim->n_in,
2729 map->dim->n_out, map->flags, map->dim->n_id);
2730 for (i = 0; i < map->n; ++i) {
2731 fprintf(out, "%*s", indent, "");
2732 fprintf(out, "basic map %d:\n", i);
2733 isl_basic_map_print_internal(map->p[i], out, indent+4);
2734 }
2735}
2736
2737struct isl_basic_map *isl_basic_map_intersect_domain(
2738 struct isl_basic_map *bmap, struct isl_basic_set *bset)
2739{
2740 struct isl_basic_map *bmap_domain;
2741
2742 if (!bmap || !bset)
2743 goto error;
2744
2745 isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
2746 bset->dim, isl_dim_param), goto error);
2747
2748 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
2749 isl_assert(bset->ctx,
2750 isl_basic_map_compatible_domain(bmap, bset), goto error);
2751
2752 bmap = isl_basic_map_cow(bmap);
2753 if (!bmap)
2754 goto error;
2755 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
2756 bset->n_div, bset->n_eq, bset->n_ineq);
2757 bmap_domain = isl_basic_map_from_domain(bset);
2758 bmap = add_constraints(bmap, bmap_domain, 0, 0);
2759
2760 bmap = isl_basic_map_simplify(bmap);
2761 return isl_basic_map_finalize(bmap);
2762error:
2763 isl_basic_map_free(bmap);
2764 isl_basic_set_free(bset);
2765 return NULL;
2766}
2767
2768struct isl_basic_map *isl_basic_map_intersect_range(
2769 struct isl_basic_map *bmap, struct isl_basic_set *bset)
2770{
2771 struct isl_basic_map *bmap_range;
2772
2773 if (!bmap || !bset)
2774 goto error;
2775
2776 isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
2777 bset->dim, isl_dim_param), goto error);
2778
2779 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
2780 isl_assert(bset->ctx,
2781 isl_basic_map_compatible_range(bmap, bset), goto error);
2782
2783 if (isl_basic_set_is_universe(bset)) {
2784 isl_basic_set_free(bset);
2785 return bmap;
2786 }
2787
2788 bmap = isl_basic_map_cow(bmap);
2789 if (!bmap)
2790 goto error;
2791 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
2792 bset->n_div, bset->n_eq, bset->n_ineq);
2793 bmap_range = isl_basic_map_from_basic_set(bset, isl_space_copy(bset->dim));
2794 bmap = add_constraints(bmap, bmap_range, 0, 0);
2795
2796 bmap = isl_basic_map_simplify(bmap);
2797 return isl_basic_map_finalize(bmap);
2798error:
2799 isl_basic_map_free(bmap);
2800 isl_basic_set_free(bset);
2801 return NULL;
2802}
2803
2804int isl_basic_map_contains(struct isl_basic_map *bmap, struct isl_vec *vec)
2805{
2806 int i;
2807 unsigned total;
2808 isl_int s;
2809
2810 if (!bmap || !vec)
2811 return -1;
2812
2813 total = 1 + isl_basic_map_total_dim(bmap);
2814 if (total != vec->size)
2815 return -1;
2816
2817 isl_int_init(s);
2818
2819 for (i = 0; i < bmap->n_eq; ++i) {
2820 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
2821 if (!isl_int_is_zero(s)) {
2822 isl_int_clear(s);
2823 return 0;
2824 }
2825 }
2826
2827 for (i = 0; i < bmap->n_ineq; ++i) {
2828 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
2829 if (isl_int_is_neg(s)) {
2830 isl_int_clear(s);
2831 return 0;
2832 }
2833 }
2834
2835 isl_int_clear(s);
2836
2837 return 1;
2838}
2839
2840int isl_basic_set_contains(struct isl_basic_set *bset, struct isl_vec *vec)
2841{
2842 return isl_basic_map_contains((struct isl_basic_map *)bset, vec);
2843}
2844
2845struct isl_basic_map *isl_basic_map_intersect(
2846 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
2847{
2848 struct isl_vec *sample = NULL;
2849
2850 if (!bmap1 || !bmap2)
2851 goto error;
2852
2853 isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
2854 bmap2->dim, isl_dim_param), goto error);
2855 if (isl_space_dim(bmap1->dim, isl_dim_all) ==
2856 isl_space_dim(bmap1->dim, isl_dim_param) &&
2857 isl_space_dim(bmap2->dim, isl_dim_all) !=
2858 isl_space_dim(bmap2->dim, isl_dim_param))
2859 return isl_basic_map_intersect(bmap2, bmap1);
2860
2861 if (isl_space_dim(bmap2->dim, isl_dim_all) !=
2862 isl_space_dim(bmap2->dim, isl_dim_param))
2863 isl_assert(bmap1->ctx,
2864 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
2865
2866 if (bmap1->sample &&
2867 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
2868 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
2869 sample = isl_vec_copy(bmap1->sample);
2870 else if (bmap2->sample &&
2871 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
2872 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
2873 sample = isl_vec_copy(bmap2->sample);
2874
2875 bmap1 = isl_basic_map_cow(bmap1);
2876 if (!bmap1)
2877 goto error;
2878 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
2879 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
2880 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
2881
2882 if (!bmap1)
2883 isl_vec_free(sample);
2884 else if (sample) {
2885 isl_vec_free(bmap1->sample);
2886 bmap1->sample = sample;
2887 }
2888
2889 bmap1 = isl_basic_map_simplify(bmap1);
2890 return isl_basic_map_finalize(bmap1);
2891error:
2892 if (sample)
2893 isl_vec_free(sample);
2894 isl_basic_map_free(bmap1);
2895 isl_basic_map_free(bmap2);
2896 return NULL;
2897}
2898
2899struct isl_basic_set *isl_basic_set_intersect(
2900 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
2901{
2902 return (struct isl_basic_set *)
2903 isl_basic_map_intersect(
2904 (struct isl_basic_map *)bset1,
2905 (struct isl_basic_map *)bset2);
2906}
2907
2908__isl_give isl_basic_set *isl_basic_set_intersect_params(
2909 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
2910{
2911 return isl_basic_set_intersect(bset1, bset2);
2912}
2913
2914/* Special case of isl_map_intersect, where both map1 and map2
2915 * are convex, without any divs and such that either map1 or map2
2916 * contains a single constraint. This constraint is then simply
2917 * added to the other map.
2918 */
2919static __isl_give isl_map *map_intersect_add_constraint(
2920 __isl_take isl_map *map1, __isl_take isl_map *map2)
2921{
2922 isl_assert(map1->ctx, map1->n == 1, goto error);
2923 isl_assert(map2->ctx, map1->n == 1, goto error);
2924 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
2925 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
2926
2927 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
2928 return isl_map_intersect(map2, map1);
2929
2930 isl_assert(map2->ctx,
2931 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1, goto error);
2932
2933 map1 = isl_map_cow(map1);
2934 if (!map1)
2935 goto error;
2936 if (isl_map_plain_is_empty(map1)) {
2937 isl_map_free(map2);
2938 return map1;
2939 }
2940 map1->p[0] = isl_basic_map_cow(map1->p[0]);
2941 if (map2->p[0]->n_eq == 1)
2942 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
2943 else
2944 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
2945 map2->p[0]->ineq[0]);
2946
2947 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
2948 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
2949 if (!map1->p[0])
2950 goto error;
2951
2952 if (isl_basic_map_plain_is_empty(map1->p[0])) {
2953 isl_basic_map_free(map1->p[0]);
2954 map1->n = 0;
2955 }
2956
2957 isl_map_free(map2);
2958
2959 return map1;
2960error:
2961 isl_map_free(map1);
2962 isl_map_free(map2);
2963 return NULL;
2964}
2965
2966/* map2 may be either a parameter domain or a map living in the same
2967 * space as map1.
2968 */
2969static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
2970 __isl_take isl_map *map2)
2971{
2972 unsigned flags = 0;
2973 isl_map *result;
2974 int i, j;
2975
2976 if (!map1 || !map2)
2977 goto error;
2978
2979 if ((isl_map_plain_is_empty(map1) ||
2980 isl_map_plain_is_universe(map2)) &&
2981 isl_space_is_equal(map1->dim, map2->dim)) {
2982 isl_map_free(map2);
2983 return map1;
2984 }
2985 if ((isl_map_plain_is_empty(map2) ||
2986 isl_map_plain_is_universe(map1)) &&
2987 isl_space_is_equal(map1->dim, map2->dim)) {
2988 isl_map_free(map1);
2989 return map2;
2990 }
2991
2992 if (map1->n == 1 && map2->n == 1 &&
2993 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
2994 isl_space_is_equal(map1->dim, map2->dim) &&
2995 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
2996 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
2997 return map_intersect_add_constraint(map1, map2);
2998
2999 if (isl_space_dim(map2->dim, isl_dim_all) !=
3000 isl_space_dim(map2->dim, isl_dim_param))
3001 isl_assert(map1->ctx,
3002 isl_space_is_equal(map1->dim, map2->dim), goto error);
3003
3004 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3005 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3006 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3007
3008 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3009 map1->n * map2->n, flags);
3010 if (!result)
3011 goto error;
3012 for (i = 0; i < map1->n; ++i)
3013 for (j = 0; j < map2->n; ++j) {
3014 struct isl_basic_map *part;
3015 part = isl_basic_map_intersect(
3016 isl_basic_map_copy(map1->p[i]),
3017 isl_basic_map_copy(map2->p[j]));
3018 if (isl_basic_map_is_empty(part) < 0)
3019 part = isl_basic_map_free(part);
3020 result = isl_map_add_basic_map(result, part);
3021 if (!result)
3022 goto error;
3023 }
3024 isl_map_free(map1);
3025 isl_map_free(map2);
3026 return result;
3027error:
3028 isl_map_free(map1);
3029 isl_map_free(map2);
3030 return NULL;
3031}
3032
3033static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3034 __isl_take isl_map *map2)
3035{
3036 if (!map1 || !map2)
3037 goto error;
3038 if (!isl_space_is_equal(map1->dim, map2->dim))
3039 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3040 "spaces don't match", goto error);
3041 return map_intersect_internal(map1, map2);
3042error:
3043 isl_map_free(map1);
3044 isl_map_free(map2);
3045 return NULL;
3046}
3047
3048__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3049 __isl_take isl_map *map2)
3050{
3051 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3052}
3053
3054struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3055{
3056 return (struct isl_set *)
3057 isl_map_intersect((struct isl_map *)set1,
3058 (struct isl_map *)set2);
3059}
3060
3061/* map_intersect_internal accepts intersections
3062 * with parameter domains, so we can just call that function.
3063 */
3064static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3065 __isl_take isl_set *params)
3066{
3067 return map_intersect_internal(map, params);
3068}
3069
3070__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3071 __isl_take isl_map *map2)
3072{
3073 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3074}
3075
3076__isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3077 __isl_take isl_set *params)
3078{
3079 return isl_map_intersect_params(set, params);
3080}
3081
3082struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap)
3083{
3084 isl_space *dim;
3085 struct isl_basic_set *bset;
3086 unsigned in;
3087
3088 if (!bmap)
3089 return NULL;
3090 bmap = isl_basic_map_cow(bmap);
3091 if (!bmap)
3092 return NULL;
3093 dim = isl_space_reverse(isl_space_copy(bmap->dim));
3094 in = isl_basic_map_n_in(bmap);
3095 bset = isl_basic_set_from_basic_map(bmap);
3096 bset = isl_basic_set_swap_vars(bset, in);
3097 return isl_basic_map_from_basic_set(bset, dim);
3098}
3099
3100static __isl_give isl_basic_map *basic_map_space_reset(
3101 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3102{
3103 isl_space *space;
3104
3105 if (!bmap)
3106 return NULL;
3107 if (!isl_space_is_named_or_nested(bmap->dim, type))
3108 return bmap;
3109
3110 space = isl_basic_map_get_space(bmap);
3111 space = isl_space_reset(space, type);
3112 bmap = isl_basic_map_reset_space(bmap, space);
3113 return bmap;
3114}
3115
3116__isl_give isl_basic_map *isl_basic_map_insert_dims(
3117 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3118 unsigned pos, unsigned n)
3119{
3120 isl_space *res_dim;
3121 struct isl_basic_map *res;
3122 struct isl_dim_map *dim_map;
3123 unsigned total, off;
3124 enum isl_dim_type t;
3125
3126 if (n == 0)
3127 return basic_map_space_reset(bmap, type);
3128
3129 if (!bmap)
3130 return NULL;
3131
3132 res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n);
3133
3134 total = isl_basic_map_total_dim(bmap) + n;
3135 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3136 off = 0;
3137 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3138 if (t != type) {
3139 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3140 } else {
3141 unsigned size = isl_basic_map_dim(bmap, t);
3142 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3143 0, pos, off);
3144 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3145 pos, size - pos, off + pos + n);
3146 }
3147 off += isl_space_dim(res_dim, t);
3148 }
3149 isl_dim_map_div(dim_map, bmap, off);
3150
3151 res = isl_basic_map_alloc_space(res_dim,
3152 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3153 if (isl_basic_map_is_rational(bmap))
3154 res = isl_basic_map_set_rational(res);
3155 if (isl_basic_map_plain_is_empty(bmap)) {
3156 isl_basic_map_free(bmap);
3157 free(dim_map);
3158 return isl_basic_map_set_to_empty(res);
3159 }
3160 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3161 return isl_basic_map_finalize(res);
3162}
3163
3164__isl_give isl_basic_set *isl_basic_set_insert_dims(
3165 __isl_take isl_basic_set *bset,
3166 enum isl_dim_type type, unsigned pos, unsigned n)
3167{
3168 return isl_basic_map_insert_dims(bset, type, pos, n);
3169}
3170
3171__isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
3172 enum isl_dim_type type, unsigned n)
3173{
3174 if (!bmap)
3175 return NULL;
3176 return isl_basic_map_insert_dims(bmap, type,
3177 isl_basic_map_dim(bmap, type), n);
3178}
3179
3180__isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3181 enum isl_dim_type type, unsigned n)
3182{
3183 if (!bset)
3184 return NULL;
3185 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3186 return (isl_basic_set *)isl_basic_map_add((isl_basic_map *)bset, type, n);
3187error:
3188 isl_basic_set_free(bset);
3189 return NULL;
3190}
3191
3192static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3193 enum isl_dim_type type)
3194{
3195 isl_space *space;
3196
3197 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3198 return map;
3199
3200 space = isl_map_get_space(map);
3201 space = isl_space_reset(space, type);
3202 map = isl_map_reset_space(map, space);
3203 return map;
3204}
3205
3206__isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3207 enum isl_dim_type type, unsigned pos, unsigned n)
3208{
3209 int i;
3210
3211 if (n == 0)
3212 return map_space_reset(map, type);
3213
3214 map = isl_map_cow(map);
3215 if (!map)
3216 return NULL;
3217
3218 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3219 if (!map->dim)
3220 goto error;
3221
3222 for (i = 0; i < map->n; ++i) {
3223 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3224 if (!map->p[i])
3225 goto error;
3226 }
3227
3228 return map;
3229error:
3230 isl_map_free(map);
3231 return NULL;
3232}
3233
3234__isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3235 enum isl_dim_type type, unsigned pos, unsigned n)
3236{
3237 return isl_map_insert_dims(set, type, pos, n);
3238}
3239
3240__isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3241 enum isl_dim_type type, unsigned n)
3242{
3243 if (!map)
3244 return NULL;
3245 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3246}
3247
3248__isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3249 enum isl_dim_type type, unsigned n)
3250{
3251 if (!set)
3252 return NULL;
3253 isl_assert(set->ctx, type != isl_dim_in, goto error);
3254 return (isl_set *)isl_map_add_dims((isl_map *)set, type, n);
3255error:
3256 isl_set_free(set);
3257 return NULL;
3258}
3259
3260__isl_give isl_basic_map *isl_basic_map_move_dims(
3261 __isl_take isl_basic_map *bmap,
3262 enum isl_dim_type dst_type, unsigned dst_pos,
3263 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3264{
3265 struct isl_dim_map *dim_map;
3266 struct isl_basic_map *res;
3267 enum isl_dim_type t;
3268 unsigned total, off;
3269
3270 if (!bmap)
3271 return NULL;
3272 if (n == 0)
3273 return bmap;
3274
3275 isl_assert(bmap->ctx, src_pos + n <= isl_basic_map_dim(bmap, src_type),
3276 goto error);
3277
3278 if (dst_type == src_type && dst_pos == src_pos)
3279 return bmap;
3280
3281 isl_assert(bmap->ctx, dst_type != src_type, goto error);
3282
3283 if (pos(bmap->dim, dst_type) + dst_pos ==
3284 pos(bmap->dim, src_type) + src_pos +
3285 ((src_type < dst_type) ? n : 0)) {
3286 bmap = isl_basic_map_cow(bmap);
3287 if (!bmap)
3288 return NULL;
3289
3290 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3291 src_type, src_pos, n);
3292 if (!bmap->dim)
3293 goto error;
3294
3295 bmap = isl_basic_map_finalize(bmap);
3296
3297 return bmap;
3298 }
3299
3300 total = isl_basic_map_total_dim(bmap);
3301 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3302
3303 off = 0;
3304 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3305 unsigned size = isl_space_dim(bmap->dim, t);
3306 if (t == dst_type) {
3307 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3308 0, dst_pos, off);
3309 off += dst_pos;
3310 isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
3311 src_pos, n, off);
3312 off += n;
3313 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3314 dst_pos, size - dst_pos, off);
3315 off += size - dst_pos;
3316 } else if (t == src_type) {
3317 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3318 0, src_pos, off);
3319 off += src_pos;
3320 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3321 src_pos + n, size - src_pos - n, off);
3322 off += size - src_pos - n;
3323 } else {
3324 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3325 off += size;
3326 }
3327 }
3328 isl_dim_map_div(dim_map, bmap, off);
3329
3330 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3331 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3332 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3333 if (!bmap)
3334 goto error;
3335
3336 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3337 src_type, src_pos, n);
3338 if (!bmap->dim)
3339 goto error;
3340
3341 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
3342 bmap = isl_basic_map_gauss(bmap, NULL);
3343 bmap = isl_basic_map_finalize(bmap);
3344
3345 return bmap;
3346error:
3347 isl_basic_map_free(bmap);
3348 return NULL;
3349}
3350
3351__isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
3352 enum isl_dim_type dst_type, unsigned dst_pos,
3353 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3354{
3355 return (isl_basic_set *)isl_basic_map_move_dims(
3356 (isl_basic_map *)bset, dst_type, dst_pos, src_type, src_pos, n);
3357}
3358
3359__isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
3360 enum isl_dim_type dst_type, unsigned dst_pos,
3361 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3362{
3363 if (!set)
3364 return NULL;
3365 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
3366 return (isl_set *)isl_map_move_dims((isl_map *)set, dst_type, dst_pos,
3367 src_type, src_pos, n);
3368error:
3369 isl_set_free(set);
3370 return NULL;
3371}
3372
3373__isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
3374 enum isl_dim_type dst_type, unsigned dst_pos,
3375 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3376{
3377 int i;
3378
3379 if (!map)
3380 return NULL;
3381 if (n == 0)
3382 return map;
3383
3384 isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type),
3385 goto error);
3386
3387 if (dst_type == src_type && dst_pos == src_pos)
3388 return map;
3389
3390 isl_assert(map->ctx, dst_type != src_type, goto error);
3391
3392 map = isl_map_cow(map);
3393 if (!map)
3394 return NULL;
3395
3396 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
3397 if (!map->dim)
3398 goto error;
3399
3400 for (i = 0; i < map->n; ++i) {
3401 map->p[i] = isl_basic_map_move_dims(map->p[i],
3402 dst_type, dst_pos,
3403 src_type, src_pos, n);
3404 if (!map->p[i])
3405 goto error;
3406 }
3407
3408 return map;
3409error:
3410 isl_map_free(map);
3411 return NULL;
3412}
3413
3414/* Move the specified dimensions to the last columns right before
3415 * the divs. Don't change the dimension specification of bmap.
3416 * That's the responsibility of the caller.
3417 */
3418static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
3419 enum isl_dim_type type, unsigned first, unsigned n)
3420{
3421 struct isl_dim_map *dim_map;
3422 struct isl_basic_map *res;
3423 enum isl_dim_type t;
3424 unsigned total, off;
3425
3426 if (!bmap)
3427 return NULL;
3428 if (pos(bmap->dim, type) + first + n ==
3429 1 + isl_space_dim(bmap->dim, isl_dim_all))
3430 return bmap;
3431
3432 total = isl_basic_map_total_dim(bmap);
3433 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3434
3435 off = 0;
3436 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3437 unsigned size = isl_space_dim(bmap->dim, t);
3438 if (t == type) {
3439 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3440 0, first, off);
3441 off += first;
3442 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3443 first, n, total - bmap->n_div - n);
3444 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3445 first + n, size - (first + n), off);
3446 off += size - (first + n);
3447 } else {
3448 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3449 off += size;
3450 }
3451 }
3452 isl_dim_map_div(dim_map, bmap, off + n);
3453
3454 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3455 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3456 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3457 return res;
3458}
3459
3460/* Insert "n" rows in the divs of "bmap".
3461 *
3462 * The number of columns is not changed, which means that the last
3463 * dimensions of "bmap" are being reintepreted as the new divs.
3464 * The space of "bmap" is not adjusted, however, which means
3465 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
3466 * from the space of "bmap" is the responsibility of the caller.
3467 */
3468static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
3469 int n)
3470{
3471 int i;
3472 size_t row_size;
3473 isl_int **new_div;
3474 isl_int *old;
3475
3476 bmap = isl_basic_map_cow(bmap);
3477 if (!bmap)
3478 return NULL;
3479
3480 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
3481 old = bmap->block2.data;
3482 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
3483 (bmap->extra + n) * (1 + row_size));
3484 if (!bmap->block2.data)
3485 return isl_basic_map_free(bmap);
3486 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
3487 if (!new_div)
3488 return isl_basic_map_free(bmap);
3489 for (i = 0; i < n; ++i) {
3490 new_div[i] = bmap->block2.data +
3491 (bmap->extra + i) * (1 + row_size);
3492 isl_seq_clr(new_div[i], 1 + row_size);
3493 }
3494 for (i = 0; i < bmap->extra; ++i)
3495 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
3496 free(bmap->div);
3497 bmap->div = new_div;
3498 bmap->n_div += n;
3499 bmap->extra += n;
3500
3501 return bmap;
3502}
3503
3504/* Turn the n dimensions of type type, starting at first
3505 * into existentially quantified variables.
3506 */
3507__isl_give isl_basic_map *isl_basic_map_project_out(
3508 __isl_take isl_basic_map *bmap,
3509 enum isl_dim_type type, unsigned first, unsigned n)
3510{
3511 if (n == 0)
3512 return basic_map_space_reset(bmap, type);
3513
3514 if (!bmap)
3515 return NULL;
3516
3517 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
3518 return isl_basic_map_remove_dims(bmap, type, first, n);
3519
3520 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
3521 goto error);
3522
3523 bmap = move_last(bmap, type, first, n);
3524 bmap = isl_basic_map_cow(bmap);
3525 bmap = insert_div_rows(bmap, n);
3526 if (!bmap)
3527 return NULL;
3528
3529 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
3530 if (!bmap->dim)
3531 goto error;
3532 bmap = isl_basic_map_simplify(bmap);
3533 bmap = isl_basic_map_drop_redundant_divs(bmap);
3534 return isl_basic_map_finalize(bmap);
3535error:
3536 isl_basic_map_free(bmap);
3537 return NULL;
3538}
3539
3540/* Turn the n dimensions of type type, starting at first
3541 * into existentially quantified variables.
3542 */
3543struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
3544 enum isl_dim_type type, unsigned first, unsigned n)
3545{
3546 return (isl_basic_set *)isl_basic_map_project_out(
3547 (isl_basic_map *)bset, type, first, n);
3548}
3549
3550/* Turn the n dimensions of type type, starting at first
3551 * into existentially quantified variables.
3552 */
3553__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
3554 enum isl_dim_type type, unsigned first, unsigned n)
3555{
3556 int i;
3557
3558 if (!map)
3559 return NULL;
3560
3561 if (n == 0)
3562 return map_space_reset(map, type);
3563
3564 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
3565
3566 map = isl_map_cow(map);
3567 if (!map)
3568 return NULL;
3569
3570 map->dim = isl_space_drop_dims(map->dim, type, first, n);
3571 if (!map->dim)
3572 goto error;
3573
3574 for (i = 0; i < map->n; ++i) {
3575 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
3576 if (!map->p[i])
3577 goto error;
3578 }
3579
3580 return map;
3581error:
3582 isl_map_free(map);
3583 return NULL;
3584}
3585
3586/* Turn the n dimensions of type type, starting at first
3587 * into existentially quantified variables.
3588 */
3589__isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
3590 enum isl_dim_type type, unsigned first, unsigned n)
3591{
3592 return (isl_set *)isl_map_project_out((isl_map *)set, type, first, n);
3593}
3594
3595static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
3596{
3597 int i, j;
3598
3599 for (i = 0; i < n; ++i) {
3600 j = isl_basic_map_alloc_div(bmap);
3601 if (j < 0)
3602 goto error;
3603 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
3604 }
3605 return bmap;
3606error:
3607 isl_basic_map_free(bmap);
3608 return NULL;
3609}
3610
3611struct isl_basic_map *isl_basic_map_apply_range(
3612 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3613{
3614 isl_space *dim_result = NULL;
3615 struct isl_basic_map *bmap;
3616 unsigned n_in, n_out, n, nparam, total, pos;
3617 struct isl_dim_map *dim_map1, *dim_map2;
3618
3619 if (!bmap1 || !bmap2)
3620 goto error;
3621 if (!isl_space_match(bmap1->dim, isl_dim_param,
3622 bmap2->dim, isl_dim_param))
3623 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
3624 "parameters don't match", goto error);
3625 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
3626 bmap2->dim, isl_dim_in))
3627 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
3628 "spaces don't match", goto error);
3629
3630 dim_result = isl_space_join(isl_space_copy(bmap1->dim),
3631 isl_space_copy(bmap2->dim));
3632
3633 n_in = isl_basic_map_n_in(bmap1);
3634 n_out = isl_basic_map_n_out(bmap2);
3635 n = isl_basic_map_n_out(bmap1);
3636 nparam = isl_basic_map_n_param(bmap1);
3637
3638 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
3639 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
3640 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
3641 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
3642 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
3643 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
3644 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
3645 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
3646 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
3647 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
3648 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
3649
3650 bmap = isl_basic_map_alloc_space(dim_result,
3651 bmap1->n_div + bmap2->n_div + n,
3652 bmap1->n_eq + bmap2->n_eq,
3653 bmap1->n_ineq + bmap2->n_ineq);
3654 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
3655 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
3656 bmap = add_divs(bmap, n);
3657 bmap = isl_basic_map_simplify(bmap);
3658 bmap = isl_basic_map_drop_redundant_divs(bmap);
3659 return isl_basic_map_finalize(bmap);
3660error:
3661 isl_basic_map_free(bmap1);
3662 isl_basic_map_free(bmap2);
3663 return NULL;
3664}
3665
3666struct isl_basic_set *isl_basic_set_apply(
3667 struct isl_basic_set *bset, struct isl_basic_map *bmap)
3668{
3669 if (!bset || !bmap)
3670 goto error;
3671
3672 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
3673 goto error);
3674
3675 return (struct isl_basic_set *)
3676 isl_basic_map_apply_range((struct isl_basic_map *)bset, bmap);
3677error:
3678 isl_basic_set_free(bset);
3679 isl_basic_map_free(bmap);
3680 return NULL;
3681}
3682
3683struct isl_basic_map *isl_basic_map_apply_domain(
3684 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3685{
3686 if (!bmap1 || !bmap2)
3687 goto error;
3688
3689 isl_assert(bmap1->ctx,
3690 isl_basic_map_n_in(bmap1) == isl_basic_map_n_in(bmap2), goto error);
3691 isl_assert(bmap1->ctx,
3692 isl_basic_map_n_param(bmap1) == isl_basic_map_n_param(bmap2),
3693 goto error);
3694
3695 bmap1 = isl_basic_map_reverse(bmap1);
3696 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
3697 return isl_basic_map_reverse(bmap1);
3698error:
3699 isl_basic_map_free(bmap1);
3700 isl_basic_map_free(bmap2);
3701 return NULL;
3702}
3703
3704/* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
3705 * A \cap B -> f(A) + f(B)
3706 */
3707struct isl_basic_map *isl_basic_map_sum(
3708 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3709{
3710 unsigned n_in, n_out, nparam, total, pos;
3711 struct isl_basic_map *bmap = NULL;
3712 struct isl_dim_map *dim_map1, *dim_map2;
3713 int i;
3714
3715 if (!bmap1 || !bmap2)
3716 goto error;
3717
3718 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
3719 goto error);
3720
3721 nparam = isl_basic_map_n_param(bmap1);
3722 n_in = isl_basic_map_n_in(bmap1);
3723 n_out = isl_basic_map_n_out(bmap1);
3724
3725 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
3726 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
3727 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
3728 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
3729 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
3730 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
3731 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
3732 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
3733 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
3734 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
3735 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
3736
3737 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
3738 bmap1->n_div + bmap2->n_div + 2 * n_out,
3739 bmap1->n_eq + bmap2->n_eq + n_out,
3740 bmap1->n_ineq + bmap2->n_ineq);
3741 for (i = 0; i < n_out; ++i) {
3742 int j = isl_basic_map_alloc_equality(bmap);
3743 if (j < 0)
3744 goto error;
3745 isl_seq_clr(bmap->eq[j], 1+total);
3746 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
3747 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
3748 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
3749 }
3750 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
3751 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
3752 bmap = add_divs(bmap, 2 * n_out);
3753
3754 bmap = isl_basic_map_simplify(bmap);
3755 return isl_basic_map_finalize(bmap);
3756error:
3757 isl_basic_map_free(bmap);
3758 isl_basic_map_free(bmap1);
3759 isl_basic_map_free(bmap2);
3760 return NULL;
3761}
3762
3763/* Given two maps A -> f(A) and B -> g(B), construct a map
3764 * A \cap B -> f(A) + f(B)
3765 */
3766struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2)
3767{
3768 struct isl_map *result;
3769 int i, j;
3770
3771 if (!map1 || !map2)
3772 goto error;
3773
3774 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
3775
3776 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3777 map1->n * map2->n, 0);
3778 if (!result)
3779 goto error;
3780 for (i = 0; i < map1->n; ++i)
3781 for (j = 0; j < map2->n; ++j) {
3782 struct isl_basic_map *part;
3783 part = isl_basic_map_sum(
3784 isl_basic_map_copy(map1->p[i]),
3785 isl_basic_map_copy(map2->p[j]));
3786 if (isl_basic_map_is_empty(part))
3787 isl_basic_map_free(part);
3788 else
3789 result = isl_map_add_basic_map(result, part);
3790 if (!result)
3791 goto error;
3792 }
3793 isl_map_free(map1);
3794 isl_map_free(map2);
3795 return result;
3796error:
3797 isl_map_free(map1);
3798 isl_map_free(map2);
3799 return NULL;
3800}
3801
3802__isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
3803 __isl_take isl_set *set2)
3804{
3805 return (isl_set *)isl_map_sum((isl_map *)set1, (isl_map *)set2);
3806}
3807
3808/* Given a basic map A -> f(A), construct A -> -f(A).
3809 */
3810struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap)
3811{
3812 int i, j;
3813 unsigned off, n;
3814
3815 bmap = isl_basic_map_cow(bmap);
3816 if (!bmap)
3817 return NULL;
3818
3819 n = isl_basic_map_dim(bmap, isl_dim_out);
3820 off = isl_basic_map_offset(bmap, isl_dim_out);
3821 for (i = 0; i < bmap->n_eq; ++i)
3822 for (j = 0; j < n; ++j)
3823 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
3824 for (i = 0; i < bmap->n_ineq; ++i)
3825 for (j = 0; j < n; ++j)
3826 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
3827 for (i = 0; i < bmap->n_div; ++i)
3828 for (j = 0; j < n; ++j)
3829 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
3830 bmap = isl_basic_map_gauss(bmap, NULL);
3831 return isl_basic_map_finalize(bmap);
3832}
3833
3834__isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
3835{
3836 return isl_basic_map_neg(bset);
3837}
3838
3839/* Given a map A -> f(A), construct A -> -f(A).
3840 */
3841struct isl_map *isl_map_neg(struct isl_map *map)
3842{
3843 int i;
3844
3845 map = isl_map_cow(map);
3846 if (!map)
3847 return NULL;
3848
3849 for (i = 0; i < map->n; ++i) {
3850 map->p[i] = isl_basic_map_neg(map->p[i]);
3851 if (!map->p[i])
3852 goto error;
3853 }
3854
3855 return map;
3856error:
3857 isl_map_free(map);
3858 return NULL;
3859}
3860
3861__isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
3862{
3863 return (isl_set *)isl_map_neg((isl_map *)set);
3864}
3865
3866/* Given a basic map A -> f(A) and an integer d, construct a basic map
3867 * A -> floor(f(A)/d).
3868 */
3869struct isl_basic_map *isl_basic_map_floordiv(struct isl_basic_map *bmap,
3870 isl_int d)
3871{
3872 unsigned n_in, n_out, nparam, total, pos;
3873 struct isl_basic_map *result = NULL;
3874 struct isl_dim_map *dim_map;
3875 int i;
3876
3877 if (!bmap)
3878 return NULL;
3879
3880 nparam = isl_basic_map_n_param(bmap);
3881 n_in = isl_basic_map_n_in(bmap);
3882 n_out = isl_basic_map_n_out(bmap);
3883
3884 total = nparam + n_in + n_out + bmap->n_div + n_out;
3885 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3886 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
3887 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
3888 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
3889 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
3890
3891 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
3892 bmap->n_div + n_out,
3893 bmap->n_eq, bmap->n_ineq + 2 * n_out);
3894 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
3895 result = add_divs(result, n_out);
3896 for (i = 0; i < n_out; ++i) {
3897 int j;
3898 j = isl_basic_map_alloc_inequality(result);
3899 if (j < 0)
3900 goto error;
3901 isl_seq_clr(result->ineq[j], 1+total);
3902 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
3903 isl_int_set_si(result->ineq[j][1+pos+i], 1);
3904 j = isl_basic_map_alloc_inequality(result);
3905 if (j < 0)
3906 goto error;
3907 isl_seq_clr(result->ineq[j], 1+total);
3908 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
3909 isl_int_set_si(result->ineq[j][1+pos+i], -1);
3910 isl_int_sub_ui(result->ineq[j][0], d, 1);
3911 }
3912
3913 result = isl_basic_map_simplify(result);
3914 return isl_basic_map_finalize(result);
3915error:
3916 isl_basic_map_free(result);
3917 return NULL;
3918}
3919
3920/* Given a map A -> f(A) and an integer d, construct a map
3921 * A -> floor(f(A)/d).
3922 */
3923struct isl_map *isl_map_floordiv(struct isl_map *map, isl_int d)
3924{
3925 int i;
3926
3927 map = isl_map_cow(map);
3928 if (!map)
3929 return NULL;
3930
3931 ISL_F_CLR(map, ISL_MAP_DISJOINT);
3932 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
3933 for (i = 0; i < map->n; ++i) {
3934 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
3935 if (!map->p[i])
3936 goto error;
3937 }
3938
3939 return map;
3940error:
3941 isl_map_free(map);
3942 return NULL;
3943}
3944
3945/* Given a map A -> f(A) and an integer d, construct a map
3946 * A -> floor(f(A)/d).
3947 */
3948__isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
3949 __isl_take isl_val *d)
3950{
3951 if (!map || !d)
3952 goto error;
3953 if (!isl_val_is_int(d))
3954 isl_die(isl_val_get_ctx(d), isl_error_invalid,
3955 "expecting integer denominator", goto error);
3956 map = isl_map_floordiv(map, d->n);
3957 isl_val_free(d);
3958 return map;
3959error:
3960 isl_map_free(map);
3961 isl_val_free(d);
3962 return NULL;
3963}
3964
3965static struct isl_basic_map *var_equal(struct isl_basic_map *bmap, unsigned pos)
3966{
3967 int i;
3968 unsigned nparam;
3969 unsigned n_in;
3970
3971 i = isl_basic_map_alloc_equality(bmap);
3972 if (i < 0)
3973 goto error;
3974 nparam = isl_basic_map_n_param(bmap);
3975 n_in = isl_basic_map_n_in(bmap);
3976 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
3977 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
3978 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
3979 return isl_basic_map_finalize(bmap);
3980error:
3981 isl_basic_map_free(bmap);
3982 return NULL;
3983}
3984
3985/* Add a constraints to "bmap" expressing i_pos < o_pos
3986 */
3987static struct isl_basic_map *var_less(struct isl_basic_map *bmap, unsigned pos)
3988{
3989 int i;
3990 unsigned nparam;
3991 unsigned n_in;
3992
3993 i = isl_basic_map_alloc_inequality(bmap);
3994 if (i < 0)
3995 goto error;
3996 nparam = isl_basic_map_n_param(bmap);
3997 n_in = isl_basic_map_n_in(bmap);
3998 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
3999 isl_int_set_si(bmap->ineq[i][0], -1);
4000 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4001 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4002 return isl_basic_map_finalize(bmap);
4003error:
4004 isl_basic_map_free(bmap);
4005 return NULL;
4006}
4007
4008/* Add a constraint to "bmap" expressing i_pos <= o_pos
4009 */
4010static __isl_give isl_basic_map *var_less_or_equal(
4011 __isl_take isl_basic_map *bmap, unsigned pos)
4012{
4013 int i;
4014 unsigned nparam;
4015 unsigned n_in;
4016
4017 i = isl_basic_map_alloc_inequality(bmap);
4018 if (i < 0)
4019 goto error;
4020 nparam = isl_basic_map_n_param(bmap);
4021 n_in = isl_basic_map_n_in(bmap);
4022 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4023 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4024 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4025 return isl_basic_map_finalize(bmap);
4026error:
4027 isl_basic_map_free(bmap);
4028 return NULL;
4029}
4030
4031/* Add a constraints to "bmap" expressing i_pos > o_pos
4032 */
4033static struct isl_basic_map *var_more(struct isl_basic_map *bmap, unsigned pos)
4034{
4035 int i;
4036 unsigned nparam;
4037 unsigned n_in;
4038
4039 i = isl_basic_map_alloc_inequality(bmap);
4040 if (i < 0)
4041 goto error;
4042 nparam = isl_basic_map_n_param(bmap);
4043 n_in = isl_basic_map_n_in(bmap);
4044 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4045 isl_int_set_si(bmap->ineq[i][0], -1);
4046 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4047 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4048 return isl_basic_map_finalize(bmap);
4049error:
4050 isl_basic_map_free(bmap);
4051 return NULL;
4052}
4053
4054/* Add a constraint to "bmap" expressing i_pos >= o_pos
4055 */
4056static __isl_give isl_basic_map *var_more_or_equal(
4057 __isl_take isl_basic_map *bmap, unsigned pos)
4058{
4059 int i;
4060 unsigned nparam;
4061 unsigned n_in;
4062
4063 i = isl_basic_map_alloc_inequality(bmap);
4064 if (i < 0)
4065 goto error;
4066 nparam = isl_basic_map_n_param(bmap);
4067 n_in = isl_basic_map_n_in(bmap);
4068 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4069 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4070 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4071 return isl_basic_map_finalize(bmap);
4072error:
4073 isl_basic_map_free(bmap);
4074 return NULL;
4075}
4076
4077__isl_give isl_basic_map *isl_basic_map_equal(
4078 __isl_take isl_space *dim, unsigned n_equal)
4079{
4080 int i;
4081 struct isl_basic_map *bmap;
4082 bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
4083 if (!bmap)
4084 return NULL;
4085 for (i = 0; i < n_equal && bmap; ++i)
4086 bmap = var_equal(bmap, i);
4087 return isl_basic_map_finalize(bmap);
4088}
4089
4090/* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
4091 */
4092__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
4093 unsigned pos)
4094{
4095 int i;
4096 struct isl_basic_map *bmap;
4097 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4098 if (!bmap)
4099 return NULL;
4100 for (i = 0; i < pos && bmap; ++i)
4101 bmap = var_equal(bmap, i);
4102 if (bmap)
4103 bmap = var_less(bmap, pos);
4104 return isl_basic_map_finalize(bmap);
4105}
4106
4107/* Return a relation on of dimension "dim" expressing i_[0..pos] <<= o_[0..pos]
4108 */
4109__isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4110 __isl_take isl_space *dim, unsigned pos)
4111{
4112 int i;
4113 isl_basic_map *bmap;
4114
4115 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4116 for (i = 0; i < pos; ++i)
4117 bmap = var_equal(bmap, i);
4118 bmap = var_less_or_equal(bmap, pos);
4119 return isl_basic_map_finalize(bmap);
4120}
4121
4122/* Return a relation on pairs of sets of dimension "dim" expressing i_pos > o_pos
4123 */
4124__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
4125 unsigned pos)
4126{
4127 int i;
4128 struct isl_basic_map *bmap;
4129 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4130 if (!bmap)
4131 return NULL;
4132 for (i = 0; i < pos && bmap; ++i)
4133 bmap = var_equal(bmap, i);
4134 if (bmap)
4135 bmap = var_more(bmap, pos);
4136 return isl_basic_map_finalize(bmap);
4137}
4138
4139/* Return a relation on of dimension "dim" expressing i_[0..pos] >>= o_[0..pos]
4140 */
4141__isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4142 __isl_take isl_space *dim, unsigned pos)
4143{
4144 int i;
4145 isl_basic_map *bmap;
4146
4147 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4148 for (i = 0; i < pos; ++i)
4149 bmap = var_equal(bmap, i);
4150 bmap = var_more_or_equal(bmap, pos);
4151 return isl_basic_map_finalize(bmap);
4152}
4153
4154static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
4155 unsigned n, int equal)
4156{
4157 struct isl_map *map;
4158 int i;
4159
4160 if (n == 0 && equal)
4161 return isl_map_universe(dims);
4162
4163 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4164
4165 for (i = 0; i + 1 < n; ++i)
4166 map = isl_map_add_basic_map(map,
4167 isl_basic_map_less_at(isl_space_copy(dims), i));
4168 if (n > 0) {
4169 if (equal)
4170 map = isl_map_add_basic_map(map,
4171 isl_basic_map_less_or_equal_at(dims, n - 1));
4172 else
4173 map = isl_map_add_basic_map(map,
4174 isl_basic_map_less_at(dims, n - 1));
4175 } else
4176 isl_space_free(dims);
4177
4178 return map;
4179}
4180
4181static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
4182{
4183 if (!dims)
4184 return NULL;
4185 return map_lex_lte_first(dims, dims->n_out, equal);
4186}
4187
4188__isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
4189{
4190 return map_lex_lte_first(dim, n, 0);
4191}
4192
4193__isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
4194{
4195 return map_lex_lte_first(dim, n, 1);
4196}
4197
4198__isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
4199{
4200 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
4201}
4202
4203__isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
4204{
4205 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
4206}
4207
4208static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
4209 unsigned n, int equal)
4210{
4211 struct isl_map *map;
4212 int i;
4213
4214 if (n == 0 && equal)
4215 return isl_map_universe(dims);
4216
4217 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4218
4219 for (i = 0; i + 1 < n; ++i)
4220 map = isl_map_add_basic_map(map,
4221 isl_basic_map_more_at(isl_space_copy(dims), i));
4222 if (n > 0) {
4223 if (equal)
4224 map = isl_map_add_basic_map(map,
4225 isl_basic_map_more_or_equal_at(dims, n - 1));
4226 else
4227 map = isl_map_add_basic_map(map,
4228 isl_basic_map_more_at(dims, n - 1));
4229 } else
4230 isl_space_free(dims);
4231
4232 return map;
4233}
4234
4235static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
4236{
4237 if (!dims)
4238 return NULL;
4239 return map_lex_gte_first(dims, dims->n_out, equal);
4240}
4241
4242__isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
4243{
4244 return map_lex_gte_first(dim, n, 0);
4245}
4246
4247__isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
4248{
4249 return map_lex_gte_first(dim, n, 1);
4250}
4251
4252__isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
4253{
4254 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
4255}
4256
4257__isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
4258{
4259 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
4260}
4261
4262__isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
4263 __isl_take isl_set *set2)
4264{
4265 isl_map *map;
4266 map = isl_map_lex_le(isl_set_get_space(set1));
4267 map = isl_map_intersect_domain(map, set1);
4268 map = isl_map_intersect_range(map, set2);
4269 return map;
4270}
4271
4272__isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
4273 __isl_take isl_set *set2)
4274{
4275 isl_map *map;
4276 map = isl_map_lex_lt(isl_set_get_space(set1));
4277 map = isl_map_intersect_domain(map, set1);
4278 map = isl_map_intersect_range(map, set2);
4279 return map;
4280}
4281
4282__isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
4283 __isl_take isl_set *set2)
4284{
4285 isl_map *map;
4286 map = isl_map_lex_ge(isl_set_get_space(set1));
4287 map = isl_map_intersect_domain(map, set1);
4288 map = isl_map_intersect_range(map, set2);
4289 return map;
4290}
4291
4292__isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
4293 __isl_take isl_set *set2)
4294{
4295 isl_map *map;
4296 map = isl_map_lex_gt(isl_set_get_space(set1));
4297 map = isl_map_intersect_domain(map, set1);
4298 map = isl_map_intersect_range(map, set2);
4299 return map;
4300}
4301
4302__isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
4303 __isl_take isl_map *map2)
4304{
4305 isl_map *map;
4306 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
4307 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4308 map = isl_map_apply_range(map, isl_map_reverse(map2));
4309 return map;
4310}
4311
4312__isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
4313 __isl_take isl_map *map2)
4314{
4315 isl_map *map;
4316 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
4317 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4318 map = isl_map_apply_range(map, isl_map_reverse(map2));
4319 return map;
4320}
4321
4322__isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
4323 __isl_take isl_map *map2)
4324{
4325 isl_map *map;
4326 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
4327 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4328 map = isl_map_apply_range(map, isl_map_reverse(map2));
4329 return map;
4330}
4331
4332__isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
4333 __isl_take isl_map *map2)
4334{
4335 isl_map *map;
4336 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
4337 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4338 map = isl_map_apply_range(map, isl_map_reverse(map2));
4339 return map;
4340}
4341
4342__isl_give isl_basic_map *isl_basic_map_from_basic_set(
4343 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
4344{
4345 struct isl_basic_map *bmap;
4346
4347 bset = isl_basic_set_cow(bset);
4348 if (!bset || !dim)
4349 goto error;
4350
4351 isl_assert(bset->ctx, isl_space_compatible(bset->dim, dim), goto error);
4352 isl_space_free(bset->dim);
4353 bmap = (struct isl_basic_map *) bset;
4354 bmap->dim = dim;
4355 return isl_basic_map_finalize(bmap);
4356error:
4357 isl_basic_set_free(bset);
4358 isl_space_free(dim);
4359 return NULL;
4360}
4361
4362struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap)
4363{
4364 if (!bmap)
4365 goto error;
4366 if (bmap->dim->n_in == 0)
4367 return (struct isl_basic_set *)bmap;
4368 bmap = isl_basic_map_cow(bmap);
4369 if (!bmap)
4370 goto error;
4371 bmap->dim = isl_space_as_set_space(bmap->dim);
4372 if (!bmap->dim)
4373 goto error;
4374 bmap = isl_basic_map_finalize(bmap);
4375 return (struct isl_basic_set *)bmap;
4376error:
4377 isl_basic_map_free(bmap);
4378 return NULL;
4379}
4380
4381/* For a div d = floor(f/m), add the constraint
4382 *
4383 * f - m d >= 0
4384 */
4385static int add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
4386 unsigned pos, isl_int *div)
4387{
4388 int i;
4389 unsigned total = isl_basic_map_total_dim(bmap);
4390
4391 i = isl_basic_map_alloc_inequality(bmap);
4392 if (i < 0)
4393 return -1;
4394 isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
4395 isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
4396
4397 return 0;
4398}
4399
4400/* For a div d = floor(f/m), add the constraint
4401 *
4402 * -(f-(n-1)) + m d >= 0
4403 */
4404static int add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
4405 unsigned pos, isl_int *div)
4406{
4407 int i;
4408 unsigned total = isl_basic_map_total_dim(bmap);
4409
4410 i = isl_basic_map_alloc_inequality(bmap);
4411 if (i < 0)
4412 return -1;
4413 isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
4414 isl_int_set(bmap->ineq[i][1 + pos], div[0]);
4415 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
4416 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
4417
4418 return 0;
4419}
4420
4421/* For a div d = floor(f/m), add the constraints
4422 *
4423 * f - m d >= 0
4424 * -(f-(n-1)) + m d >= 0
4425 *
4426 * Note that the second constraint is the negation of
4427 *
4428 * f - m d >= n
4429 */
4430int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
4431 unsigned pos, isl_int *div)
4432{
4433 if (add_upper_div_constraint(bmap, pos, div) < 0)
4434 return -1;
4435 if (add_lower_div_constraint(bmap, pos, div) < 0)
4436 return -1;
4437 return 0;
4438}
4439
4440int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
4441 unsigned pos, isl_int *div)
4442{
4443 return isl_basic_map_add_div_constraints_var((isl_basic_map *)bset,
4444 pos, div);
4445}
4446
4447int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
4448{
4449 unsigned total = isl_basic_map_total_dim(bmap);
4450 unsigned div_pos = total - bmap->n_div + div;
4451
4452 return isl_basic_map_add_div_constraints_var(bmap, div_pos,
4453 bmap->div[div]);
4454}
4455
4456/* For each known div d = floor(f/m), add the constraints
4457 *
4458 * f - m d >= 0
4459 * -(f-(n-1)) + m d >= 0
4460 */
4461__isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
4462 __isl_take isl_basic_map *bmap)
4463{
4464 int i;
4465 unsigned n_div;
4466
4467 if (!bmap)
4468 return NULL;
4469 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4470 if (n_div == 0)
4471 return bmap;
4472 bmap = isl_basic_map_cow(bmap);
4473 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
4474 if (!bmap)
4475 return NULL;
4476 for (i = 0; i < n_div; ++i) {
4477 if (isl_int_is_zero(bmap->div[i][0]))
4478 continue;
4479 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
4480 return isl_basic_map_free(bmap);
4481 }
4482
4483 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
4484 bmap = isl_basic_map_finalize(bmap);
4485 return bmap;
4486}
4487
4488/* Add the div constraint of sign "sign" for div "div" of "bmap".
4489 *
4490 * In particular, if this div is of the form d = floor(f/m),
4491 * then add the constraint
4492 *
4493 * f - m d >= 0
4494 *
4495 * if sign < 0 or the constraint
4496 *
4497 * -(f-(n-1)) + m d >= 0
4498 *
4499 * if sign > 0.
4500 */
4501int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
4502 unsigned div, int sign)
4503{
4504 unsigned total;
4505 unsigned div_pos;
4506
4507 if (!bmap)
4508 return -1;
4509
4510 total = isl_basic_map_total_dim(bmap);
4511 div_pos = total - bmap->n_div + div;
4512
4513 if (sign < 0)
4514 return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
4515 else
4516 return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
4517}
4518
4519int isl_basic_set_add_div_constraints(struct isl_basic_set *bset, unsigned div)
4520{
4521 return isl_basic_map_add_div_constraints(bset, div);
4522}
4523
4524struct isl_basic_set *isl_basic_map_underlying_set(
4525 struct isl_basic_map *bmap)
4526{
4527 if (!bmap)
4528 goto error;
4529 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
4530 bmap->n_div == 0 &&
4531 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
4532 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
4533 return (struct isl_basic_set *)bmap;
4534 bmap = isl_basic_map_cow(bmap);
4535 if (!bmap)
4536 goto error;
4537 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
4538 if (!bmap->dim)
4539 goto error;
4540 bmap->extra -= bmap->n_div;
4541 bmap->n_div = 0;
4542 bmap = isl_basic_map_finalize(bmap);
4543 return (struct isl_basic_set *)bmap;
4544error:
4545 isl_basic_map_free(bmap);
4546 return NULL;
4547}
4548
4549__isl_give isl_basic_set *isl_basic_set_underlying_set(
4550 __isl_take isl_basic_set *bset)
4551{
4552 return isl_basic_map_underlying_set((isl_basic_map *)bset);
4553}
4554
4555/* Replace each element in "list" by the result of applying
4556 * isl_basic_set_underlying_set to the element.
4557 */
4558__isl_give isl_basic_set_list *isl_basic_set_list_underlying_set(
4559 __isl_take isl_basic_set_list *list)
4560{
4561 int i, n;
4562
4563 if (!list)
4564 return NULL;
4565
4566 n = isl_basic_set_list_n_basic_set(list);
4567 for (i = 0; i < n; ++i) {
4568 isl_basic_set *bset;
4569
4570 bset = isl_basic_set_list_get_basic_set(list, i);
4571 bset = isl_basic_set_underlying_set(bset);
4572 list = isl_basic_set_list_set_basic_set(list, i, bset);
4573 }
4574
4575 return list;
4576}
4577
4578struct isl_basic_map *isl_basic_map_overlying_set(
4579 struct isl_basic_set *bset, struct isl_basic_map *like)
4580{
4581 struct isl_basic_map *bmap;
4582 struct isl_ctx *ctx;
4583 unsigned total;
4584 int i;
4585
4586 if (!bset || !like)
4587 goto error;
4588 ctx = bset->ctx;
4589 isl_assert(ctx, bset->n_div == 0, goto error);
4590 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
4591 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
4592 goto error);
4593 if (isl_space_is_equal(bset->dim, like->dim) && like->n_div == 0) {
4594 isl_basic_map_free(like);
4595 return (struct isl_basic_map *)bset;
4596 }
4597 bset = isl_basic_set_cow(bset);
4598 if (!bset)
4599 goto error;
4600 total = bset->dim->n_out + bset->extra;
4601 bmap = (struct isl_basic_map *)bset;
4602 isl_space_free(bmap->dim);
4603 bmap->dim = isl_space_copy(like->dim);
4604 if (!bmap->dim)
4605 goto error;
4606 bmap->n_div = like->n_div;
4607 bmap->extra += like->n_div;
4608 if (bmap->extra) {
4609 unsigned ltotal;
4610 isl_int **div;
4611 ltotal = total - bmap->extra + like->extra;
4612 if (ltotal > total)
4613 ltotal = total;
4614 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
4615 bmap->extra * (1 + 1 + total));
4616 if (isl_blk_is_error(bmap->block2))
4617 goto error;
4618 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
4619 if (!div)
4620 goto error;
4621 bmap->div = div;
4622 for (i = 0; i < bmap->extra; ++i)
4623 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
4624 for (i = 0; i < like->n_div; ++i) {
4625 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
4626 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
4627 }
4628 bmap = isl_basic_map_add_known_div_constraints(bmap);
4629 }
4630 isl_basic_map_free(like);
4631 bmap = isl_basic_map_simplify(bmap);
4632 bmap = isl_basic_map_finalize(bmap);
4633 return bmap;
4634error:
4635 isl_basic_map_free(like);
4636 isl_basic_set_free(bset);
4637 return NULL;
4638}
4639
4640struct isl_basic_set *isl_basic_set_from_underlying_set(
4641 struct isl_basic_set *bset, struct isl_basic_set *like)
4642{
4643 return (struct isl_basic_set *)
4644 isl_basic_map_overlying_set(bset, (struct isl_basic_map *)like);
4645}
4646
4647struct isl_set *isl_set_from_underlying_set(
4648 struct isl_set *set, struct isl_basic_set *like)
4649{
4650 int i;
4651
4652 if (!set || !like)
4653 goto error;
4654 isl_assert(set->ctx, set->dim->n_out == isl_basic_set_total_dim(like),
4655 goto error);
4656 if (isl_space_is_equal(set->dim, like->dim) && like->n_div == 0) {
4657 isl_basic_set_free(like);
4658 return set;
4659 }
4660 set = isl_set_cow(set);
4661 if (!set)
4662 goto error;
4663 for (i = 0; i < set->n; ++i) {
4664 set->p[i] = isl_basic_set_from_underlying_set(set->p[i],
4665 isl_basic_set_copy(like));
4666 if (!set->p[i])
4667 goto error;
4668 }
4669 isl_space_free(set->dim);
4670 set->dim = isl_space_copy(like->dim);
4671 if (!set->dim)
4672 goto error;
4673 isl_basic_set_free(like);
4674 return set;
4675error:
4676 isl_basic_set_free(like);
4677 isl_set_free(set);
4678 return NULL;
4679}
4680
4681struct isl_set *isl_map_underlying_set(struct isl_map *map)
4682{
4683 int i;
4684
4685 map = isl_map_cow(map);
4686 if (!map)
4687 return NULL;
4688 map->dim = isl_space_cow(map->dim);
4689 if (!map->dim)
4690 goto error;
4691
4692 for (i = 1; i < map->n; ++i)
4693 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
4694 goto error);
4695 for (i = 0; i < map->n; ++i) {
4696 map->p[i] = (struct isl_basic_map *)
4697 isl_basic_map_underlying_set(map->p[i]);
4698 if (!map->p[i])
4699 goto error;
4700 }
4701 if (map->n == 0)
4702 map->dim = isl_space_underlying(map->dim, 0);
4703 else {
4704 isl_space_free(map->dim);
4705 map->dim = isl_space_copy(map->p[0]->dim);
4706 }
4707 if (!map->dim)
4708 goto error;
4709 return (struct isl_set *)map;
4710error:
4711 isl_map_free(map);
4712 return NULL;
4713}
4714
4715struct isl_set *isl_set_to_underlying_set(struct isl_set *set)
4716{
4717 return (struct isl_set *)isl_map_underlying_set((struct isl_map *)set);
4718}
4719
4720__isl_give isl_basic_map *isl_basic_map_reset_space(
4721 __isl_take isl_basic_map *bmap, __isl_take isl_space *dim)
4722{
4723 bmap = isl_basic_map_cow(bmap);
4724 if (!bmap || !dim)
4725 goto error;
4726
4727 isl_space_free(bmap->dim);
4728 bmap->dim = dim;
4729
4730 bmap = isl_basic_map_finalize(bmap);
4731
4732 return bmap;
4733error:
4734 isl_basic_map_free(bmap);
4735 isl_space_free(dim);
4736 return NULL;
4737}
4738
4739__isl_give isl_basic_set *isl_basic_set_reset_space(
4740 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
4741{
4742 return (isl_basic_set *)isl_basic_map_reset_space((isl_basic_map *)bset,
4743 dim);
4744}
4745
4746__isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
4747 __isl_take isl_space *dim)
4748{
4749 int i;
4750
4751 map = isl_map_cow(map);
4752 if (!map || !dim)
4753 goto error;
4754
4755 for (i = 0; i < map->n; ++i) {
4756 map->p[i] = isl_basic_map_reset_space(map->p[i],
4757 isl_space_copy(dim));
4758 if (!map->p[i])
4759 goto error;
4760 }
4761 isl_space_free(map->dim);
4762 map->dim = dim;
4763
4764 return map;
4765error:
4766 isl_map_free(map);
4767 isl_space_free(dim);
4768 return NULL;
4769}
4770
4771__isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
4772 __isl_take isl_space *dim)
4773{
4774 return (struct isl_set *) isl_map_reset_space((struct isl_map *)set, dim);
4775}
4776
4777/* Compute the parameter domain of the given basic set.
4778 */
4779__isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
4780{
4781 isl_space *space;
4782 unsigned n;
4783
4784 if (isl_basic_set_is_params(bset))
4785 return bset;
4786
4787 n = isl_basic_set_dim(bset, isl_dim_set);
4788 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
4789 space = isl_basic_set_get_space(bset);
4790 space = isl_space_params(space);
4791 bset = isl_basic_set_reset_space(bset, space);
4792 return bset;
4793}
4794
4795/* Construct a zero-dimensional basic set with the given parameter domain.
4796 */
4797__isl_give isl_basic_set *isl_basic_set_from_params(
4798 __isl_take isl_basic_set *bset)
4799{
4800 isl_space *space;
4801 space = isl_basic_set_get_space(bset);
4802 space = isl_space_set_from_params(space);
4803 bset = isl_basic_set_reset_space(bset, space);
4804 return bset;
4805}
4806
4807/* Compute the parameter domain of the given set.
4808 */
4809__isl_give isl_set *isl_set_params(__isl_take isl_set *set)
4810{
4811 isl_space *space;
4812 unsigned n;
4813
4814 if (isl_set_is_params(set))
4815 return set;
4816
4817 n = isl_set_dim(set, isl_dim_set);
4818 set = isl_set_project_out(set, isl_dim_set, 0, n);
4819 space = isl_set_get_space(set);
4820 space = isl_space_params(space);
4821 set = isl_set_reset_space(set, space);
4822 return set;
4823}
4824
4825/* Construct a zero-dimensional set with the given parameter domain.
4826 */
4827__isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
4828{
4829 isl_space *space;
4830 space = isl_set_get_space(set);
4831 space = isl_space_set_from_params(space);
4832 set = isl_set_reset_space(set, space);
4833 return set;
4834}
4835
4836/* Compute the parameter domain of the given map.
4837 */
4838__isl_give isl_set *isl_map_params(__isl_take isl_map *map)
4839{
4840 isl_space *space;
4841 unsigned n;
4842
4843 n = isl_map_dim(map, isl_dim_in);
4844 map = isl_map_project_out(map, isl_dim_in, 0, n);
4845 n = isl_map_dim(map, isl_dim_out);
4846 map = isl_map_project_out(map, isl_dim_out, 0, n);
4847 space = isl_map_get_space(map);
4848 space = isl_space_params(space);
4849 map = isl_map_reset_space(map, space);
4850 return map;
4851}
4852
4853struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
4854{
4855 isl_space *dim;
4856 struct isl_basic_set *domain;
4857 unsigned n_in;
4858 unsigned n_out;
4859
4860 if (!bmap)
4861 return NULL;
4862 dim = isl_space_domain(isl_basic_map_get_space(bmap));
4863
4864 n_in = isl_basic_map_n_in(bmap);
4865 n_out = isl_basic_map_n_out(bmap);
4866 domain = isl_basic_set_from_basic_map(bmap);
4867 domain = isl_basic_set_project_out(domain, isl_dim_set, n_in, n_out);
4868
4869 domain = isl_basic_set_reset_space(domain, dim);
4870
4871 return domain;
4872}
4873
4874int isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
4875{
4876 if (!bmap)
4877 return -1;
4878 return isl_space_may_be_set(bmap->dim);
4879}
4880
4881/* Is this basic map actually a set?
4882 * Users should never call this function. Outside of isl,
4883 * the type should indicate whether something is a set or a map.
4884 */
4885int isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
4886{
4887 if (!bmap)
4888 return -1;
4889 return isl_space_is_set(bmap->dim);
4890}
4891
4892struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
4893{
4894 if (!bmap)
4895 return NULL;
4896 if (isl_basic_map_is_set(bmap))
4897 return bmap;
4898 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
4899}
4900
4901__isl_give isl_basic_map *isl_basic_map_domain_map(
4902 __isl_take isl_basic_map *bmap)
4903{
4904 int i, k;
4905 isl_space *dim;
4906 isl_basic_map *domain;
4907 int nparam, n_in, n_out;
4908 unsigned total;
4909
4910 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4911 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4912 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4913
4914 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
4915 domain = isl_basic_map_universe(dim);
4916
4917 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
4918 bmap = isl_basic_map_apply_range(bmap, domain);
4919 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
4920
4921 total = isl_basic_map_total_dim(bmap);
4922
4923 for (i = 0; i < n_in; ++i) {
4924 k = isl_basic_map_alloc_equality(bmap);
4925 if (k < 0)
4926 goto error;
4927 isl_seq_clr(bmap->eq[k], 1 + total);
4928 isl_int_set_si(bmap->eq[k][1 + nparam + i], -1);
4929 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1);
4930 }
4931
4932 bmap = isl_basic_map_gauss(bmap, NULL);
4933 return isl_basic_map_finalize(bmap);
4934error:
4935 isl_basic_map_free(bmap);
4936 return NULL;
4937}
4938
4939__isl_give isl_basic_map *isl_basic_map_range_map(
4940 __isl_take isl_basic_map *bmap)
4941{
4942 int i, k;
4943 isl_space *dim;
4944 isl_basic_map *range;
4945 int nparam, n_in, n_out;
4946 unsigned total;
4947
4948 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4949 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4950 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4951
4952 dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
4953 range = isl_basic_map_universe(dim);
4954
4955 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
4956 bmap = isl_basic_map_apply_range(bmap, range);
4957 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
4958
4959 total = isl_basic_map_total_dim(bmap);
4960
4961 for (i = 0; i < n_out; ++i) {
4962 k = isl_basic_map_alloc_equality(bmap);
4963 if (k < 0)
4964 goto error;
4965 isl_seq_clr(bmap->eq[k], 1 + total);
4966 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + i], -1);
4967 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1);
4968 }
4969
4970 bmap = isl_basic_map_gauss(bmap, NULL);
4971 return isl_basic_map_finalize(bmap);
4972error:
4973 isl_basic_map_free(bmap);
4974 return NULL;
4975}
4976
4977int isl_map_may_be_set(__isl_keep isl_map *map)
4978{
4979 if (!map)
4980 return -1;
4981 return isl_space_may_be_set(map->dim);
4982}
4983
4984/* Is this map actually a set?
4985 * Users should never call this function. Outside of isl,
4986 * the type should indicate whether something is a set or a map.
4987 */
4988int isl_map_is_set(__isl_keep isl_map *map)
4989{
4990 if (!map)
4991 return -1;
4992 return isl_space_is_set(map->dim);
4993}
4994
4995struct isl_set *isl_map_range(struct isl_map *map)
4996{
4997 int i;
4998 struct isl_set *set;
4999
5000 if (!map)
5001 goto error;
5002 if (isl_map_is_set(map))
5003 return (isl_set *)map;
5004
5005 map = isl_map_cow(map);
5006 if (!map)
5007 goto error;
5008
5009 set = (struct isl_set *) map;
5010 set->dim = isl_space_range(set->dim);
5011 if (!set->dim)
5012 goto error;
5013 for (i = 0; i < map->n; ++i) {
5014 set->p[i] = isl_basic_map_range(map->p[i]);
5015 if (!set->p[i])
5016 goto error;
5017 }
5018 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5019 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5020 return set;
5021error:
5022 isl_map_free(map);
5023 return NULL;
5024}
5025
5026__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5027{
5028 int i;
5029
5030 map = isl_map_cow(map);
5031 if (!map)
5032 return NULL;
5033
5034 map->dim = isl_space_domain_map(map->dim);
5035 if (!map->dim)
5036 goto error;
5037 for (i = 0; i < map->n; ++i) {
5038 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5039 if (!map->p[i])
5040 goto error;
5041 }
5042 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5043 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5044 return map;
5045error:
5046 isl_map_free(map);
5047 return NULL;
5048}
5049
5050__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5051{
5052 int i;
5053 isl_space *range_dim;
5054
5055 map = isl_map_cow(map);
5056 if (!map)
5057 return NULL;
5058
5059 range_dim = isl_space_range(isl_map_get_space(map));
5060 range_dim = isl_space_from_range(range_dim);
5061 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5062 map->dim = isl_space_join(map->dim, range_dim);
5063 if (!map->dim)
5064 goto error;
5065 for (i = 0; i < map->n; ++i) {
5066 map->p[i] = isl_basic_map_range_map(map->p[i]);
5067 if (!map->p[i])
5068 goto error;
5069 }
5070 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5071 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5072 return map;
5073error:
5074 isl_map_free(map);
5075 return NULL;
5076}
5077
5078/* Given a wrapped map of the form A[B -> C],
5079 * return the map A[B -> C] -> B.
5080 */
5081__isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5082{
5083 isl_id *id;
5084 isl_map *map;
5085
5086 if (!set)
5087 return NULL;
5088 if (!isl_set_has_tuple_id(set))
5089 return isl_map_domain_map(isl_set_unwrap(set));
5090
5091 id = isl_set_get_tuple_id(set);
5092 map = isl_map_domain_map(isl_set_unwrap(set));
5093 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5094
5095 return map;
5096}
5097
5098__isl_give isl_map *isl_map_from_set(__isl_take isl_set *set,
5099 __isl_take isl_space *dim)
5100{
5101 int i;
5102 struct isl_map *map = NULL;
5103
5104 set = isl_set_cow(set);
5105 if (!set || !dim)
5106 goto error;
5107 isl_assert(set->ctx, isl_space_compatible(set->dim, dim), goto error);
5108 map = (struct isl_map *)set;
5109 for (i = 0; i < set->n; ++i) {
5110 map->p[i] = isl_basic_map_from_basic_set(
5111 set->p[i], isl_space_copy(dim));
5112 if (!map->p[i])
5113 goto error;
5114 }
5115 isl_space_free(map->dim);
5116 map->dim = dim;
5117 return map;
5118error:
5119 isl_space_free(dim);
5120 isl_set_free(set);
5121 return NULL;
5122}
5123
5124__isl_give isl_basic_map *isl_basic_map_from_domain(
5125 __isl_take isl_basic_set *bset)
5126{
5127 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5128}
5129
5130__isl_give isl_basic_map *isl_basic_map_from_range(
5131 __isl_take isl_basic_set *bset)
5132{
5133 isl_space *space;
5134 space = isl_basic_set_get_space(bset);
5135 space = isl_space_from_range(space);
5136 bset = isl_basic_set_reset_space(bset, space);
5137 return (isl_basic_map *)bset;
5138}
5139
5140/* Create a relation with the given set as range.
5141 * The domain of the created relation is a zero-dimensional
5142 * flat anonymous space.
5143 */
5144__isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5145{
5146 isl_space *space;
5147 space = isl_set_get_space(set);
5148 space = isl_space_from_range(space);
5149 set = isl_set_reset_space(set, space);
5150 return (struct isl_map *)set;
5151}
5152
5153/* Create a relation with the given set as domain.
5154 * The range of the created relation is a zero-dimensional
5155 * flat anonymous space.
5156 */
5157__isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5158{
5159 return isl_map_reverse(isl_map_from_range(set));
5160}
5161
5162__isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5163 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5164{
5165 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5166}
5167
5168__isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5169 __isl_take isl_set *range)
5170{
5171 return isl_map_apply_range(isl_map_reverse(domain), range);
5172}
5173
5174struct isl_set *isl_set_from_map(struct isl_map *map)
5175{
5176 int i;
5177 struct isl_set *set = NULL;
5178
5179 if (!map)
5180 return NULL;
5181 map = isl_map_cow(map);
5182 if (!map)
5183 return NULL;
5184 map->dim = isl_space_as_set_space(map->dim);
5185 if (!map->dim)
5186 goto error;
5187 set = (struct isl_set *)map;
5188 for (i = 0; i < map->n; ++i) {
5189 set->p[i] = isl_basic_set_from_basic_map(map->p[i]);
5190 if (!set->p[i])
5191 goto error;
5192 }
5193 return set;
5194error:
5195 isl_map_free(map);
5196 return NULL;
5197}
5198
5199__isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *dim, int n,
5200 unsigned flags)
5201{
5202 struct isl_map *map;
5203
5204 if (!dim)
5205 return NULL;
5206 if (n < 0)
5207 isl_die(dim->ctx, isl_error_internal,
5208 "negative number of basic maps", goto error);
5209 map = isl_alloc(dim->ctx, struct isl_map,
5210 sizeof(struct isl_map) +
5211 (n - 1) * sizeof(struct isl_basic_map *));
5212 if (!map)
5213 goto error;
5214
5215 map->ctx = dim->ctx;
5216 isl_ctx_ref(map->ctx);
5217 map->ref = 1;
5218 map->size = n;
5219 map->n = 0;
5220 map->dim = dim;
5221 map->flags = flags;
5222 return map;
5223error:
5224 isl_space_free(dim);
5225 return NULL;
5226}
5227
5228struct isl_map *isl_map_alloc(struct isl_ctx *ctx,
5229 unsigned nparam, unsigned in, unsigned out, int n,
5230 unsigned flags)
5231{
5232 struct isl_map *map;
5233 isl_space *dims;
5234
5235 dims = isl_space_alloc(ctx, nparam, in, out);
5236 if (!dims)
5237 return NULL;
5238
5239 map = isl_map_alloc_space(dims, n, flags);
5240 return map;
5241}
5242
5243__isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim)
5244{
5245 struct isl_basic_map *bmap;
5246 bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
5247 bmap = isl_basic_map_set_to_empty(bmap);
5248 return bmap;
5249}
5250
5251__isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim)
5252{
5253 struct isl_basic_set *bset;
5254 bset = isl_basic_set_alloc_space(dim, 0, 1, 0);
5255 bset = isl_basic_set_set_to_empty(bset);
5256 return bset;
5257}
5258
5259struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model)
5260{
5261 struct isl_basic_map *bmap;
5262 if (!model)
5263 return NULL;
5264 bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5265 bmap = isl_basic_map_set_to_empty(bmap);
5266 return bmap;
5267}
5268
5269struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model)
5270{
5271 struct isl_basic_map *bmap;
5272 if (!model)
5273 return NULL;
5274 bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5275 bmap = isl_basic_map_set_to_empty(bmap);
5276 return bmap;
5277}
5278
5279struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *model)
5280{
5281 struct isl_basic_set *bset;
5282 if (!model)
5283 return NULL;
5284 bset = isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
5285 bset = isl_basic_set_set_to_empty(bset);
5286 return bset;
5287}
5288
5289__isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim)
5290{
5291 struct isl_basic_map *bmap;
5292 bmap = isl_basic_map_alloc_space(dim, 0, 0, 0);
5293 bmap = isl_basic_map_finalize(bmap);
5294 return bmap;
5295}
5296
5297__isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim)
5298{
5299 struct isl_basic_set *bset;
5300 bset = isl_basic_set_alloc_space(dim, 0, 0, 0);
5301 bset = isl_basic_set_finalize(bset);
5302 return bset;
5303}
5304
5305__isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
5306{
5307 int i;
5308 unsigned total = isl_space_dim(dim, isl_dim_all);
5309 isl_basic_map *bmap;
5310
5311 bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
5312 for (i = 0; i < total; ++i) {
5313 int k = isl_basic_map_alloc_inequality(bmap);
5314 if (k < 0)
5315 goto error;
5316 isl_seq_clr(bmap->ineq[k], 1 + total);
5317 isl_int_set_si(bmap->ineq[k][1 + i], 1);
5318 }
5319 return bmap;
5320error:
5321 isl_basic_map_free(bmap);
5322 return NULL;
5323}
5324
5325__isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
5326{
5327 return isl_basic_map_nat_universe(dim);
5328}
5329
5330__isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
5331{
5332 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
5333}
5334
5335__isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
5336{
5337 return isl_map_nat_universe(dim);
5338}
5339
5340__isl_give isl_basic_map *isl_basic_map_universe_like(
5341 __isl_keep isl_basic_map *model)
5342{
5343 if (!model)
5344 return NULL;
5345 return isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5346}
5347
5348struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *model)
5349{
5350 if (!model)
5351 return NULL;
5352 return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5353}
5354
5355__isl_give isl_basic_set *isl_basic_set_universe_like_set(
5356 __isl_keep isl_set *model)
5357{
5358 if (!model)
5359 return NULL;
5360 return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
5361}
5362
5363__isl_give isl_map *isl_map_empty(__isl_take isl_space *dim)
5364{
5365 return isl_map_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5366}
5367
5368struct isl_map *isl_map_empty_like(struct isl_map *model)
5369{
5370 if (!model)
5371 return NULL;
5372 return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT);
5373}
5374
5375struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model)
5376{
5377 if (!model)
5378 return NULL;
5379 return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT);
5380}
5381
5382__isl_give isl_set *isl_set_empty(__isl_take isl_space *dim)
5383{
5384 return isl_set_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5385}
5386
5387struct isl_set *isl_set_empty_like(struct isl_set *model)
5388{
5389 if (!model)
5390 return NULL;
5391 return isl_set_empty(isl_space_copy(model->dim));
5392}
5393
5394__isl_give isl_map *isl_map_universe(__isl_take isl_space *dim)
5395{
5396 struct isl_map *map;
5397 if (!dim)
5398 return NULL;
5399 map = isl_map_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5400 map = isl_map_add_basic_map(map, isl_basic_map_universe(dim));
5401 return map;
5402}
5403
5404__isl_give isl_set *isl_set_universe(__isl_take isl_space *dim)
5405{
5406 struct isl_set *set;
5407 if (!dim)
5408 return NULL;
5409 set = isl_set_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5410 set = isl_set_add_basic_set(set, isl_basic_set_universe(dim));
5411 return set;
5412}
5413
5414__isl_give isl_set *isl_set_universe_like(__isl_keep isl_set *model)
5415{
5416 if (!model)
5417 return NULL;
5418 return isl_set_universe(isl_space_copy(model->dim));
5419}
5420
5421struct isl_map *isl_map_dup(struct isl_map *map)
5422{
5423 int i;
5424 struct isl_map *dup;
5425
5426 if (!map)
5427 return NULL;
5428 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
5429 for (i = 0; i < map->n; ++i)
5430 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
5431 return dup;
5432}
5433
5434__isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
5435 __isl_take isl_basic_map *bmap)
5436{
5437 if (!bmap || !map)
5438 goto error;
5439 if (isl_basic_map_plain_is_empty(bmap)) {
5440 isl_basic_map_free(bmap);
5441 return map;
5442 }
5443 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
5444 isl_assert(map->ctx, map->n < map->size, goto error);
5445 map->p[map->n] = bmap;
5446 map->n++;
5447 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5448 return map;
5449error:
5450 if (map)
5451 isl_map_free(map);
5452 if (bmap)
5453 isl_basic_map_free(bmap);
5454 return NULL;
5455}
5456
5457__isl_null isl_map *isl_map_free(__isl_take isl_map *map)
5458{
5459 int i;
5460
5461 if (!map)
5462 return NULL;
5463
5464 if (--map->ref > 0)
5465 return NULL;
5466
5467 isl_ctx_deref(map->ctx);
5468 for (i = 0; i < map->n; ++i)
5469 isl_basic_map_free(map->p[i]);
5470 isl_space_free(map->dim);
5471 free(map);
5472
5473 return NULL;
5474}
5475
5476struct isl_map *isl_map_extend(struct isl_map *base,
5477 unsigned nparam, unsigned n_in, unsigned n_out)
5478{
5479 int i;
5480
5481 base = isl_map_cow(base);
5482 if (!base)
5483 return NULL;
5484
5485 base->dim = isl_space_extend(base->dim, nparam, n_in, n_out);
5486 if (!base->dim)
5487 goto error;
5488 for (i = 0; i < base->n; ++i) {
5489 base->p[i] = isl_basic_map_extend_space(base->p[i],
5490 isl_space_copy(base->dim), 0, 0, 0);
5491 if (!base->p[i])
5492 goto error;
5493 }
5494 return base;
5495error:
5496 isl_map_free(base);
5497 return NULL;
5498}
5499
5500struct isl_set *isl_set_extend(struct isl_set *base,
5501 unsigned nparam, unsigned dim)
5502{
5503 return (struct isl_set *)isl_map_extend((struct isl_map *)base,
5504 nparam, 0, dim);
5505}
5506
5507static struct isl_basic_map *isl_basic_map_fix_pos_si(
5508 struct isl_basic_map *bmap, unsigned pos, int value)
5509{
5510 int j;
5511
5512 bmap = isl_basic_map_cow(bmap);
5513 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5514 j = isl_basic_map_alloc_equality(bmap);
5515 if (j < 0)
5516 goto error;
5517 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5518 isl_int_set_si(bmap->eq[j][pos], -1);
5519 isl_int_set_si(bmap->eq[j][0], value);
5520 bmap = isl_basic_map_simplify(bmap);
5521 return isl_basic_map_finalize(bmap);
5522error:
5523 isl_basic_map_free(bmap);
5524 return NULL;
5525}
5526
5527static __isl_give isl_basic_map *isl_basic_map_fix_pos(
5528 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
5529{
5530 int j;
5531
5532 bmap = isl_basic_map_cow(bmap);
5533 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5534 j = isl_basic_map_alloc_equality(bmap);
5535 if (j < 0)
5536 goto error;
5537 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5538 isl_int_set_si(bmap->eq[j][pos], -1);
5539 isl_int_set(bmap->eq[j][0], value);
5540 bmap = isl_basic_map_simplify(bmap);
5541 return isl_basic_map_finalize(bmap);
5542error:
5543 isl_basic_map_free(bmap);
5544 return NULL;
5545}
5546
5547struct isl_basic_map *isl_basic_map_fix_si(struct isl_basic_map *bmap,
5548 enum isl_dim_type type, unsigned pos, int value)
5549{
5550 if (!bmap)
5551 return NULL;
5552 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5553 return isl_basic_map_fix_pos_si(bmap,
5554 isl_basic_map_offset(bmap, type) + pos, value);
5555error:
5556 isl_basic_map_free(bmap);
5557 return NULL;
5558}
5559
5560__isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
5561 enum isl_dim_type type, unsigned pos, isl_int value)
5562{
5563 if (!bmap)
5564 return NULL;
5565 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5566 return isl_basic_map_fix_pos(bmap,
5567 isl_basic_map_offset(bmap, type) + pos, value);
5568error:
5569 isl_basic_map_free(bmap);
5570 return NULL;
5571}
5572
5573/* Fix the value of the variable at position "pos" of type "type" of "bmap"
5574 * to be equal to "v".
5575 */
5576__isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
5577 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5578{
5579 if (!bmap || !v)
5580 goto error;
5581 if (!isl_val_is_int(v))
5582 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
5583 "expecting integer value", goto error);
5584 if (pos >= isl_basic_map_dim(bmap, type))
5585 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
5586 "index out of bounds", goto error);
5587 pos += isl_basic_map_offset(bmap, type);
5588 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
5589 isl_val_free(v);
5590 return bmap;
5591error:
5592 isl_basic_map_free(bmap);
5593 isl_val_free(v);
5594 return NULL;
5595}
5596
5597/* Fix the value of the variable at position "pos" of type "type" of "bset"
5598 * to be equal to "v".
5599 */
5600__isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
5601 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5602{
5603 return isl_basic_map_fix_val(bset, type, pos, v);
5604}
5605
5606struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
5607 enum isl_dim_type type, unsigned pos, int value)
5608{
5609 return (struct isl_basic_set *)
5610 isl_basic_map_fix_si((struct isl_basic_map *)bset,
5611 type, pos, value);
5612}
5613
5614__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
5615 enum isl_dim_type type, unsigned pos, isl_int value)
5616{
5617 return (struct isl_basic_set *)
5618 isl_basic_map_fix((struct isl_basic_map *)bset,
5619 type, pos, value);
5620}
5621
5622struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
5623 unsigned input, int value)
5624{
5625 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
5626}
5627
5628struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
5629 unsigned dim, int value)
5630{
5631 return (struct isl_basic_set *)
5632 isl_basic_map_fix_si((struct isl_basic_map *)bset,
5633 isl_dim_set, dim, value);
5634}
5635
5636static int remove_if_empty(__isl_keep isl_map *map, int i)
5637{
5638 int empty = isl_basic_map_plain_is_empty(map->p[i]);
5639
5640 if (empty < 0)
5641 return -1;
5642 if (!empty)
5643 return 0;
5644
5645 isl_basic_map_free(map->p[i]);
5646 if (i != map->n - 1) {
5647 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5648 map->p[i] = map->p[map->n - 1];
5649 }
5650 map->n--;
5651
5652 return 0;
5653}
5654
5655/* Perform "fn" on each basic map of "map", where we may not be holding
5656 * the only reference to "map".
5657 * In particular, "fn" should be a semantics preserving operation
5658 * that we want to apply to all copies of "map". We therefore need
5659 * to be careful not to modify "map" in a way that breaks "map"
5660 * in case anything goes wrong.
5661 */
5662__isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
5663 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
5664{
5665 struct isl_basic_map *bmap;
5666 int i;
5667
5668 if (!map)
5669 return NULL;
5670
5671 for (i = map->n - 1; i >= 0; --i) {
5672 bmap = isl_basic_map_copy(map->p[i]);
5673 bmap = fn(bmap);
5674 if (!bmap)
5675 goto error;
5676 isl_basic_map_free(map->p[i]);
5677 map->p[i] = bmap;
5678 if (remove_if_empty(map, i) < 0)
5679 goto error;
5680 }
5681
5682 return map;
5683error:
5684 isl_map_free(map);
5685 return NULL;
5686}
5687
5688struct isl_map *isl_map_fix_si(struct isl_map *map,
5689 enum isl_dim_type type, unsigned pos, int value)
5690{
5691 int i;
5692
5693 map = isl_map_cow(map);
5694 if (!map)
5695 return NULL;
5696
5697 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5698 for (i = map->n - 1; i >= 0; --i) {
5699 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
5700 if (remove_if_empty(map, i) < 0)
5701 goto error;
5702 }
5703 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5704 return map;
5705error:
5706 isl_map_free(map);
5707 return NULL;
5708}
5709
5710__isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
5711 enum isl_dim_type type, unsigned pos, int value)
5712{
5713 return (struct isl_set *)
5714 isl_map_fix_si((struct isl_map *)set, type, pos, value);
5715}
5716
5717__isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
5718 enum isl_dim_type type, unsigned pos, isl_int value)
5719{
5720 int i;
5721
5722 map = isl_map_cow(map);
5723 if (!map)
5724 return NULL;
5725
5726 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5727 for (i = 0; i < map->n; ++i) {
5728 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
5729 if (!map->p[i])
5730 goto error;
5731 }
5732 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5733 return map;
5734error:
5735 isl_map_free(map);
5736 return NULL;
5737}
5738
5739__isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
5740 enum isl_dim_type type, unsigned pos, isl_int value)
5741{
5742 return (struct isl_set *)isl_map_fix((isl_map *)set, type, pos, value);
5743}
5744
5745/* Fix the value of the variable at position "pos" of type "type" of "map"
5746 * to be equal to "v".
5747 */
5748__isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
5749 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5750{
5751 int i;
5752
5753 map = isl_map_cow(map);
5754 if (!map || !v)
5755 goto error;
5756
5757 if (!isl_val_is_int(v))
5758 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5759 "expecting integer value", goto error);
5760 if (pos >= isl_map_dim(map, type))
5761 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5762 "index out of bounds", goto error);
5763 for (i = map->n - 1; i >= 0; --i) {
5764 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
5765 isl_val_copy(v));
5766 if (remove_if_empty(map, i) < 0)
5767 goto error;
5768 }
5769 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5770 isl_val_free(v);
5771 return map;
5772error:
5773 isl_map_free(map);
5774 isl_val_free(v);
5775 return NULL;
5776}
5777
5778/* Fix the value of the variable at position "pos" of type "type" of "set"
5779 * to be equal to "v".
5780 */
5781__isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
5782 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5783{
5784 return isl_map_fix_val(set, type, pos, v);
5785}
5786
5787struct isl_map *isl_map_fix_input_si(struct isl_map *map,
5788 unsigned input, int value)
5789{
5790 return isl_map_fix_si(map, isl_dim_in, input, value);
5791}
5792
5793struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
5794{
5795 return (struct isl_set *)
5796 isl_map_fix_si((struct isl_map *)set, isl_dim_set, dim, value);
5797}
5798
5799static __isl_give isl_basic_map *basic_map_bound_si(
5800 __isl_take isl_basic_map *bmap,
5801 enum isl_dim_type type, unsigned pos, int value, int upper)
5802{
5803 int j;
5804
5805 if (!bmap)
5806 return NULL;
5807 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
5808 pos += isl_basic_map_offset(bmap, type);
5809 bmap = isl_basic_map_cow(bmap);
5810 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
5811 j = isl_basic_map_alloc_inequality(bmap);
5812 if (j < 0)
5813 goto error;
5814 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
5815 if (upper) {
5816 isl_int_set_si(bmap->ineq[j][pos], -1);
5817 isl_int_set_si(bmap->ineq[j][0], value);
5818 } else {
5819 isl_int_set_si(bmap->ineq[j][pos], 1);
5820 isl_int_set_si(bmap->ineq[j][0], -value);
5821 }
5822 bmap = isl_basic_map_simplify(bmap);
5823 return isl_basic_map_finalize(bmap);
5824error:
5825 isl_basic_map_free(bmap);
5826 return NULL;
5827}
5828
5829__isl_give isl_basic_map *isl_basic_map_lower_bound_si(
5830 __isl_take isl_basic_map *bmap,
5831 enum isl_dim_type type, unsigned pos, int value)
5832{
5833 return basic_map_bound_si(bmap, type, pos, value, 0);
5834}
5835
5836/* Constrain the values of the given dimension to be no greater than "value".
5837 */
5838__isl_give isl_basic_map *isl_basic_map_upper_bound_si(
5839 __isl_take isl_basic_map *bmap,
5840 enum isl_dim_type type, unsigned pos, int value)
5841{
5842 return basic_map_bound_si(bmap, type, pos, value, 1);
5843}
5844
5845struct isl_basic_set *isl_basic_set_lower_bound_dim(struct isl_basic_set *bset,
5846 unsigned dim, isl_int value)
5847{
5848 int j;
5849
5850 bset = isl_basic_set_cow(bset);
5851 bset = isl_basic_set_extend_constraints(bset, 0, 1);
5852 j = isl_basic_set_alloc_inequality(bset);
5853 if (j < 0)
5854 goto error;
5855 isl_seq_clr(bset->ineq[j], 1 + isl_basic_set_total_dim(bset));
5856 isl_int_set_si(bset->ineq[j][1 + isl_basic_set_n_param(bset) + dim], 1);
5857 isl_int_neg(bset->ineq[j][0], value);
5858 bset = isl_basic_set_simplify(bset);
5859 return isl_basic_set_finalize(bset);
5860error:
5861 isl_basic_set_free(bset);
5862 return NULL;
5863}
5864
5865static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
5866 enum isl_dim_type type, unsigned pos, int value, int upper)
5867{
5868 int i;
5869
5870 map = isl_map_cow(map);
5871 if (!map)
5872 return NULL;
5873
5874 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5875 for (i = 0; i < map->n; ++i) {
5876 map->p[i] = basic_map_bound_si(map->p[i],
5877 type, pos, value, upper);
5878 if (!map->p[i])
5879 goto error;
5880 }
5881 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5882 return map;
5883error:
5884 isl_map_free(map);
5885 return NULL;
5886}
5887
5888__isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
5889 enum isl_dim_type type, unsigned pos, int value)
5890{
5891 return map_bound_si(map, type, pos, value, 0);
5892}
5893
5894__isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
5895 enum isl_dim_type type, unsigned pos, int value)
5896{
5897 return map_bound_si(map, type, pos, value, 1);
5898}
5899
5900__isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
5901 enum isl_dim_type type, unsigned pos, int value)
5902{
5903 return (struct isl_set *)
5904 isl_map_lower_bound_si((struct isl_map *)set, type, pos, value);
5905}
5906
5907__isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
5908 enum isl_dim_type type, unsigned pos, int value)
5909{
5910 return isl_map_upper_bound_si(set, type, pos, value);
5911}
5912
5913/* Bound the given variable of "bmap" from below (or above is "upper"
5914 * is set) to "value".
5915 */
5916static __isl_give isl_basic_map *basic_map_bound(
5917 __isl_take isl_basic_map *bmap,
5918 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
5919{
5920 int j;
5921
5922 if (!bmap)
5923 return NULL;
5924 if (pos >= isl_basic_map_dim(bmap, type))
5925 isl_die(bmap->ctx, isl_error_invalid,
5926 "index out of bounds", goto error);
5927 pos += isl_basic_map_offset(bmap, type);
5928 bmap = isl_basic_map_cow(bmap);
5929 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
5930 j = isl_basic_map_alloc_inequality(bmap);
5931 if (j < 0)
5932 goto error;
5933 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
5934 if (upper) {
5935 isl_int_set_si(bmap->ineq[j][pos], -1);
5936 isl_int_set(bmap->ineq[j][0], value);
5937 } else {
5938 isl_int_set_si(bmap->ineq[j][pos], 1);
5939 isl_int_neg(bmap->ineq[j][0], value);
5940 }
5941 bmap = isl_basic_map_simplify(bmap);
5942 return isl_basic_map_finalize(bmap);
5943error:
5944 isl_basic_map_free(bmap);
5945 return NULL;
5946}
5947
5948/* Bound the given variable of "map" from below (or above is "upper"
5949 * is set) to "value".
5950 */
5951static __isl_give isl_map *map_bound(__isl_take isl_map *map,
5952 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
5953{
5954 int i;
5955
5956 map = isl_map_cow(map);
5957 if (!map)
5958 return NULL;
5959
5960 if (pos >= isl_map_dim(map, type))
5961 isl_die(map->ctx, isl_error_invalid,
5962 "index out of bounds", goto error);
5963 for (i = map->n - 1; i >= 0; --i) {
5964 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
5965 if (remove_if_empty(map, i) < 0)
5966 goto error;
5967 }
5968 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5969 return map;
5970error:
5971 isl_map_free(map);
5972 return NULL;
5973}
5974
5975__isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
5976 enum isl_dim_type type, unsigned pos, isl_int value)
5977{
5978 return map_bound(map, type, pos, value, 0);
5979}
5980
5981__isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
5982 enum isl_dim_type type, unsigned pos, isl_int value)
5983{
5984 return map_bound(map, type, pos, value, 1);
5985}
5986
5987__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
5988 enum isl_dim_type type, unsigned pos, isl_int value)
5989{
5990 return isl_map_lower_bound(set, type, pos, value);
5991}
5992
5993__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
5994 enum isl_dim_type type, unsigned pos, isl_int value)
5995{
5996 return isl_map_upper_bound(set, type, pos, value);
5997}
5998
5999/* Force the values of the variable at position "pos" of type "type" of "set"
6000 * to be no smaller than "value".
6001 */
6002__isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6003 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6004{
6005 if (!value)
6006 goto error;
6007 if (!isl_val_is_int(value))
6008 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6009 "expecting integer value", goto error);
6010 set = isl_set_lower_bound(set, type, pos, value->n);
6011 isl_val_free(value);
6012 return set;
6013error:
6014 isl_val_free(value);
6015 isl_set_free(set);
6016 return NULL;
6017}
6018
6019/* Force the values of the variable at position "pos" of type "type" of "set"
6020 * to be no greater than "value".
6021 */
6022__isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6023 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6024{
6025 if (!value)
6026 goto error;
6027 if (!isl_val_is_int(value))
6028 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6029 "expecting integer value", goto error);
6030 set = isl_set_upper_bound(set, type, pos, value->n);
6031 isl_val_free(value);
6032 return set;
6033error:
6034 isl_val_free(value);
6035 isl_set_free(set);
6036 return NULL;
6037}
6038
6039struct isl_set *isl_set_lower_bound_dim(struct isl_set *set, unsigned dim,
6040 isl_int value)
6041{
6042 int i;
6043
6044 set = isl_set_cow(set);
6045 if (!set)
6046 return NULL;
6047
6048 isl_assert(set->ctx, dim < isl_set_n_dim(set), goto error);
6049 for (i = 0; i < set->n; ++i) {
6050 set->p[i] = isl_basic_set_lower_bound_dim(set->p[i], dim, value);
6051 if (!set->p[i])
6052 goto error;
6053 }
6054 return set;
6055error:
6056 isl_set_free(set);
6057 return NULL;
6058}
6059
6060struct isl_map *isl_map_reverse(struct isl_map *map)
6061{
6062 int i;
6063
6064 map = isl_map_cow(map);
6065 if (!map)
6066 return NULL;
6067
6068 map->dim = isl_space_reverse(map->dim);
6069 if (!map->dim)
6070 goto error;
6071 for (i = 0; i < map->n; ++i) {
6072 map->p[i] = isl_basic_map_reverse(map->p[i]);
6073 if (!map->p[i])
6074 goto error;
6075 }
6076 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
6077 return map;
6078error:
6079 isl_map_free(map);
6080 return NULL;
6081}
6082
6083static struct isl_map *isl_basic_map_partial_lexopt(
6084 struct isl_basic_map *bmap, struct isl_basic_set *dom,
6085 struct isl_set **empty, int max)
6086{
6087 return isl_tab_basic_map_partial_lexopt(bmap, dom, empty, max);
6088}
6089
6090struct isl_map *isl_basic_map_partial_lexmax(
6091 struct isl_basic_map *bmap, struct isl_basic_set *dom,
6092 struct isl_set **empty)
6093{
6094 return isl_basic_map_partial_lexopt(bmap, dom, empty, 1);
6095}
6096
6097struct isl_map *isl_basic_map_partial_lexmin(
6098 struct isl_basic_map *bmap, struct isl_basic_set *dom,
6099 struct isl_set **empty)
6100{
6101 return isl_basic_map_partial_lexopt(bmap, dom, empty, 0);
6102}
6103
6104struct isl_set *isl_basic_set_partial_lexmin(
6105 struct isl_basic_set *bset, struct isl_basic_set *dom,
6106 struct isl_set **empty)
6107{
6108 return (struct isl_set *)
6109 isl_basic_map_partial_lexmin((struct isl_basic_map *)bset,
6110 dom, empty);
6111}
6112
6113struct isl_set *isl_basic_set_partial_lexmax(
6114 struct isl_basic_set *bset, struct isl_basic_set *dom,
6115 struct isl_set **empty)
6116{
6117 return (struct isl_set *)
6118 isl_basic_map_partial_lexmax((struct isl_basic_map *)bset,
6119 dom, empty);
6120}
6121
6122__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff(
6123 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
6124 __isl_give isl_set **empty)
6125{
6126 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 0);
6127}
6128
6129__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
6130 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
6131 __isl_give isl_set **empty)
6132{
6133 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 1);
6134}
6135
6136__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff(
6137 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
6138 __isl_give isl_set **empty)
6139{
6140 return isl_basic_map_partial_lexmin_pw_multi_aff(bset, dom, empty);
6141}
6142
6143__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff(
6144 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
6145 __isl_give isl_set **empty)
6146{
6147 return isl_basic_map_partial_lexmax_pw_multi_aff(bset, dom, empty);
6148}
6149
6150__isl_give isl_pw_multi_aff *isl_basic_map_lexopt_pw_multi_aff(
6151 __isl_take isl_basic_map *bmap, int max)
6152{
6153 isl_basic_set *dom = NULL;
6154 isl_space *dom_space;
6155
6156 if (!bmap)
6157 goto error;
6158 dom_space = isl_space_domain(isl_space_copy(bmap->dim));
6159 dom = isl_basic_set_universe(dom_space);
6160 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, NULL, max);
6161error:
6162 isl_basic_map_free(bmap);
6163 return NULL;
6164}
6165
6166__isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
6167 __isl_take isl_basic_map *bmap)
6168{
6169 return isl_basic_map_lexopt_pw_multi_aff(bmap, 0);
6170}
6171
6172#undef TYPE
6173#define TYPE isl_pw_multi_aff
6174#undef SUFFIX
6175#define SUFFIX _pw_multi_aff
6176#undef EMPTY
6177#define EMPTY isl_pw_multi_aff_empty
6178#undef ADD
6179#define ADD isl_pw_multi_aff_union_add
6180#include "isl_map_lexopt_templ.c"
6181
6182/* Given a map "map", compute the lexicographically minimal
6183 * (or maximal) image element for each domain element in dom,
6184 * in the form of an isl_pw_multi_aff.
6185 * Set *empty to those elements in dom that do not have an image element.
6186 *
6187 * We first compute the lexicographically minimal or maximal element
6188 * in the first basic map. This results in a partial solution "res"
6189 * and a subset "todo" of dom that still need to be handled.
6190 * We then consider each of the remaining maps in "map" and successively
6191 * update both "res" and "todo".
6192 */
6193static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6194 __isl_take isl_map *map, __isl_take isl_set *dom,
6195 __isl_give isl_set **empty, int max)
6196{
6197 int i;
6198 isl_pw_multi_aff *res;
6199 isl_set *todo;
6200
6201 if (!map || !dom)
6202 goto error;
6203
6204 if (isl_map_plain_is_empty(map)) {
6205 if (empty)
6206 *empty = dom;
6207 else
6208 isl_set_free(dom);
6209 return isl_pw_multi_aff_from_map(map);
6210 }
6211
6212 res = basic_map_partial_lexopt_pw_multi_aff(
6213 isl_basic_map_copy(map->p[0]),
6214 isl_set_copy(dom), &todo, max);
6215
6216 for (i = 1; i < map->n; ++i) {
6217 isl_pw_multi_aff *res_i;
6218 isl_set *todo_i;
6219
6220 res_i = basic_map_partial_lexopt_pw_multi_aff(
6221 isl_basic_map_copy(map->p[i]),
6222 isl_set_copy(dom), &todo_i, max);
6223
6224 if (max)
6225 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6226 else
6227 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6228
6229 todo = isl_set_intersect(todo, todo_i);
6230 }
6231
6232 isl_set_free(dom);
6233 isl_map_free(map);
6234
6235 if (empty)
6236 *empty = todo;
6237 else
6238 isl_set_free(todo);
6239
6240 return res;
6241error:
6242 if (empty)
6243 *empty = NULL;
6244 isl_set_free(dom);
6245 isl_map_free(map);
6246 return NULL;
6247}
6248
6249#undef TYPE
6250#define TYPE isl_map
6251#undef SUFFIX
6252#define SUFFIX
6253#undef EMPTY
6254#define EMPTY isl_map_empty
6255#undef ADD
6256#define ADD isl_map_union_disjoint
6257#include "isl_map_lexopt_templ.c"
6258
6259/* Given a map "map", compute the lexicographically minimal
6260 * (or maximal) image element for each domain element in dom.
6261 * Set *empty to those elements in dom that do not have an image element.
6262 *
6263 * We first compute the lexicographically minimal or maximal element
6264 * in the first basic map. This results in a partial solution "res"
6265 * and a subset "todo" of dom that still need to be handled.
6266 * We then consider each of the remaining maps in "map" and successively
6267 * update both "res" and "todo".
6268 *
6269 * Let res^k and todo^k be the results after k steps and let i = k + 1.
6270 * Assume we are computing the lexicographical maximum.
6271 * We first compute the lexicographically maximal element in basic map i.
6272 * This results in a partial solution res_i and a subset todo_i.
6273 * Then we combine these results with those obtain for the first k basic maps
6274 * to obtain a result that is valid for the first k+1 basic maps.
6275 * In particular, the set where there is no solution is the set where
6276 * there is no solution for the first k basic maps and also no solution
6277 * for the ith basic map, i.e.,
6278 *
6279 * todo^i = todo^k * todo_i
6280 *
6281 * On dom(res^k) * dom(res_i), we need to pick the larger of the two
6282 * solutions, arbitrarily breaking ties in favor of res^k.
6283 * That is, when res^k(a) >= res_i(a), we pick res^k and
6284 * when res^k(a) < res_i(a), we pick res_i. (Here, ">=" and "<" denote
6285 * the lexicographic order.)
6286 * In practice, we compute
6287 *
6288 * res^k * (res_i . "<=")
6289 *
6290 * and
6291 *
6292 * res_i * (res^k . "<")
6293 *
6294 * Finally, we consider the symmetric difference of dom(res^k) and dom(res_i),
6295 * where only one of res^k and res_i provides a solution and we simply pick
6296 * that one, i.e.,
6297 *
6298 * res^k * todo_i
6299 * and
6300 * res_i * todo^k
6301 *
6302 * Note that we only compute these intersections when dom(res^k) intersects
6303 * dom(res_i). Otherwise, the only effect of these intersections is to
6304 * potentially break up res^k and res_i into smaller pieces.
6305 * We want to avoid such splintering as much as possible.
6306 * In fact, an earlier implementation of this function would look for
6307 * better results in the domain of res^k and for extra results in todo^k,
6308 * but this would always result in a splintering according to todo^k,
6309 * even when the domain of basic map i is disjoint from the domains of
6310 * the previous basic maps.
6311 */
6312static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6313 __isl_take isl_map *map, __isl_take isl_set *dom,
6314 __isl_give isl_set **empty, int max)
6315{
6316 int i;
6317 struct isl_map *res;
6318 struct isl_set *todo;
6319
6320 if (!map || !dom)
6321 goto error;
6322
6323 if (isl_map_plain_is_empty(map)) {
6324 if (empty)
6325 *empty = dom;
6326 else
6327 isl_set_free(dom);
6328 return map;
6329 }
6330
6331 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6332 isl_set_copy(dom), &todo, max);
6333
6334 for (i = 1; i < map->n; ++i) {
6335 isl_map *lt, *le;
6336 isl_map *res_i;
6337 isl_set *todo_i;
6338 isl_space *dim = isl_space_range(isl_map_get_space(res));
6339
6340 res_i = basic_map_partial_lexopt(isl_basic_map_copy(map->p[i]),
6341 isl_set_copy(dom), &todo_i, max);
6342
6343 if (max) {
6344 lt = isl_map_lex_lt(isl_space_copy(dim));
6345 le = isl_map_lex_le(dim);
6346 } else {
6347 lt = isl_map_lex_gt(isl_space_copy(dim));
6348 le = isl_map_lex_ge(dim);
6349 }
6350 lt = isl_map_apply_range(isl_map_copy(res), lt);
6351 lt = isl_map_intersect(lt, isl_map_copy(res_i));
6352 le = isl_map_apply_range(isl_map_copy(res_i), le);
6353 le = isl_map_intersect(le, isl_map_copy(res));
6354
6355 if (!isl_map_is_empty(lt) || !isl_map_is_empty(le)) {
6356 res = isl_map_intersect_domain(res,
6357 isl_set_copy(todo_i));
6358 res_i = isl_map_intersect_domain(res_i,
6359 isl_set_copy(todo));
6360 }
6361
6362 res = isl_map_union_disjoint(res, res_i);
6363 res = isl_map_union_disjoint(res, lt);
6364 res = isl_map_union_disjoint(res, le);
6365
6366 todo = isl_set_intersect(todo, todo_i);
6367 }
6368
6369 isl_set_free(dom);
6370 isl_map_free(map);
6371
6372 if (empty)
6373 *empty = todo;
6374 else
6375 isl_set_free(todo);
6376
6377 return res;
6378error:
6379 if (empty)
6380 *empty = NULL;
6381 isl_set_free(dom);
6382 isl_map_free(map);
6383 return NULL;
6384}
6385
6386__isl_give isl_map *isl_map_partial_lexmax(
6387 __isl_take isl_map *map, __isl_take isl_set *dom,
6388 __isl_give isl_set **empty)
6389{
6390 return isl_map_partial_lexopt(map, dom, empty, 1);
6391}
6392
6393__isl_give isl_map *isl_map_partial_lexmin(
6394 __isl_take isl_map *map, __isl_take isl_set *dom,
6395 __isl_give isl_set **empty)
6396{
6397 return isl_map_partial_lexopt(map, dom, empty, 0);
6398}
6399
6400__isl_give isl_set *isl_set_partial_lexmin(
6401 __isl_take isl_set *set, __isl_take isl_set *dom,
6402 __isl_give isl_set **empty)
6403{
6404 return (struct isl_set *)
6405 isl_map_partial_lexmin((struct isl_map *)set,
6406 dom, empty);
6407}
6408
6409__isl_give isl_set *isl_set_partial_lexmax(
6410 __isl_take isl_set *set, __isl_take isl_set *dom,
6411 __isl_give isl_set **empty)
6412{
6413 return (struct isl_set *)
6414 isl_map_partial_lexmax((struct isl_map *)set,
6415 dom, empty);
6416}
6417
6418/* Compute the lexicographic minimum (or maximum if "max" is set)
6419 * of "bmap" over its domain.
6420 *
6421 * Since we are not interested in the part of the domain space where
6422 * there is no solution, we initialize the domain to those constraints
6423 * of "bmap" that only involve the parameters and the input dimensions.
6424 * This relieves the parametric programming engine from detecting those
6425 * inequalities and transferring them to the context. More importantly,
6426 * it ensures that those inequalities are transferred first and not
6427 * intermixed with inequalities that actually split the domain.
6428 */
6429__isl_give isl_map *isl_basic_map_lexopt(__isl_take isl_basic_map *bmap, int max)
6430{
6431 int n_div;
6432 int n_out;
6433 isl_basic_map *copy;
6434 isl_basic_set *dom;
6435
6436 n_div = isl_basic_map_dim(bmap, isl_dim_div);
6437 n_out = isl_basic_map_dim(bmap, isl_dim_out);
6438 copy = isl_basic_map_copy(bmap);
6439 copy = isl_basic_map_drop_constraints_involving_dims(copy,
6440 isl_dim_div, 0, n_div);
6441 copy = isl_basic_map_drop_constraints_involving_dims(copy,
6442 isl_dim_out, 0, n_out);
6443 dom = isl_basic_map_domain(copy);
6444 return isl_basic_map_partial_lexopt(bmap, dom, NULL, max);
6445}
6446
6447__isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap)
6448{
6449 return isl_basic_map_lexopt(bmap, 0);
6450}
6451
6452__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6453{
6454 return isl_basic_map_lexopt(bmap, 1);
6455}
6456
6457__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6458{
6459 return (isl_set *)isl_basic_map_lexmin((isl_basic_map *)bset);
6460}
6461
6462__isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6463{
6464 return (isl_set *)isl_basic_map_lexmax((isl_basic_map *)bset);
6465}
6466
6467/* Extract the first and only affine expression from list
6468 * and then add it to *pwaff with the given dom.
6469 * This domain is known to be disjoint from other domains
6470 * because of the way isl_basic_map_foreach_lexmax works.
6471 */
6472static int update_dim_opt(__isl_take isl_basic_set *dom,
6473 __isl_take isl_aff_list *list, void *user)
6474{
6475 isl_ctx *ctx = isl_basic_set_get_ctx(dom);
6476 isl_aff *aff;
6477 isl_pw_aff **pwaff = user;
6478 isl_pw_aff *pwaff_i;
6479
6480 if (!list)
6481 goto error;
6482 if (isl_aff_list_n_aff(list) != 1)
6483 isl_die(ctx, isl_error_internal,
6484 "expecting single element list", goto error);
6485
6486 aff = isl_aff_list_get_aff(list, 0);
6487 pwaff_i = isl_pw_aff_alloc(isl_set_from_basic_set(dom), aff);
6488
6489 *pwaff = isl_pw_aff_add_disjoint(*pwaff, pwaff_i);
6490
6491 isl_aff_list_free(list);
6492
6493 return 0;
6494error:
6495 isl_basic_set_free(dom);
6496 isl_aff_list_free(list);
6497 return -1;
6498}
6499
6500/* Given a basic map with one output dimension, compute the minimum or
6501 * maximum of that dimension as an isl_pw_aff.
6502 *
6503 * The isl_pw_aff is constructed by having isl_basic_map_foreach_lexopt
6504 * call update_dim_opt on each leaf of the result.
6505 */
6506static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6507 int max)
6508{
6509 isl_space *dim = isl_basic_map_get_space(bmap);
6510 isl_pw_aff *pwaff;
6511 int r;
6512
6513 dim = isl_space_from_domain(isl_space_domain(dim));
6514 dim = isl_space_add_dims(dim, isl_dim_out, 1);
6515 pwaff = isl_pw_aff_empty(dim);
6516
6517 r = isl_basic_map_foreach_lexopt(bmap, max, &update_dim_opt, &pwaff);
6518 if (r < 0)
6519 return isl_pw_aff_free(pwaff);
6520
6521 return pwaff;
6522}
6523
6524/* Compute the minimum or maximum of the given output dimension
6525 * as a function of the parameters and the input dimensions,
6526 * but independently of the other output dimensions.
6527 *
6528 * We first project out the other output dimension and then compute
6529 * the "lexicographic" maximum in each basic map, combining the results
6530 * using isl_pw_aff_union_max.
6531 */
6532static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6533 int max)
6534{
6535 int i;
6536 isl_pw_aff *pwaff;
6537 unsigned n_out;
6538
6539 n_out = isl_map_dim(map, isl_dim_out);
6540 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6541 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6542 if (!map)
6543 return NULL;
6544
6545 if (map->n == 0) {
6546 isl_space *dim = isl_map_get_space(map);
6547 isl_map_free(map);
6548 return isl_pw_aff_empty(dim);
6549 }
6550
6551 pwaff = basic_map_dim_opt(map->p[0], max);
6552 for (i = 1; i < map->n; ++i) {
6553 isl_pw_aff *pwaff_i;
6554
6555 pwaff_i = basic_map_dim_opt(map->p[i], max);
6556 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6557 }
6558
6559 isl_map_free(map);
6560
6561 return pwaff;
6562}
6563
6564/* Compute the maximum of the given output dimension as a function of the
6565 * parameters and input dimensions, but independently of
6566 * the other output dimensions.
6567 */
6568__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6569{
6570 return map_dim_opt(map, pos, 1);
6571}
6572
6573/* Compute the minimum or maximum of the given set dimension
6574 * as a function of the parameters,
6575 * but independently of the other set dimensions.
6576 */
6577static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
6578 int max)
6579{
6580 return map_dim_opt(set, pos, max);
6581}
6582
6583/* Compute the maximum of the given set dimension as a function of the
6584 * parameters, but independently of the other set dimensions.
6585 */
6586__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
6587{
6588 return set_dim_opt(set, pos, 1);
6589}
6590
6591/* Compute the minimum of the given set dimension as a function of the
6592 * parameters, but independently of the other set dimensions.
6593 */
6594__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
6595{
6596 return set_dim_opt(set, pos, 0);
6597}
6598
6599/* Apply a preimage specified by "mat" on the parameters of "bset".
6600 * bset is assumed to have only parameters and divs.
6601 */
6602static struct isl_basic_set *basic_set_parameter_preimage(
6603 struct isl_basic_set *bset, struct isl_mat *mat)
6604{
6605 unsigned nparam;
6606
6607 if (!bset || !mat)
6608 goto error;
6609
6610 bset->dim = isl_space_cow(bset->dim);
6611 if (!bset->dim)
6612 goto error;
6613
6614 nparam = isl_basic_set_dim(bset, isl_dim_param);
6615
6616 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
6617
6618 bset->dim->nparam = 0;
6619 bset->dim->n_out = nparam;
6620 bset = isl_basic_set_preimage(bset, mat);
6621 if (bset) {
6622 bset->dim->nparam = bset->dim->n_out;
6623 bset->dim->n_out = 0;
6624 }
6625 return bset;
6626error:
6627 isl_mat_free(mat);
6628 isl_basic_set_free(bset);
6629 return NULL;
6630}
6631
6632/* Apply a preimage specified by "mat" on the parameters of "set".
6633 * set is assumed to have only parameters and divs.
6634 */
6635static struct isl_set *set_parameter_preimage(
6636 struct isl_set *set, struct isl_mat *mat)
6637{
6638 isl_space *dim = NULL;
6639 unsigned nparam;
6640
6641 if (!set || !mat)
6642 goto error;
6643
6644 dim = isl_space_copy(set->dim);
6645 dim = isl_space_cow(dim);
6646 if (!dim)
6647 goto error;
6648
6649 nparam = isl_set_dim(set, isl_dim_param);
6650
6651 isl_assert(set->ctx, mat->n_row == 1 + nparam, goto error);
6652
6653 dim->nparam = 0;
6654 dim->n_out = nparam;
6655 isl_set_reset_space(set, dim);
6656 set = isl_set_preimage(set, mat);
6657 if (!set)
6658 goto error2;
6659 dim = isl_space_copy(set->dim);
6660 dim = isl_space_cow(dim);
6661 if (!dim)
6662 goto error2;
6663 dim->nparam = dim->n_out;
6664 dim->n_out = 0;
6665 isl_set_reset_space(set, dim);
6666 return set;
6667error:
6668 isl_space_free(dim);
6669 isl_mat_free(mat);
6670error2:
6671 isl_set_free(set);
6672 return NULL;
6673}
6674
6675/* Intersect the basic set "bset" with the affine space specified by the
6676 * equalities in "eq".
6677 */
6678static struct isl_basic_set *basic_set_append_equalities(
6679 struct isl_basic_set *bset, struct isl_mat *eq)
6680{
6681 int i, k;
6682 unsigned len;
6683
6684 if (!bset || !eq)
6685 goto error;
6686
6687 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
6688 eq->n_row, 0);
6689 if (!bset)
6690 goto error;
6691
6692 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
6693 for (i = 0; i < eq->n_row; ++i) {
6694 k = isl_basic_set_alloc_equality(bset);
6695 if (k < 0)
6696 goto error;
6697 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
6698 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
6699 }
6700 isl_mat_free(eq);
6701
6702 bset = isl_basic_set_gauss(bset, NULL);
6703 bset = isl_basic_set_finalize(bset);
6704
6705 return bset;
6706error:
6707 isl_mat_free(eq);
6708 isl_basic_set_free(bset);
6709 return NULL;
6710}
6711
6712/* Intersect the set "set" with the affine space specified by the
6713 * equalities in "eq".
6714 */
6715static struct isl_set *set_append_equalities(struct isl_set *set,
6716 struct isl_mat *eq)
6717{
6718 int i;
6719
6720 if (!set || !eq)
6721 goto error;
6722
6723 for (i = 0; i < set->n; ++i) {
6724 set->p[i] = basic_set_append_equalities(set->p[i],
6725 isl_mat_copy(eq));
6726 if (!set->p[i])
6727 goto error;
6728 }
6729 isl_mat_free(eq);
6730 return set;
6731error:
6732 isl_mat_free(eq);
6733 isl_set_free(set);
6734 return NULL;
6735}
6736
6737/* Given a basic set "bset" that only involves parameters and existentially
6738 * quantified variables, return the index of the first equality
6739 * that only involves parameters. If there is no such equality then
6740 * return bset->n_eq.
6741 *
6742 * This function assumes that isl_basic_set_gauss has been called on "bset".
6743 */
6744static int first_parameter_equality(__isl_keep isl_basic_set *bset)
6745{
6746 int i, j;
6747 unsigned nparam, n_div;
6748
6749 if (!bset)
6750 return -1;
6751
6752 nparam = isl_basic_set_dim(bset, isl_dim_param);
6753 n_div = isl_basic_set_dim(bset, isl_dim_div);
6754
6755 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
6756 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
6757 ++i;
6758 }
6759
6760 return i;
6761}
6762
6763/* Compute an explicit representation for the existentially quantified
6764 * variables in "bset" by computing the "minimal value" of the set
6765 * variables. Since there are no set variables, the computation of
6766 * the minimal value essentially computes an explicit representation
6767 * of the non-empty part(s) of "bset".
6768 *
6769 * The input only involves parameters and existentially quantified variables.
6770 * All equalities among parameters have been removed.
6771 *
6772 * Since the existentially quantified variables in the result are in general
6773 * going to be different from those in the input, we first replace
6774 * them by the minimal number of variables based on their equalities.
6775 * This should simplify the parametric integer programming.
6776 */
6777static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
6778{
6779 isl_morph *morph1, *morph2;
6780 isl_set *set;
6781 unsigned n;
6782
6783 if (!bset)
6784 return NULL;
6785 if (bset->n_eq == 0)
6786 return isl_basic_set_lexmin(bset);
6787
6788 morph1 = isl_basic_set_parameter_compression(bset);
6789 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
6790 bset = isl_basic_set_lift(bset);
6791 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
6792 bset = isl_morph_basic_set(morph2, bset);
6793 n = isl_basic_set_dim(bset, isl_dim_set);
6794 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
6795
6796 set = isl_basic_set_lexmin(bset);
6797
6798 set = isl_morph_set(isl_morph_inverse(morph1), set);
6799
6800 return set;
6801}
6802
6803/* Project the given basic set onto its parameter domain, possibly introducing
6804 * new, explicit, existential variables in the constraints.
6805 * The input has parameters and (possibly implicit) existential variables.
6806 * The output has the same parameters, but only
6807 * explicit existentially quantified variables.
6808 *
6809 * The actual projection is performed by pip, but pip doesn't seem
6810 * to like equalities very much, so we first remove the equalities
6811 * among the parameters by performing a variable compression on
6812 * the parameters. Afterward, an inverse transformation is performed
6813 * and the equalities among the parameters are inserted back in.
6814 *
6815 * The variable compression on the parameters may uncover additional
6816 * equalities that were only implicit before. We therefore check
6817 * if there are any new parameter equalities in the result and
6818 * if so recurse. The removal of parameter equalities is required
6819 * for the parameter compression performed by base_compute_divs.
6820 */
6821static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
6822{
6823 int i;
6824 struct isl_mat *eq;
6825 struct isl_mat *T, *T2;
6826 struct isl_set *set;
6827 unsigned nparam;
6828
6829 bset = isl_basic_set_cow(bset);
6830 if (!bset)
6831 return NULL;
6832
6833 if (bset->n_eq == 0)
6834 return base_compute_divs(bset);
6835
6836 bset = isl_basic_set_gauss(bset, NULL);
6837 if (!bset)
6838 return NULL;
6839 if (isl_basic_set_plain_is_empty(bset))
6840 return isl_set_from_basic_set(bset);
6841
6842 i = first_parameter_equality(bset);
6843 if (i == bset->n_eq)
6844 return base_compute_divs(bset);
6845
6846 nparam = isl_basic_set_dim(bset, isl_dim_param);
6847 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
6848 0, 1 + nparam);
6849 eq = isl_mat_cow(eq);
6850 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
6851 if (T && T->n_col == 0) {
6852 isl_mat_free(T);
6853 isl_mat_free(T2);
6854 isl_mat_free(eq);
6855 bset = isl_basic_set_set_to_empty(bset);
6856 return isl_set_from_basic_set(bset);
6857 }
6858 bset = basic_set_parameter_preimage(bset, T);
6859
6860 i = first_parameter_equality(bset);
6861 if (!bset)
6862 set = NULL;
6863 else if (i == bset->n_eq)
6864 set = base_compute_divs(bset);
6865 else
6866 set = parameter_compute_divs(bset);
6867 set = set_parameter_preimage(set, T2);
6868 set = set_append_equalities(set, eq);
6869 return set;
6870}
6871
6872/* Insert the divs from "ls" before those of "bmap".
6873 *
6874 * The number of columns is not changed, which means that the last
6875 * dimensions of "bmap" are being reintepreted as the divs from "ls".
6876 * The caller is responsible for removing the same number of dimensions
6877 * from the space of "bmap".
6878 */
6879static __isl_give isl_basic_map *insert_divs_from_local_space(
6880 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
6881{
6882 int i;
6883 int n_div;
6884 int old_n_div;
6885
6886 n_div = isl_local_space_dim(ls, isl_dim_div);
6887 if (n_div == 0)
6888 return bmap;
6889
6890 old_n_div = bmap->n_div;
6891 bmap = insert_div_rows(bmap, n_div);
6892 if (!bmap)
6893 return NULL;
6894
6895 for (i = 0; i < n_div; ++i) {
6896 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
6897 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
6898 }
6899
6900 return bmap;
6901}
6902
6903/* Replace the space of "bmap" by the space and divs of "ls".
6904 *
6905 * If "ls" has any divs, then we simplify the result since we may
6906 * have discovered some additional equalities that could simplify
6907 * the div expressions.
6908 */
6909static __isl_give isl_basic_map *basic_replace_space_by_local_space(
6910 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
6911{
6912 int n_div;
6913
6914 bmap = isl_basic_map_cow(bmap);
6915 if (!bmap || !ls)
6916 goto error;
6917
6918 n_div = isl_local_space_dim(ls, isl_dim_div);
6919 bmap = insert_divs_from_local_space(bmap, ls);
6920 if (!bmap)
6921 goto error;
6922
6923 isl_space_free(bmap->dim);
6924 bmap->dim = isl_local_space_get_space(ls);
6925 if (!bmap->dim)
6926 goto error;
6927
6928 isl_local_space_free(ls);
6929 if (n_div > 0)
6930 bmap = isl_basic_map_simplify(bmap);
6931 bmap = isl_basic_map_finalize(bmap);
6932 return bmap;
6933error:
6934 isl_basic_map_free(bmap);
6935 isl_local_space_free(ls);
6936 return NULL;
6937}
6938
6939/* Replace the space of "map" by the space and divs of "ls".
6940 */
6941static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
6942 __isl_take isl_local_space *ls)
6943{
6944 int i;
6945
6946 map = isl_map_cow(map);
6947 if (!map || !ls)
6948 goto error;
6949
6950 for (i = 0; i < map->n; ++i) {
6951 map->p[i] = basic_replace_space_by_local_space(map->p[i],
6952 isl_local_space_copy(ls));
6953 if (!map->p[i])
6954 goto error;
6955 }
6956 isl_space_free(map->dim);
6957 map->dim = isl_local_space_get_space(ls);
6958 if (!map->dim)
6959 goto error;
6960
6961 isl_local_space_free(ls);
6962 return map;
6963error:
6964 isl_local_space_free(ls);
6965 isl_map_free(map);
6966 return NULL;
6967}
6968
6969/* Compute an explicit representation for the existentially
6970 * quantified variables for which do not know any explicit representation yet.
6971 *
6972 * We first sort the existentially quantified variables so that the
6973 * existentially quantified variables for which we already have an explicit
6974 * representation are placed before those for which we do not.
6975 * The input dimensions, the output dimensions and the existentially
6976 * quantified variables for which we already have an explicit
6977 * representation are then turned into parameters.
6978 * compute_divs returns a map with the same parameters and
6979 * no input or output dimensions and the dimension specification
6980 * is reset to that of the input, including the existentially quantified
6981 * variables for which we already had an explicit representation.
6982 */
6983static struct isl_map *compute_divs(struct isl_basic_map *bmap)
6984{
6985 struct isl_basic_set *bset;
6986 struct isl_set *set;
6987 struct isl_map *map;
6988 isl_space *dim;
6989 isl_local_space *ls;
6990 unsigned nparam;
6991 unsigned n_in;
6992 unsigned n_out;
6993 unsigned n_known;
6994 int i;
6995
6996 bmap = isl_basic_map_sort_divs(bmap);
6997 bmap = isl_basic_map_cow(bmap);
6998 if (!bmap)
6999 return NULL;
7000
7001 for (n_known = 0; n_known < bmap->n_div; ++n_known)
7002 if (isl_int_is_zero(bmap->div[n_known][0]))
7003 break;
7004
7005 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7006 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7007 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7008 dim = isl_space_set_alloc(bmap->ctx,
7009 nparam + n_in + n_out + n_known, 0);
7010 if (!dim)
7011 goto error;
7012
7013 ls = isl_basic_map_get_local_space(bmap);
7014 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7015 n_known, bmap->n_div - n_known);
7016 if (n_known > 0) {
7017 for (i = n_known; i < bmap->n_div; ++i)
7018 swap_div(bmap, i - n_known, i);
7019 bmap->n_div -= n_known;
7020 bmap->extra -= n_known;
7021 }
7022 bmap = isl_basic_map_reset_space(bmap, dim);
7023 bset = (struct isl_basic_set *)bmap;
7024
7025 set = parameter_compute_divs(bset);
7026 map = (struct isl_map *)set;
7027 map = replace_space_by_local_space(map, ls);
7028
7029 return map;
7030error:
7031 isl_basic_map_free(bmap);
7032 return NULL;
7033}
7034
7035int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7036{
7037 int i;
7038 unsigned off;
7039
7040 if (!bmap)
7041 return -1;
7042
7043 off = isl_space_dim(bmap->dim, isl_dim_all);
7044 for (i = 0; i < bmap->n_div; ++i) {
7045 if (isl_int_is_zero(bmap->div[i][0]))
7046 return 0;
7047 isl_assert(bmap->ctx, isl_int_is_zero(bmap->div[i][1+1+off+i]),
7048 return -1);
7049 }
7050 return 1;
7051}
7052
7053static int map_divs_known(__isl_keep isl_map *map)
7054{
7055 int i;
7056
7057 if (!map)
7058 return -1;
7059
7060 for (i = 0; i < map->n; ++i) {
7061 int known = isl_basic_map_divs_known(map->p[i]);
7062 if (known <= 0)
7063 return known;
7064 }
7065
7066 return 1;
7067}
7068
7069/* If bmap contains any unknown divs, then compute explicit
7070 * expressions for them. However, this computation may be
7071 * quite expensive, so first try to remove divs that aren't
7072 * strictly needed.
7073 */
7074struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap)
7075{
7076 int known;
7077 struct isl_map *map;
7078
7079 known = isl_basic_map_divs_known(bmap);
7080 if (known < 0)
7081 goto error;
7082 if (known)
7083 return isl_map_from_basic_map(bmap);
7084
7085 bmap = isl_basic_map_drop_redundant_divs(bmap);
7086
7087 known = isl_basic_map_divs_known(bmap);
7088 if (known < 0)
7089 goto error;
7090 if (known)
7091 return isl_map_from_basic_map(bmap);
7092
7093 map = compute_divs(bmap);
7094 return map;
7095error:
7096 isl_basic_map_free(bmap);
7097 return NULL;
7098}
7099
7100struct isl_map *isl_map_compute_divs(struct isl_map *map)
7101{
7102 int i;
7103 int known;
7104 struct isl_map *res;
7105
7106 if (!map)
7107 return NULL;
7108 if (map->n == 0)
7109 return map;
7110
7111 known = map_divs_known(map);
7112 if (known < 0) {
7113 isl_map_free(map);
7114 return NULL;
7115 }
7116 if (known)
7117 return map;
7118
7119 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7120 for (i = 1 ; i < map->n; ++i) {
7121 struct isl_map *r2;
7122 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7123 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7124 res = isl_map_union_disjoint(res, r2);
7125 else
7126 res = isl_map_union(res, r2);
7127 }
7128 isl_map_free(map);
7129
7130 return res;
7131}
7132
7133struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset)
7134{
7135 return (struct isl_set *)
7136 isl_basic_map_compute_divs((struct isl_basic_map *)bset);
7137}
7138
7139struct isl_set *isl_set_compute_divs(struct isl_set *set)
7140{
7141 return (struct isl_set *)
7142 isl_map_compute_divs((struct isl_map *)set);
7143}
7144
7145struct isl_set *isl_map_domain(struct isl_map *map)
7146{
7147 int i;
7148 struct isl_set *set;
7149
7150 if (!map)
7151 goto error;
7152
7153 map = isl_map_cow(map);
7154 if (!map)
7155 return NULL;
7156
7157 set = (struct isl_set *)map;
7158 set->dim = isl_space_domain(set->dim);
7159 if (!set->dim)
7160 goto error;
7161 for (i = 0; i < map->n; ++i) {
7162 set->p[i] = isl_basic_map_domain(map->p[i]);
7163 if (!set->p[i])
7164 goto error;
7165 }
7166 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7167 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7168 return set;
7169error:
7170 isl_map_free(map);
7171 return NULL;
7172}
7173
7174/* Return the union of "map1" and "map2", where we assume for now that
7175 * "map1" and "map2" are disjoint. Note that the basic maps inside
7176 * "map1" or "map2" may not be disjoint from each other.
7177 * Also note that this function is also called from isl_map_union,
7178 * which takes care of handling the situation where "map1" and "map2"
7179 * may not be disjoint.
7180 *
7181 * If one of the inputs is empty, we can simply return the other input.
7182 * Similarly, if one of the inputs is universal, then it is equal to the union.
7183 */
7184static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7185 __isl_take isl_map *map2)
7186{
7187 int i;
7188 unsigned flags = 0;
7189 struct isl_map *map = NULL;
7190 int is_universe;
7191
7192 if (!map1 || !map2)
7193 goto error;
7194
7195 if (!isl_space_is_equal(map1->dim, map2->dim))
7196 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7197 "spaces don't match", goto error);
7198
7199 if (map1->n == 0) {
7200 isl_map_free(map1);
7201 return map2;
7202 }
7203 if (map2->n == 0) {
7204 isl_map_free(map2);
7205 return map1;
7206 }
7207
7208 is_universe = isl_map_plain_is_universe(map1);
7209 if (is_universe < 0)
7210 goto error;
7211 if (is_universe) {
7212 isl_map_free(map2);
7213 return map1;
7214 }
7215
7216 is_universe = isl_map_plain_is_universe(map2);
7217 if (is_universe < 0)
7218 goto error;
7219 if (is_universe) {
7220 isl_map_free(map1);
7221 return map2;
7222 }
7223
7224 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7225 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7226 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7227
7228 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7229 map1->n + map2->n, flags);
7230 if (!map)
7231 goto error;
7232 for (i = 0; i < map1->n; ++i) {
7233 map = isl_map_add_basic_map(map,
7234 isl_basic_map_copy(map1->p[i]));
7235 if (!map)
7236 goto error;
7237 }
7238 for (i = 0; i < map2->n; ++i) {
7239 map = isl_map_add_basic_map(map,
7240 isl_basic_map_copy(map2->p[i]));
7241 if (!map)
7242 goto error;
7243 }
7244 isl_map_free(map1);
7245 isl_map_free(map2);
7246 return map;
7247error:
7248 isl_map_free(map);
7249 isl_map_free(map1);
7250 isl_map_free(map2);
7251 return NULL;
7252}
7253
7254/* Return the union of "map1" and "map2", where "map1" and "map2" are
7255 * guaranteed to be disjoint by the caller.
7256 *
7257 * Note that this functions is called from within isl_map_make_disjoint,
7258 * so we have to be careful not to touch the constraints of the inputs
7259 * in any way.
7260 */
7261__isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7262 __isl_take isl_map *map2)
7263{
7264 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7265}
7266
7267/* Return the union of "map1" and "map2", where "map1" and "map2" may
7268 * not be disjoint. The parameters are assumed to have been aligned.
7269 *
7270 * We currently simply call map_union_disjoint, the internal operation
7271 * of which does not really depend on the inputs being disjoint.
7272 * If the result contains more than one basic map, then we clear
7273 * the disjoint flag since the result may contain basic maps from
7274 * both inputs and these are not guaranteed to be disjoint.
7275 *
7276 * As a special case, if "map1" and "map2" are obviously equal,
7277 * then we simply return "map1".
7278 */
7279static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7280 __isl_take isl_map *map2)
7281{
7282 int equal;
7283
7284 if (!map1 || !map2)
7285 goto error;
7286
7287 equal = isl_map_plain_is_equal(map1, map2);
7288 if (equal < 0)
7289 goto error;
7290 if (equal) {
7291 isl_map_free(map2);
7292 return map1;
7293 }
7294
7295 map1 = map_union_disjoint(map1, map2);
7296 if (!map1)
7297 return NULL;
7298 if (map1->n > 1)
7299 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7300 return map1;
7301error:
7302 isl_map_free(map1);
7303 isl_map_free(map2);
7304 return NULL;
7305}
7306
7307/* Return the union of "map1" and "map2", where "map1" and "map2" may
7308 * not be disjoint.
7309 */
7310__isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7311 __isl_take isl_map *map2)
7312{
7313 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7314}
7315
7316struct isl_set *isl_set_union_disjoint(
7317 struct isl_set *set1, struct isl_set *set2)
7318{
7319 return (struct isl_set *)
7320 isl_map_union_disjoint(
7321 (struct isl_map *)set1, (struct isl_map *)set2);
7322}
7323
7324struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7325{
7326 return (struct isl_set *)
7327 isl_map_union((struct isl_map *)set1, (struct isl_map *)set2);
7328}
7329
7330/* Apply "fn" to pairs of elements from "map" and "set" and collect
7331 * the results.
7332 *
7333 * "map" and "set" are assumed to be compatible and non-NULL.
7334 */
7335static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7336 __isl_take isl_set *set,
7337 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7338 __isl_take isl_basic_set *bset))
7339{
7340 unsigned flags = 0;
7341 struct isl_map *result;
7342 int i, j;
7343
7344 if (isl_set_plain_is_universe(set)) {
7345 isl_set_free(set);
7346 return map;
7347 }
7348
7349 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7350 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7351 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7352
7353 result = isl_map_alloc_space(isl_space_copy(map->dim),
7354 map->n * set->n, flags);
7355 for (i = 0; result && i < map->n; ++i)
7356 for (j = 0; j < set->n; ++j) {
7357 result = isl_map_add_basic_map(result,
7358 fn(isl_basic_map_copy(map->p[i]),
7359 isl_basic_set_copy(set->p[j])));
7360 if (!result)
7361 break;
7362 }
7363
7364 isl_map_free(map);
7365 isl_set_free(set);
7366 return result;
7367}
7368
7369static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7370 __isl_take isl_set *set)
7371{
7372 if (!map || !set)
7373 goto error;
7374
7375 if (!isl_map_compatible_range(map, set))
7376 isl_die(set->ctx, isl_error_invalid,
7377 "incompatible spaces", goto error);
7378
7379 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7380error:
7381 isl_map_free(map);
7382 isl_set_free(set);
7383 return NULL;
7384}
7385
7386__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7387 __isl_take isl_set *set)
7388{
7389 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7390}
7391
7392static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7393 __isl_take isl_set *set)
7394{
7395 if (!map || !set)
7396 goto error;
7397
7398 if (!isl_map_compatible_domain(map, set))
7399 isl_die(set->ctx, isl_error_invalid,
7400 "incompatible spaces", goto error);
7401
7402 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7403error:
7404 isl_map_free(map);
7405 isl_set_free(set);
7406 return NULL;
7407}
7408
7409__isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7410 __isl_take isl_set *set)
7411{
7412 return isl_map_align_params_map_map_and(map, set,
7413 &map_intersect_domain);
7414}
7415
7416static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7417 __isl_take isl_map *map2)
7418{
7419 if (!map1 || !map2)
7420 goto error;
7421 map1 = isl_map_reverse(map1);
7422 map1 = isl_map_apply_range(map1, map2);
7423 return isl_map_reverse(map1);
7424error:
7425 isl_map_free(map1);
7426 isl_map_free(map2);
7427 return NULL;
7428}
7429
7430__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7431 __isl_take isl_map *map2)
7432{
7433 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7434}
7435
7436static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7437 __isl_take isl_map *map2)
7438{
7439 isl_space *dim_result;
7440 struct isl_map *result;
7441 int i, j;
7442
7443 if (!map1 || !map2)
7444 goto error;
7445
7446 dim_result = isl_space_join(isl_space_copy(map1->dim),
7447 isl_space_copy(map2->dim));
7448
7449 result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
7450 if (!result)
7451 goto error;
7452 for (i = 0; i < map1->n; ++i)
7453 for (j = 0; j < map2->n; ++j) {
7454 result = isl_map_add_basic_map(result,
7455 isl_basic_map_apply_range(
7456 isl_basic_map_copy(map1->p[i]),
7457 isl_basic_map_copy(map2->p[j])));
7458 if (!result)
7459 goto error;
7460 }
7461 isl_map_free(map1);
7462 isl_map_free(map2);
7463 if (result && result->n <= 1)
7464 ISL_F_SET(result, ISL_MAP_DISJOINT);
7465 return result;
7466error:
7467 isl_map_free(map1);
7468 isl_map_free(map2);
7469 return NULL;
7470}
7471
7472__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
7473 __isl_take isl_map *map2)
7474{
7475 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
7476}
7477
7478/*
7479 * returns range - domain
7480 */
7481struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap)
7482{
7483 isl_space *dims, *target_dim;
7484 struct isl_basic_set *bset;
7485 unsigned dim;
7486 unsigned nparam;
7487 int i;
7488
7489 if (!bmap)
7490 goto error;
7491 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7492 bmap->dim, isl_dim_out),
7493 goto error);
7494 target_dim = isl_space_domain(isl_basic_map_get_space(bmap));
7495 dim = isl_basic_map_n_in(bmap);
7496 nparam = isl_basic_map_n_param(bmap);
7497 bset = isl_basic_set_from_basic_map(bmap);
7498 bset = isl_basic_set_cow(bset);
7499 dims = isl_basic_set_get_space(bset);
7500 dims = isl_space_add_dims(dims, isl_dim_set, dim);
7501 bset = isl_basic_set_extend_space(bset, dims, 0, dim, 0);
7502 bset = isl_basic_set_swap_vars(bset, 2*dim);
7503 for (i = 0; i < dim; ++i) {
7504 int j = isl_basic_map_alloc_equality(
7505 (struct isl_basic_map *)bset);
7506 if (j < 0) {
7507 bset = isl_basic_set_free(bset);
7508 break;
7509 }
7510 isl_seq_clr(bset->eq[j], 1 + isl_basic_set_total_dim(bset));
7511 isl_int_set_si(bset->eq[j][1+nparam+i], 1);
7512 isl_int_set_si(bset->eq[j][1+nparam+dim+i], 1);
7513 isl_int_set_si(bset->eq[j][1+nparam+2*dim+i], -1);
7514 }
7515 bset = isl_basic_set_project_out(bset, isl_dim_set, dim, 2*dim);
7516 bset = isl_basic_set_reset_space(bset, target_dim);
7517 return bset;
7518error:
7519 isl_basic_map_free(bmap);
7520 return NULL;
7521}
7522
7523/*
7524 * returns range - domain
7525 */
7526__isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
7527{
7528 int i;
7529 isl_space *dim;
7530 struct isl_set *result;
7531
7532 if (!map)
7533 return NULL;
7534
7535 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
7536 map->dim, isl_dim_out),
7537 goto error);
7538 dim = isl_map_get_space(map);
7539 dim = isl_space_domain(dim);
7540 result = isl_set_alloc_space(dim, map->n, 0);
7541 if (!result)
7542 goto error;
7543 for (i = 0; i < map->n; ++i)
7544 result = isl_set_add_basic_set(result,
7545 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
7546 isl_map_free(map);
7547 return result;
7548error:
7549 isl_map_free(map);
7550 return NULL;
7551}
7552
7553/*
7554 * returns [domain -> range] -> range - domain
7555 */
7556__isl_give isl_basic_map *isl_basic_map_deltas_map(
7557 __isl_take isl_basic_map *bmap)
7558{
7559 int i, k;
7560 isl_space *dim;
7561 isl_basic_map *domain;
7562 int nparam, n;
7563 unsigned total;
7564
7565 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7566 bmap->dim, isl_dim_out))
7567 isl_die(bmap->ctx, isl_error_invalid,
7568 "domain and range don't match", goto error);
7569
7570 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7571 n = isl_basic_map_dim(bmap, isl_dim_in);
7572
7573 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
7574 domain = isl_basic_map_universe(dim);
7575
7576 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
7577 bmap = isl_basic_map_apply_range(bmap, domain);
7578 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
7579
7580 total = isl_basic_map_total_dim(bmap);
7581
7582 for (i = 0; i < n; ++i) {
7583 k = isl_basic_map_alloc_equality(bmap);
7584 if (k < 0)
7585 goto error;
7586 isl_seq_clr(bmap->eq[k], 1 + total);
7587 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
7588 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
7589 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
7590 }
7591
7592 bmap = isl_basic_map_gauss(bmap, NULL);
7593 return isl_basic_map_finalize(bmap);
7594error:
7595 isl_basic_map_free(bmap);
7596 return NULL;
7597}
7598
7599/*
7600 * returns [domain -> range] -> range - domain
7601 */
7602__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
7603{
7604 int i;
7605 isl_space *domain_dim;
7606
7607 if (!map)
7608 return NULL;
7609
7610 if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
7611 map->dim, isl_dim_out))
7612 isl_die(map->ctx, isl_error_invalid,
7613 "domain and range don't match", goto error);
7614
7615 map = isl_map_cow(map);
7616 if (!map)
7617 return NULL;
7618
7619 domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
7620 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
7621 map->dim = isl_space_join(map->dim, domain_dim);
7622 if (!map->dim)
7623 goto error;
7624 for (i = 0; i < map->n; ++i) {
7625 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
7626 if (!map->p[i])
7627 goto error;
7628 }
7629 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
7630 return map;
7631error:
7632 isl_map_free(map);
7633 return NULL;
7634}
7635
7636static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
7637{
7638 struct isl_basic_map *bmap;
7639 unsigned nparam;
7640 unsigned dim;
7641 int i;
7642
7643 if (!dims)
7644 return NULL;
7645
7646 nparam = dims->nparam;
7647 dim = dims->n_out;
7648 bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
7649 if (!bmap)
7650 goto error;
7651
7652 for (i = 0; i < dim; ++i) {
7653 int j = isl_basic_map_alloc_equality(bmap);
7654 if (j < 0)
7655 goto error;
7656 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7657 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7658 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
7659 }
7660 return isl_basic_map_finalize(bmap);
7661error:
7662 isl_basic_map_free(bmap);
7663 return NULL;
7664}
7665
7666__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
7667{
7668 if (!dim)
7669 return NULL;
7670 if (dim->n_in != dim->n_out)
7671 isl_die(dim->ctx, isl_error_invalid,
7672 "number of input and output dimensions needs to be "
7673 "the same", goto error);
7674 return basic_map_identity(dim);
7675error:
7676 isl_space_free(dim);
7677 return NULL;
7678}
7679
7680struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model)
7681{
7682 if (!model || !model->dim)
7683 return NULL;
7684 return isl_basic_map_identity(isl_space_copy(model->dim));
7685}
7686
7687__isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
7688{
7689 return isl_map_from_basic_map(isl_basic_map_identity(dim));
7690}
7691
7692struct isl_map *isl_map_identity_like(struct isl_map *model)
7693{
7694 if (!model || !model->dim)
7695 return NULL;
7696 return isl_map_identity(isl_space_copy(model->dim));
7697}
7698
7699struct isl_map *isl_map_identity_like_basic_map(struct isl_basic_map *model)
7700{
7701 if (!model || !model->dim)
7702 return NULL;
7703 return isl_map_identity(isl_space_copy(model->dim));
7704}
7705
7706__isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
7707{
7708 isl_space *dim = isl_set_get_space(set);
7709 isl_map *id;
7710 id = isl_map_identity(isl_space_map_from_set(dim));
7711 return isl_map_intersect_range(id, set);
7712}
7713
7714/* Construct a basic set with all set dimensions having only non-negative
7715 * values.
7716 */
7717__isl_give isl_basic_set *isl_basic_set_positive_orthant(
7718 __isl_take isl_space *space)
7719{
7720 int i;
7721 unsigned nparam;
7722 unsigned dim;
7723 struct isl_basic_set *bset;
7724
7725 if (!space)
7726 return NULL;
7727 nparam = space->nparam;
7728 dim = space->n_out;
7729 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
7730 if (!bset)
7731 return NULL;
7732 for (i = 0; i < dim; ++i) {
7733 int k = isl_basic_set_alloc_inequality(bset);
7734 if (k < 0)
7735 goto error;
7736 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
7737 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
7738 }
7739 return bset;
7740error:
7741 isl_basic_set_free(bset);
7742 return NULL;
7743}
7744
7745/* Construct the half-space x_pos >= 0.
7746 */
7747static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
7748 int pos)
7749{
7750 int k;
7751 isl_basic_set *nonneg;
7752
7753 nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7754 k = isl_basic_set_alloc_inequality(nonneg);
7755 if (k < 0)
7756 goto error;
7757 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
7758 isl_int_set_si(nonneg->ineq[k][pos], 1);
7759
7760 return isl_basic_set_finalize(nonneg);
7761error:
7762 isl_basic_set_free(nonneg);
7763 return NULL;
7764}
7765
7766/* Construct the half-space x_pos <= -1.
7767 */
7768static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
7769{
7770 int k;
7771 isl_basic_set *neg;
7772
7773 neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7774 k = isl_basic_set_alloc_inequality(neg);
7775 if (k < 0)
7776 goto error;
7777 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
7778 isl_int_set_si(neg->ineq[k][0], -1);
7779 isl_int_set_si(neg->ineq[k][pos], -1);
7780
7781 return isl_basic_set_finalize(neg);
7782error:
7783 isl_basic_set_free(neg);
7784 return NULL;
7785}
7786
7787__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
7788 enum isl_dim_type type, unsigned first, unsigned n)
7789{
7790 int i;
7791 isl_basic_set *nonneg;
7792 isl_basic_set *neg;
7793
7794 if (!set)
7795 return NULL;
7796 if (n == 0)
7797 return set;
7798
7799 isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
7800
7801 for (i = 0; i < n; ++i) {
7802 nonneg = nonneg_halfspace(isl_set_get_space(set),
7803 pos(set->dim, type) + first + i);
7804 neg = neg_halfspace(isl_set_get_space(set),
7805 pos(set->dim, type) + first + i);
7806
7807 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
7808 }
7809
7810 return set;
7811error:
7812 isl_set_free(set);
7813 return NULL;
7814}
7815
7816static int foreach_orthant(__isl_take isl_set *set, int *signs, int first,
7817 int len, int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7818 void *user)
7819{
7820 isl_set *half;
7821
7822 if (!set)
7823 return -1;
7824 if (isl_set_plain_is_empty(set)) {
7825 isl_set_free(set);
7826 return 0;
7827 }
7828 if (first == len)
7829 return fn(set, signs, user);
7830
7831 signs[first] = 1;
7832 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
7833 1 + first));
7834 half = isl_set_intersect(half, isl_set_copy(set));
7835 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
7836 goto error;
7837
7838 signs[first] = -1;
7839 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
7840 1 + first));
7841 half = isl_set_intersect(half, set);
7842 return foreach_orthant(half, signs, first + 1, len, fn, user);
7843error:
7844 isl_set_free(set);
7845 return -1;
7846}
7847
7848/* Call "fn" on the intersections of "set" with each of the orthants
7849 * (except for obviously empty intersections). The orthant is identified
7850 * by the signs array, with each entry having value 1 or -1 according
7851 * to the sign of the corresponding variable.
7852 */
7853int isl_set_foreach_orthant(__isl_keep isl_set *set,
7854 int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7855 void *user)
7856{
7857 unsigned nparam;
7858 unsigned nvar;
7859 int *signs;
7860 int r;
7861
7862 if (!set)
7863 return -1;
7864 if (isl_set_plain_is_empty(set))
7865 return 0;
7866
7867 nparam = isl_set_dim(set, isl_dim_param);
7868 nvar = isl_set_dim(set, isl_dim_set);
7869
7870 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
7871
7872 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
7873 fn, user);
7874
7875 free(signs);
7876
7877 return r;
7878}
7879
7880int isl_set_is_equal(struct isl_set *set1, struct isl_set *set2)
7881{
7882 return isl_map_is_equal((struct isl_map *)set1, (struct isl_map *)set2);
7883}
7884
7885int isl_basic_map_is_subset(
7886 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7887{
7888 int is_subset;
7889 struct isl_map *map1;
7890 struct isl_map *map2;
7891
7892 if (!bmap1 || !bmap2)
7893 return -1;
7894
7895 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
7896 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
7897
7898 is_subset = isl_map_is_subset(map1, map2);
7899
7900 isl_map_free(map1);
7901 isl_map_free(map2);
7902
7903 return is_subset;
7904}
7905
7906int isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
7907 __isl_keep isl_basic_set *bset2)
7908{
7909 return isl_basic_map_is_subset(bset1, bset2);
7910}
7911
7912int isl_basic_map_is_equal(
7913 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7914{
7915 int is_subset;
7916
7917 if (!bmap1 || !bmap2)
7918 return -1;
7919 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
7920 if (is_subset != 1)
7921 return is_subset;
7922 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
7923 return is_subset;
7924}
7925
7926int isl_basic_set_is_equal(
7927 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
7928{
7929 return isl_basic_map_is_equal(
7930 (struct isl_basic_map *)bset1, (struct isl_basic_map *)bset2);
7931}
7932
7933int isl_map_is_empty(struct isl_map *map)
7934{
7935 int i;
7936 int is_empty;
7937
7938 if (!map)
7939 return -1;
7940 for (i = 0; i < map->n; ++i) {
7941 is_empty = isl_basic_map_is_empty(map->p[i]);
7942 if (is_empty < 0)
7943 return -1;
7944 if (!is_empty)
7945 return 0;
7946 }
7947 return 1;
7948}
7949
7950int isl_map_plain_is_empty(__isl_keep isl_map *map)
7951{
7952 return map ? map->n == 0 : -1;
7953}
7954
7955int isl_map_fast_is_empty(__isl_keep isl_map *map)
7956{
7957 return isl_map_plain_is_empty(map);
7958}
7959
7960int isl_set_plain_is_empty(struct isl_set *set)
7961{
7962 return set ? set->n == 0 : -1;
7963}
7964
7965int isl_set_fast_is_empty(__isl_keep isl_set *set)
7966{
7967 return isl_set_plain_is_empty(set);
7968}
7969
7970int isl_set_is_empty(struct isl_set *set)
7971{
7972 return isl_map_is_empty((struct isl_map *)set);
7973}
7974
7975int isl_map_has_equal_space(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7976{
7977 if (!map1 || !map2)
7978 return -1;
7979
7980 return isl_space_is_equal(map1->dim, map2->dim);
7981}
7982
7983int isl_set_has_equal_space(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
7984{
7985 if (!set1 || !set2)
7986 return -1;
7987
7988 return isl_space_is_equal(set1->dim, set2->dim);
7989}
7990
7991static int map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7992{
7993 int is_subset;
7994
7995 if (!map1 || !map2)
7996 return -1;
7997 is_subset = isl_map_is_subset(map1, map2);
7998 if (is_subset != 1)
7999 return is_subset;
8000 is_subset = isl_map_is_subset(map2, map1);
8001 return is_subset;
8002}
8003
8004int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8005{
8006 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8007}
8008
8009int isl_basic_map_is_strict_subset(
8010 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8011{
8012 int is_subset;
8013
8014 if (!bmap1 || !bmap2)
8015 return -1;
8016 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8017 if (is_subset != 1)
8018 return is_subset;
8019 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8020 if (is_subset == -1)
8021 return is_subset;
8022 return !is_subset;
8023}
8024
8025int isl_map_is_strict_subset(struct isl_map *map1, struct isl_map *map2)
8026{
8027 int is_subset;
8028
8029 if (!map1 || !map2)
8030 return -1;
8031 is_subset = isl_map_is_subset(map1, map2);
8032 if (is_subset != 1)
8033 return is_subset;
8034 is_subset = isl_map_is_subset(map2, map1);
8035 if (is_subset == -1)
8036 return is_subset;
8037 return !is_subset;
8038}
8039
8040int isl_set_is_strict_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8041{
8042 return isl_map_is_strict_subset((isl_map *)set1, (isl_map *)set2);
8043}
8044
8045int isl_basic_map_is_universe(struct isl_basic_map *bmap)
8046{
8047 if (!bmap)
8048 return -1;
8049 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8050}
8051
8052int isl_basic_set_is_universe(struct isl_basic_set *bset)
8053{
8054 if (!bset)
8055 return -1;
8056 return bset->n_eq == 0 && bset->n_ineq == 0;
8057}
8058
8059int isl_map_plain_is_universe(__isl_keep isl_map *map)
8060{
8061 int i;
8062
8063 if (!map)
8064 return -1;
8065
8066 for (i = 0; i < map->n; ++i) {
8067 int r = isl_basic_map_is_universe(map->p[i]);
8068 if (r < 0 || r)
8069 return r;
8070 }
8071
8072 return 0;
8073}
8074
8075int isl_set_plain_is_universe(__isl_keep isl_set *set)
8076{
8077 return isl_map_plain_is_universe((isl_map *) set);
8078}
8079
8080int isl_set_fast_is_universe(__isl_keep isl_set *set)
8081{
8082 return isl_set_plain_is_universe(set);
8083}
8084
8085int isl_basic_map_is_empty(struct isl_basic_map *bmap)
8086{
8087 struct isl_basic_set *bset = NULL;
8088 struct isl_vec *sample = NULL;
8089 int empty;
8090 unsigned total;
8091
8092 if (!bmap)
8093 return -1;
8094
8095 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8096 return 1;
8097
8098 if (isl_basic_map_is_universe(bmap))
8099 return 0;
8100
8101 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8102 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8103 copy = isl_basic_map_remove_redundancies(copy);
8104 empty = isl_basic_map_plain_is_empty(copy);
8105 isl_basic_map_free(copy);
8106 return empty;
8107 }
8108
8109 total = 1 + isl_basic_map_total_dim(bmap);
8110 if (bmap->sample && bmap->sample->size == total) {
8111 int contains = isl_basic_map_contains(bmap, bmap->sample);
8112 if (contains < 0)
8113 return -1;
8114 if (contains)
8115 return 0;
8116 }
8117 isl_vec_free(bmap->sample);
8118 bmap->sample = NULL;
8119 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8120 if (!bset)
8121 return -1;
8122 sample = isl_basic_set_sample_vec(bset);
8123 if (!sample)
8124 return -1;
8125 empty = sample->size == 0;
8126 isl_vec_free(bmap->sample);
8127 bmap->sample = sample;
8128 if (empty)
8129 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8130
8131 return empty;
8132}
8133
8134int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8135{
8136 if (!bmap)
8137 return -1;
8138 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8139}
8140
8141int isl_basic_map_fast_is_empty(__isl_keep isl_basic_map *bmap)
8142{
8143 return isl_basic_map_plain_is_empty(bmap);
8144}
8145
8146int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8147{
8148 if (!bset)
8149 return -1;
8150 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8151}
8152
8153int isl_basic_set_fast_is_empty(__isl_keep isl_basic_set *bset)
8154{
8155 return isl_basic_set_plain_is_empty(bset);
8156}
8157
8158int isl_basic_set_is_empty(struct isl_basic_set *bset)
8159{
8160 return isl_basic_map_is_empty((struct isl_basic_map *)bset);
8161}
8162
8163struct isl_map *isl_basic_map_union(
8164 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8165{
8166 struct isl_map *map;
8167 if (!bmap1 || !bmap2)
8168 goto error;
8169
8170 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8171
8172 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8173 if (!map)
8174 goto error;
8175 map = isl_map_add_basic_map(map, bmap1);
8176 map = isl_map_add_basic_map(map, bmap2);
8177 return map;
8178error:
8179 isl_basic_map_free(bmap1);
8180 isl_basic_map_free(bmap2);
8181 return NULL;
8182}
8183
8184struct isl_set *isl_basic_set_union(
8185 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8186{
8187 return (struct isl_set *)isl_basic_map_union(
8188 (struct isl_basic_map *)bset1,
8189 (struct isl_basic_map *)bset2);
8190}
8191
8192/* Order divs such that any div only depends on previous divs */
8193struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap)
8194{
8195 int i;
8196 unsigned off;
8197
8198 if (!bmap)
8199 return NULL;
8200
8201 off = isl_space_dim(bmap->dim, isl_dim_all);
8202
8203 for (i = 0; i < bmap->n_div; ++i) {
8204 int pos;
8205 if (isl_int_is_zero(bmap->div[i][0]))
8206 continue;
8207 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8208 bmap->n_div-i);
8209 if (pos == -1)
8210 continue;
8211 isl_basic_map_swap_div(bmap, i, i + pos);
8212 --i;
8213 }
8214 return bmap;
8215}
8216
8217struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8218{
8219 return (struct isl_basic_set *)
8220 isl_basic_map_order_divs((struct isl_basic_map *)bset);
8221}
8222
8223__isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8224{
8225 int i;
8226
8227 if (!map)
8228 return 0;
8229
8230 for (i = 0; i < map->n; ++i) {
8231 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8232 if (!map->p[i])
8233 goto error;
8234 }
8235
8236 return map;
8237error:
8238 isl_map_free(map);
8239 return NULL;
8240}
8241
8242/* Apply the expansion computed by isl_merge_divs.
8243 * The expansion itself is given by "exp" while the resulting
8244 * list of divs is given by "div".
8245 */
8246__isl_give isl_basic_set *isl_basic_set_expand_divs(
8247 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8248{
8249 int i, j;
8250 int n_div;
8251
8252 bset = isl_basic_set_cow(bset);
8253 if (!bset || !div)
8254 goto error;
8255
8256 if (div->n_row < bset->n_div)
8257 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8258 "not an expansion", goto error);
8259
8260 n_div = bset->n_div;
8261 bset = isl_basic_map_extend_space(bset, isl_space_copy(bset->dim),
8262 div->n_row - n_div, 0,
8263 2 * (div->n_row - n_div));
8264
8265 for (i = n_div; i < div->n_row; ++i)
8266 if (isl_basic_set_alloc_div(bset) < 0)
8267 goto error;
8268
8269 j = n_div - 1;
8270 for (i = div->n_row - 1; i >= 0; --i) {
8271 if (j >= 0 && exp[j] == i) {
8272 if (i != j)
8273 isl_basic_map_swap_div(bset, i, j);
8274 j--;
8275 } else {
8276 isl_seq_cpy(bset->div[i], div->row[i], div->n_col);
8277 if (isl_basic_map_add_div_constraints(bset, i) < 0)
8278 goto error;
8279 }
8280 }
8281
8282 isl_mat_free(div);
8283 return bset;
8284error:
8285 isl_basic_set_free(bset);
8286 isl_mat_free(div);
8287 return NULL;
8288}
8289
8290/* Look for a div in dst that corresponds to the div "div" in src.
8291 * The divs before "div" in src and dst are assumed to be the same.
8292 *
8293 * Returns -1 if no corresponding div was found and the position
8294 * of the corresponding div in dst otherwise.
8295 */
8296static int find_div(struct isl_basic_map *dst,
8297 struct isl_basic_map *src, unsigned div)
8298{
8299 int i;
8300
8301 unsigned total = isl_space_dim(src->dim, isl_dim_all);
8302
8303 isl_assert(dst->ctx, div <= dst->n_div, return -1);
8304 for (i = div; i < dst->n_div; ++i)
8305 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8306 isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8307 dst->n_div - div) == -1)
8308 return i;
8309 return -1;
8310}
8311
8312/* Align the divs of "dst" to those of "src", adding divs from "src"
8313 * if needed. That is, make sure that the first src->n_div divs
8314 * of the result are equal to those of src.
8315 *
8316 * The result is not finalized as by design it will have redundant
8317 * divs if any divs from "src" were copied.
8318 */
8319__isl_give isl_basic_map *isl_basic_map_align_divs(
8320 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8321{
8322 int i;
8323 int known, extended;
8324 unsigned total;
8325
8326 if (!dst || !src)
8327 return isl_basic_map_free(dst);
8328
8329 if (src->n_div == 0)
8330 return dst;
8331
8332 known = isl_basic_map_divs_known(src);
8333 if (known < 0)
8334 return isl_basic_map_free(dst);
8335 if (!known)
8336 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8337 "some src divs are unknown",
8338 return isl_basic_map_free(dst));
8339
8340 src = isl_basic_map_order_divs(src);
8341
8342 extended = 0;
8343 total = isl_space_dim(src->dim, isl_dim_all);
8344 for (i = 0; i < src->n_div; ++i) {
8345 int j = find_div(dst, src, i);
8346 if (j < 0) {
8347 if (!extended) {
8348 int extra = src->n_div - i;
8349 dst = isl_basic_map_cow(dst);
8350 if (!dst)
8351 return NULL;
8352 dst = isl_basic_map_extend_space(dst,
8353 isl_space_copy(dst->dim),
8354 extra, 0, 2 * extra);
8355 extended = 1;
8356 }
8357 j = isl_basic_map_alloc_div(dst);
8358 if (j < 0)
8359 return isl_basic_map_free(dst);
8360 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8361 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8362 if (isl_basic_map_add_div_constraints(dst, j) < 0)
8363 return isl_basic_map_free(dst);
8364 }
8365 if (j != i)
8366 isl_basic_map_swap_div(dst, i, j);
8367 }
8368 return dst;
8369}
8370
8371struct isl_basic_set *isl_basic_set_align_divs(
8372 struct isl_basic_set *dst, struct isl_basic_set *src)
8373{
8374 return (struct isl_basic_set *)isl_basic_map_align_divs(
8375 (struct isl_basic_map *)dst, (struct isl_basic_map *)src);
8376}
8377
8378struct isl_map *isl_map_align_divs(struct isl_map *map)
8379{
8380 int i;
8381
8382 if (!map)
8383 return NULL;
8384 if (map->n == 0)
8385 return map;
8386 map = isl_map_compute_divs(map);
8387 map = isl_map_cow(map);
8388 if (!map)
8389 return NULL;
8390
8391 for (i = 1; i < map->n; ++i)
8392 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8393 for (i = 1; i < map->n; ++i) {
8394 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8395 if (!map->p[i])
8396 return isl_map_free(map);
8397 }
8398
8399 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
8400 return map;
8401}
8402
8403struct isl_set *isl_set_align_divs(struct isl_set *set)
8404{
8405 return (struct isl_set *)isl_map_align_divs((struct isl_map *)set);
8406}
8407
8408/* Align the divs of the basic sets in "set" to those
8409 * of the basic sets in "list", as well as to the other basic sets in "set".
8410 * The elements in "list" are assumed to have known divs.
8411 */
8412__isl_give isl_set *isl_set_align_divs_to_basic_set_list(
8413 __isl_take isl_set *set, __isl_keep isl_basic_set_list *list)
8414{
8415 int i, n;
8416
8417 set = isl_set_compute_divs(set);
8418 set = isl_set_cow(set);
8419 if (!set || !list)
8420 return isl_set_free(set);
8421 if (set->n == 0)
8422 return set;
8423
8424 n = isl_basic_set_list_n_basic_set(list);
8425 for (i = 0; i < n; ++i) {
8426 isl_basic_set *bset;
8427
8428 bset = isl_basic_set_list_get_basic_set(list, i);
8429 set->p[0] = isl_basic_set_align_divs(set->p[0], bset);
8430 isl_basic_set_free(bset);
8431 }
8432 if (!set->p[0])
8433 return isl_set_free(set);
8434
8435 return isl_set_align_divs(set);
8436}
8437
8438/* Align the divs of each element of "list" to those of "bset".
8439 * Both "bset" and the elements of "list" are assumed to have known divs.
8440 */
8441__isl_give isl_basic_set_list *isl_basic_set_list_align_divs_to_basic_set(
8442 __isl_take isl_basic_set_list *list, __isl_keep isl_basic_set *bset)
8443{
8444 int i, n;
8445
8446 if (!list || !bset)
8447 return isl_basic_set_list_free(list);
8448
8449 n = isl_basic_set_list_n_basic_set(list);
8450 for (i = 0; i < n; ++i) {
8451 isl_basic_set *bset_i;
8452
8453 bset_i = isl_basic_set_list_get_basic_set(list, i);
8454 bset_i = isl_basic_set_align_divs(bset_i, bset);
8455 list = isl_basic_set_list_set_basic_set(list, i, bset_i);
8456 }
8457
8458 return list;
8459}
8460
8461static __isl_give isl_set *set_apply( __isl_take isl_set *set,
8462 __isl_take isl_map *map)
8463{
8464 if (!set || !map)
8465 goto error;
8466 isl_assert(set->ctx, isl_map_compatible_domain(map, set), goto error);
8467 map = isl_map_intersect_domain(map, set);
8468 set = isl_map_range(map);
8469 return set;
8470error:
8471 isl_set_free(set);
8472 isl_map_free(map);
8473 return NULL;
8474}
8475
8476__isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
8477 __isl_take isl_map *map)
8478{
8479 return isl_map_align_params_map_map_and(set, map, &set_apply);
8480}
8481
8482/* There is no need to cow as removing empty parts doesn't change
8483 * the meaning of the set.
8484 */
8485struct isl_map *isl_map_remove_empty_parts(struct isl_map *map)
8486{
8487 int i;
8488
8489 if (!map)
8490 return NULL;
8491
8492 for (i = map->n - 1; i >= 0; --i)
8493 remove_if_empty(map, i);
8494
8495 return map;
8496}
8497
8498struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
8499{
8500 return (struct isl_set *)
8501 isl_map_remove_empty_parts((struct isl_map *)set);
8502}
8503
8504struct isl_basic_map *isl_map_copy_basic_map(struct isl_map *map)
8505{
8506 struct isl_basic_map *bmap;
8507 if (!map || map->n == 0)
8508 return NULL;
8509 bmap = map->p[map->n-1];
8510 isl_assert(map->ctx, ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL), return NULL);
8511 return isl_basic_map_copy(bmap);
8512}
8513
8514struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set)
8515{
8516 return (struct isl_basic_set *)
8517 isl_map_copy_basic_map((struct isl_map *)set);
8518}
8519
8520__isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map,
8521 __isl_keep isl_basic_map *bmap)
8522{
8523 int i;
8524
8525 if (!map || !bmap)
8526 goto error;
8527 for (i = map->n-1; i >= 0; --i) {
8528 if (map->p[i] != bmap)
8529 continue;
8530 map = isl_map_cow(map);
8531 if (!map)
8532 goto error;
8533 isl_basic_map_free(map->p[i]);
8534 if (i != map->n-1) {
8535 ISL_F_CLR(map, ISL_SET_NORMALIZED);
8536 map->p[i] = map->p[map->n-1];
8537 }
8538 map->n--;
8539 return map;
8540 }
8541 return map;
8542error:
8543 isl_map_free(map);
8544 return NULL;
8545}
8546
8547struct isl_set *isl_set_drop_basic_set(struct isl_set *set,
8548 struct isl_basic_set *bset)
8549{
8550 return (struct isl_set *)isl_map_drop_basic_map((struct isl_map *)set,
8551 (struct isl_basic_map *)bset);
8552}
8553
8554/* Given two basic sets bset1 and bset2, compute the maximal difference
8555 * between the values of dimension pos in bset1 and those in bset2
8556 * for any common value of the parameters and dimensions preceding pos.
8557 */
8558static enum isl_lp_result basic_set_maximal_difference_at(
8559 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
8560 int pos, isl_int *opt)
8561{
8562 isl_space *dims;
8563 struct isl_basic_map *bmap1 = NULL;
8564 struct isl_basic_map *bmap2 = NULL;
8565 struct isl_ctx *ctx;
8566 struct isl_vec *obj;
8567 unsigned total;
8568 unsigned nparam;
8569 unsigned dim1, dim2;
8570 enum isl_lp_result res;
8571
8572 if (!bset1 || !bset2)
8573 return isl_lp_error;
8574
8575 nparam = isl_basic_set_n_param(bset1);
8576 dim1 = isl_basic_set_n_dim(bset1);
8577 dim2 = isl_basic_set_n_dim(bset2);
8578 dims = isl_space_alloc(bset1->ctx, nparam, pos, dim1 - pos);
8579 bmap1 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset1), dims);
8580 dims = isl_space_alloc(bset2->ctx, nparam, pos, dim2 - pos);
8581 bmap2 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset2), dims);
8582 if (!bmap1 || !bmap2)
8583 goto error;
8584 bmap1 = isl_basic_map_cow(bmap1);
8585 bmap1 = isl_basic_map_extend(bmap1, nparam,
8586 pos, (dim1 - pos) + (dim2 - pos),
8587 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
8588 bmap1 = add_constraints(bmap1, bmap2, 0, dim1 - pos);
8589 if (!bmap1)
8590 goto error2;
8591 total = isl_basic_map_total_dim(bmap1);
8592 ctx = bmap1->ctx;
8593 obj = isl_vec_alloc(ctx, 1 + total);
8594 if (!obj)
8595 goto error2;
8596 isl_seq_clr(obj->block.data, 1 + total);
8597 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
8598 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
8599 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
8600 opt, NULL, NULL);
8601 isl_basic_map_free(bmap1);
8602 isl_vec_free(obj);
8603 return res;
8604error:
8605 isl_basic_map_free(bmap2);
8606error2:
8607 isl_basic_map_free(bmap1);
8608 return isl_lp_error;
8609}
8610
8611/* Given two _disjoint_ basic sets bset1 and bset2, check whether
8612 * for any common value of the parameters and dimensions preceding pos
8613 * in both basic sets, the values of dimension pos in bset1 are
8614 * smaller or larger than those in bset2.
8615 *
8616 * Returns
8617 * 1 if bset1 follows bset2
8618 * -1 if bset1 precedes bset2
8619 * 0 if bset1 and bset2 are incomparable
8620 * -2 if some error occurred.
8621 */
8622int isl_basic_set_compare_at(struct isl_basic_set *bset1,
8623 struct isl_basic_set *bset2, int pos)
8624{
8625 isl_int opt;
8626 enum isl_lp_result res;
8627 int cmp;
8628
8629 isl_int_init(opt);
8630
8631 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8632
8633 if (res == isl_lp_empty)
8634 cmp = 0;
8635 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8636 res == isl_lp_unbounded)
8637 cmp = 1;
8638 else if (res == isl_lp_ok && isl_int_is_neg(opt))
8639 cmp = -1;
8640 else
8641 cmp = -2;
8642
8643 isl_int_clear(opt);
8644 return cmp;
8645}
8646
8647/* Given two basic sets bset1 and bset2, check whether
8648 * for any common value of the parameters and dimensions preceding pos
8649 * there is a value of dimension pos in bset1 that is larger
8650 * than a value of the same dimension in bset2.
8651 *
8652 * Return
8653 * 1 if there exists such a pair
8654 * 0 if there is no such pair, but there is a pair of equal values
8655 * -1 otherwise
8656 * -2 if some error occurred.
8657 */
8658int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
8659 __isl_keep isl_basic_set *bset2, int pos)
8660{
8661 isl_int opt;
8662 enum isl_lp_result res;
8663 int cmp;
8664
8665 isl_int_init(opt);
8666
8667 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8668
8669 if (res == isl_lp_empty)
8670 cmp = -1;
8671 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8672 res == isl_lp_unbounded)
8673 cmp = 1;
8674 else if (res == isl_lp_ok && isl_int_is_neg(opt))
8675 cmp = -1;
8676 else if (res == isl_lp_ok)
8677 cmp = 0;
8678 else
8679 cmp = -2;
8680
8681 isl_int_clear(opt);
8682 return cmp;
8683}
8684
8685/* Given two sets set1 and set2, check whether
8686 * for any common value of the parameters and dimensions preceding pos
8687 * there is a value of dimension pos in set1 that is larger
8688 * than a value of the same dimension in set2.
8689 *
8690 * Return
8691 * 1 if there exists such a pair
8692 * 0 if there is no such pair, but there is a pair of equal values
8693 * -1 otherwise
8694 * -2 if some error occurred.
8695 */
8696int isl_set_follows_at(__isl_keep isl_set *set1,
8697 __isl_keep isl_set *set2, int pos)
8698{
8699 int i, j;
8700 int follows = -1;
8701
8702 if (!set1 || !set2)
8703 return -2;
8704
8705 for (i = 0; i < set1->n; ++i)
8706 for (j = 0; j < set2->n; ++j) {
8707 int f;
8708 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
8709 if (f == 1 || f == -2)
8710 return f;
8711 if (f > follows)
8712 follows = f;
8713 }
8714
8715 return follows;
8716}
8717
8718static int isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map *bmap,
8719 unsigned pos, isl_int *val)
8720{
8721 int i;
8722 int d;
8723 unsigned total;
8724
8725 if (!bmap)
8726 return -1;
8727 total = isl_basic_map_total_dim(bmap);
8728 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
8729 for (; d+1 > pos; --d)
8730 if (!isl_int_is_zero(bmap->eq[i][1+d]))
8731 break;
8732 if (d != pos)
8733 continue;
8734 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
8735 return 0;
8736 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
8737 return 0;
8738 if (!isl_int_is_one(bmap->eq[i][1+d]))
8739 return 0;
8740 if (val)
8741 isl_int_neg(*val, bmap->eq[i][0]);
8742 return 1;
8743 }
8744 return 0;
8745}
8746
8747static int isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
8748 unsigned pos, isl_int *val)
8749{
8750 int i;
8751 isl_int v;
8752 isl_int tmp;
8753 int fixed;
8754
8755 if (!map)
8756 return -1;
8757 if (map->n == 0)
8758 return 0;
8759 if (map->n == 1)
8760 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
8761 isl_int_init(v);
8762 isl_int_init(tmp);
8763 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
8764 for (i = 1; fixed == 1 && i < map->n; ++i) {
8765 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
8766 if (fixed == 1 && isl_int_ne(tmp, v))
8767 fixed = 0;
8768 }
8769 if (val)
8770 isl_int_set(*val, v);
8771 isl_int_clear(tmp);
8772 isl_int_clear(v);
8773 return fixed;
8774}
8775
8776static int isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set *bset,
8777 unsigned pos, isl_int *val)
8778{
8779 return isl_basic_map_plain_has_fixed_var((struct isl_basic_map *)bset,
8780 pos, val);
8781}
8782
8783static int isl_set_plain_has_fixed_var(__isl_keep isl_set *set, unsigned pos,
8784 isl_int *val)
8785{
8786 return isl_map_plain_has_fixed_var((struct isl_map *)set, pos, val);
8787}
8788
8789int isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
8790 enum isl_dim_type type, unsigned pos, isl_int *val)
8791{
8792 if (pos >= isl_basic_map_dim(bmap, type))
8793 return -1;
8794 return isl_basic_map_plain_has_fixed_var(bmap,
8795 isl_basic_map_offset(bmap, type) - 1 + pos, val);
8796}
8797
8798/* If "bmap" obviously lies on a hyperplane where the given dimension
8799 * has a fixed value, then return that value.
8800 * Otherwise return NaN.
8801 */
8802__isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
8803 __isl_keep isl_basic_map *bmap,
8804 enum isl_dim_type type, unsigned pos)
8805{
8806 isl_ctx *ctx;
8807 isl_val *v;
8808 int fixed;
8809
8810 if (!bmap)
8811 return NULL;
8812 ctx = isl_basic_map_get_ctx(bmap);
8813 v = isl_val_alloc(ctx);
8814 if (!v)
8815 return NULL;
8816 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
8817 if (fixed < 0)
8818 return isl_val_free(v);
8819 if (fixed) {
8820 isl_int_set_si(v->d, 1);
8821 return v;
8822 }
8823 isl_val_free(v);
8824 return isl_val_nan(ctx);
8825}
8826
8827int isl_map_plain_is_fixed(__isl_keep isl_map *map,
8828 enum isl_dim_type type, unsigned pos, isl_int *val)
8829{
8830 if (pos >= isl_map_dim(map, type))
8831 return -1;
8832 return isl_map_plain_has_fixed_var(map,
8833 map_offset(map, type) - 1 + pos, val);
8834}
8835
8836/* If "map" obviously lies on a hyperplane where the given dimension
8837 * has a fixed value, then return that value.
8838 * Otherwise return NaN.
8839 */
8840__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
8841 enum isl_dim_type type, unsigned pos)
8842{
8843 isl_ctx *ctx;
8844 isl_val *v;
8845 int fixed;
8846
8847 if (!map)
8848 return NULL;
8849 ctx = isl_map_get_ctx(map);
8850 v = isl_val_alloc(ctx);
8851 if (!v)
8852 return NULL;
8853 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
8854 if (fixed < 0)
8855 return isl_val_free(v);
8856 if (fixed) {
8857 isl_int_set_si(v->d, 1);
8858 return v;
8859 }
8860 isl_val_free(v);
8861 return isl_val_nan(ctx);
8862}
8863
8864/* If "set" obviously lies on a hyperplane where the given dimension
8865 * has a fixed value, then return that value.
8866 * Otherwise return NaN.
8867 */
8868__isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
8869 enum isl_dim_type type, unsigned pos)
8870{
8871 return isl_map_plain_get_val_if_fixed(set, type, pos);
8872}
8873
8874int isl_set_plain_is_fixed(__isl_keep isl_set *set,
8875 enum isl_dim_type type, unsigned pos, isl_int *val)
8876{
8877 return isl_map_plain_is_fixed(set, type, pos, val);
8878}
8879
8880int isl_map_fast_is_fixed(__isl_keep isl_map *map,
8881 enum isl_dim_type type, unsigned pos, isl_int *val)
8882{
8883 return isl_map_plain_is_fixed(map, type, pos, val);
8884}
8885
8886/* Check if dimension dim has fixed value and if so and if val is not NULL,
8887 * then return this fixed value in *val.
8888 */
8889int isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
8890 unsigned dim, isl_int *val)
8891{
8892 return isl_basic_set_plain_has_fixed_var(bset,
8893 isl_basic_set_n_param(bset) + dim, val);
8894}
8895
8896/* Check if dimension dim has fixed value and if so and if val is not NULL,
8897 * then return this fixed value in *val.
8898 */
8899int isl_set_plain_dim_is_fixed(__isl_keep isl_set *set,
8900 unsigned dim, isl_int *val)
8901{
8902 return isl_set_plain_has_fixed_var(set, isl_set_n_param(set) + dim, val);
8903}
8904
8905int isl_set_fast_dim_is_fixed(__isl_keep isl_set *set,
8906 unsigned dim, isl_int *val)
8907{
8908 return isl_set_plain_dim_is_fixed(set, dim, val);
8909}
8910
8911/* Check if input variable in has fixed value and if so and if val is not NULL,
8912 * then return this fixed value in *val.
8913 */
8914int isl_map_plain_input_is_fixed(__isl_keep isl_map *map,
8915 unsigned in, isl_int *val)
8916{
8917 return isl_map_plain_has_fixed_var(map, isl_map_n_param(map) + in, val);
8918}
8919
8920/* Check if dimension dim has an (obvious) fixed lower bound and if so
8921 * and if val is not NULL, then return this lower bound in *val.
8922 */
8923int isl_basic_set_plain_dim_has_fixed_lower_bound(
8924 __isl_keep isl_basic_set *bset, unsigned dim, isl_int *val)
8925{
8926 int i, i_eq = -1, i_ineq = -1;
8927 isl_int *c;
8928 unsigned total;
8929 unsigned nparam;
8930
8931 if (!bset)
8932 return -1;
8933 total = isl_basic_set_total_dim(bset);
8934 nparam = isl_basic_set_n_param(bset);
8935 for (i = 0; i < bset->n_eq; ++i) {
8936 if (isl_int_is_zero(bset->eq[i][1+nparam+dim]))
8937 continue;
8938 if (i_eq != -1)
8939 return 0;
8940 i_eq = i;
8941 }
8942 for (i = 0; i < bset->n_ineq; ++i) {
8943 if (!isl_int_is_pos(bset->ineq[i][1+nparam+dim]))
8944 continue;
8945 if (i_eq != -1 || i_ineq != -1)
8946 return 0;
8947 i_ineq = i;
8948 }
8949 if (i_eq == -1 && i_ineq == -1)
8950 return 0;
8951 c = i_eq != -1 ? bset->eq[i_eq] : bset->ineq[i_ineq];
8952 /* The coefficient should always be one due to normalization. */
8953 if (!isl_int_is_one(c[1+nparam+dim]))
8954 return 0;
8955 if (isl_seq_first_non_zero(c+1, nparam+dim) != -1)
8956 return 0;
8957 if (isl_seq_first_non_zero(c+1+nparam+dim+1,
8958 total - nparam - dim - 1) != -1)
8959 return 0;
8960 if (val)
8961 isl_int_neg(*val, c[0]);
8962 return 1;
8963}
8964
8965int isl_set_plain_dim_has_fixed_lower_bound(__isl_keep isl_set *set,
8966 unsigned dim, isl_int *val)
8967{
8968 int i;
8969 isl_int v;
8970 isl_int tmp;
8971 int fixed;
8972
8973 if (!set)
8974 return -1;
8975 if (set->n == 0)
8976 return 0;
8977 if (set->n == 1)
8978 return isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0],
8979 dim, val);
8980 isl_int_init(v);
8981 isl_int_init(tmp);
8982 fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0],
8983 dim, &v);
8984 for (i = 1; fixed == 1 && i < set->n; ++i) {
8985 fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[i],
8986 dim, &tmp);
8987 if (fixed == 1 && isl_int_ne(tmp, v))
8988 fixed = 0;
8989 }
8990 if (val)
8991 isl_int_set(*val, v);
8992 isl_int_clear(tmp);
8993 isl_int_clear(v);
8994 return fixed;
8995}
8996
8997/* uset_gist depends on constraints without existentially quantified
8998 * variables sorting first.
8999 */
9000static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9001{
9002 isl_int **c1 = (isl_int **) p1;
9003 isl_int **c2 = (isl_int **) p2;
9004 int l1, l2;
9005 unsigned size = *(unsigned *) arg;
9006
9007 l1 = isl_seq_last_non_zero(*c1 + 1, size);
9008 l2 = isl_seq_last_non_zero(*c2 + 1, size);
9009
9010 if (l1 != l2)
9011 return l1 - l2;
9012
9013 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9014}
9015
9016static struct isl_basic_map *isl_basic_map_sort_constraints(
9017 struct isl_basic_map *bmap)
9018{
9019 unsigned total;
9020
9021 if (!bmap)
9022 return NULL;
9023 if (bmap->n_ineq == 0)
9024 return bmap;
9025 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9026 return bmap;
9027 total = isl_basic_map_total_dim(bmap);
9028 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9029 &sort_constraint_cmp, &total) < 0)
9030 return isl_basic_map_free(bmap);
9031 return bmap;
9032}
9033
9034__isl_give isl_basic_set *isl_basic_set_sort_constraints(
9035 __isl_take isl_basic_set *bset)
9036{
9037 return (struct isl_basic_set *)isl_basic_map_sort_constraints(
9038 (struct isl_basic_map *)bset);
9039}
9040
9041struct isl_basic_map *isl_basic_map_normalize(struct isl_basic_map *bmap)
9042{
9043 if (!bmap)
9044 return NULL;
9045 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9046 return bmap;
9047 bmap = isl_basic_map_remove_redundancies(bmap);
9048 bmap = isl_basic_map_sort_constraints(bmap);
9049 if (bmap)
9050 ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
9051 return bmap;
9052}
9053
9054struct isl_basic_set *isl_basic_set_normalize(struct isl_basic_set *bset)
9055{
9056 return (struct isl_basic_set *)isl_basic_map_normalize(
9057 (struct isl_basic_map *)bset);
9058}
9059
9060int isl_basic_map_plain_cmp(const __isl_keep isl_basic_map *bmap1,
9061 const __isl_keep isl_basic_map *bmap2)
9062{
9063 int i, cmp;
9064 unsigned total;
9065
9066 if (bmap1 == bmap2)
9067 return 0;
9068 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9069 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9070 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9071 if (isl_basic_map_n_param(bmap1) != isl_basic_map_n_param(bmap2))
9072 return isl_basic_map_n_param(bmap1) - isl_basic_map_n_param(bmap2);
9073 if (isl_basic_map_n_in(bmap1) != isl_basic_map_n_in(bmap2))
9074 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
9075 if (isl_basic_map_n_out(bmap1) != isl_basic_map_n_out(bmap2))
9076 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
9077 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9078 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9079 return 0;
9080 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9081 return 1;
9082 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9083 return -1;
9084 if (bmap1->n_eq != bmap2->n_eq)
9085 return bmap1->n_eq - bmap2->n_eq;
9086 if (bmap1->n_ineq != bmap2->n_ineq)
9087 return bmap1->n_ineq - bmap2->n_ineq;
9088 if (bmap1->n_div != bmap2->n_div)
9089 return bmap1->n_div - bmap2->n_div;
9090 total = isl_basic_map_total_dim(bmap1);
9091 for (i = 0; i < bmap1->n_eq; ++i) {
9092 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9093 if (cmp)
9094 return cmp;
9095 }
9096 for (i = 0; i < bmap1->n_ineq; ++i) {
9097 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9098 if (cmp)
9099 return cmp;
9100 }
9101 for (i = 0; i < bmap1->n_div; ++i) {
9102 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9103 if (cmp)
9104 return cmp;
9105 }
9106 return 0;
9107}
9108
9109int isl_basic_set_plain_cmp(const __isl_keep isl_basic_set *bset1,
9110 const __isl_keep isl_basic_set *bset2)
9111{
9112 return isl_basic_map_plain_cmp(bset1, bset2);
9113}
9114
9115int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9116{
9117 int i, cmp;
9118
9119 if (set1 == set2)
9120 return 0;
9121 if (set1->n != set2->n)
9122 return set1->n - set2->n;
9123
9124 for (i = 0; i < set1->n; ++i) {
9125 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9126 if (cmp)
9127 return cmp;
9128 }
9129
9130 return 0;
9131}
9132
9133int isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9134 __isl_keep isl_basic_map *bmap2)
9135{
9136 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9137}
9138
9139int isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9140 __isl_keep isl_basic_set *bset2)
9141{
9142 return isl_basic_map_plain_is_equal((isl_basic_map *)bset1,
9143 (isl_basic_map *)bset2);
9144}
9145
9146static int qsort_bmap_cmp(const void *p1, const void *p2)
9147{
9148 const struct isl_basic_map *bmap1 = *(const struct isl_basic_map **)p1;
9149 const struct isl_basic_map *bmap2 = *(const struct isl_basic_map **)p2;
9150
9151 return isl_basic_map_plain_cmp(bmap1, bmap2);
9152}
9153
9154/* Sort the basic maps of "map" and remove duplicate basic maps.
9155 *
9156 * While removing basic maps, we make sure that the basic maps remain
9157 * sorted because isl_map_normalize expects the basic maps of the result
9158 * to be sorted.
9159 */
9160static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9161{
9162 int i, j;
9163
9164 map = isl_map_remove_empty_parts(map);
9165 if (!map)
9166 return NULL;
9167 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9168 for (i = map->n - 1; i >= 1; --i) {
9169 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9170 continue;
9171 isl_basic_map_free(map->p[i-1]);
9172 for (j = i; j < map->n; ++j)
9173 map->p[j - 1] = map->p[j];
9174 map->n--;
9175 }
9176
9177 return map;
9178}
9179
9180/* Remove obvious duplicates among the basic maps of "map".
9181 *
9182 * Unlike isl_map_normalize, this function does not remove redundant
9183 * constraints and only removes duplicates that have exactly the same
9184 * constraints in the input. It does sort the constraints and
9185 * the basic maps to ease the detection of duplicates.
9186 *
9187 * If "map" has already been normalized or if the basic maps are
9188 * disjoint, then there can be no duplicates.
9189 */
9190__isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9191{
9192 int i;
9193 isl_basic_map *bmap;
9194
9195 if (!map)
9196 return NULL;
9197 if (map->n <= 1)
9198 return map;
9199 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9200 return map;
9201 for (i = 0; i < map->n; ++i) {
9202 bmap = isl_basic_map_copy(map->p[i]);
9203 bmap = isl_basic_map_sort_constraints(bmap);
9204 if (!bmap)
9205 return isl_map_free(map);
9206 isl_basic_map_free(map->p[i]);
9207 map->p[i] = bmap;
9208 }
9209
9210 map = sort_and_remove_duplicates(map);
9211 return map;
9212}
9213
9214/* We normalize in place, but if anything goes wrong we need
9215 * to return NULL, so we need to make sure we don't change the
9216 * meaning of any possible other copies of map.
9217 */
9218__isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9219{
9220 int i;
9221 struct isl_basic_map *bmap;
9222
9223 if (!map)
9224 return NULL;
9225 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9226 return map;
9227 for (i = 0; i < map->n; ++i) {
9228 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9229 if (!bmap)
9230 goto error;
9231 isl_basic_map_free(map->p[i]);
9232 map->p[i] = bmap;
9233 }
9234
9235 map = sort_and_remove_duplicates(map);
9236 if (map)
9237 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9238 return map;
9239error:
9240 isl_map_free(map);
9241 return NULL;
9242}
9243
9244struct isl_set *isl_set_normalize(struct isl_set *set)
9245{
9246 return (struct isl_set *)isl_map_normalize((struct isl_map *)set);
9247}
9248
9249int isl_map_plain_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9250{
9251 int i;
9252 int equal;
9253
9254 if (!map1 || !map2)
9255 return -1;
9256
9257 if (map1 == map2)
9258 return 1;
9259 if (!isl_space_is_equal(map1->dim, map2->dim))
9260 return 0;
9261
9262 map1 = isl_map_copy(map1);
9263 map2 = isl_map_copy(map2);
9264 map1 = isl_map_normalize(map1);
9265 map2 = isl_map_normalize(map2);
9266 if (!map1 || !map2)
9267 goto error;
9268 equal = map1->n == map2->n;
9269 for (i = 0; equal && i < map1->n; ++i) {
9270 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9271 if (equal < 0)
9272 goto error;
9273 }
9274 isl_map_free(map1);
9275 isl_map_free(map2);
9276 return equal;
9277error:
9278 isl_map_free(map1);
9279 isl_map_free(map2);
9280 return -1;
9281}
9282
9283int isl_map_fast_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9284{
9285 return isl_map_plain_is_equal(map1, map2);
9286}
9287
9288int isl_set_plain_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9289{
9290 return isl_map_plain_is_equal((struct isl_map *)set1,
9291 (struct isl_map *)set2);
9292}
9293
9294int isl_set_fast_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9295{
9296 return isl_set_plain_is_equal(set1, set2);
9297}
9298
9299/* Return an interval that ranges from min to max (inclusive)
9300 */
9301struct isl_basic_set *isl_basic_set_interval(struct isl_ctx *ctx,
9302 isl_int min, isl_int max)
9303{
9304 int k;
9305 struct isl_basic_set *bset = NULL;
9306
9307 bset = isl_basic_set_alloc(ctx, 0, 1, 0, 0, 2);
9308 if (!bset)
9309 goto error;
9310
9311 k = isl_basic_set_alloc_inequality(bset);
9312 if (k < 0)
9313 goto error;
9314 isl_int_set_si(bset->ineq[k][1], 1);
9315 isl_int_neg(bset->ineq[k][0], min);
9316
9317 k = isl_basic_set_alloc_inequality(bset);
9318 if (k < 0)
9319 goto error;
9320 isl_int_set_si(bset->ineq[k][1], -1);
9321 isl_int_set(bset->ineq[k][0], max);
9322
9323 return bset;
9324error:
9325 isl_basic_set_free(bset);
9326 return NULL;
9327}
9328
9329/* Return the basic sets in "set" as a list.
9330 */
9331__isl_give isl_basic_set_list *isl_set_get_basic_set_list(
9332 __isl_keep isl_set *set)
9333{
9334 int i;
9335 isl_ctx *ctx;
9336 isl_basic_set_list *list;
9337
9338 if (!set)
9339 return NULL;
9340 ctx = isl_set_get_ctx(set);
9341 list = isl_basic_set_list_alloc(ctx, set->n);
9342
9343 for (i = 0; i < set->n; ++i) {
9344 isl_basic_set *bset;
9345
9346 bset = isl_basic_set_copy(set->p[i]);
9347 list = isl_basic_set_list_add(list, bset);
9348 }
9349
9350 return list;
9351}
9352
9353/* Return the intersection of the elements in the non-empty list "list".
9354 * All elements are assumed to live in the same space.
9355 */
9356__isl_give isl_basic_set *isl_basic_set_list_intersect(
9357 __isl_take struct isl_basic_set_list *list)
9358{
9359 int i, n;
9360 isl_basic_set *bset;
9361
9362 if (!list)
9363 return NULL;
9364 n = isl_basic_set_list_n_basic_set(list);
9365 if (n < 1)
9366 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9367 "expecting non-empty list", goto error);
9368
9369 bset = isl_basic_set_list_get_basic_set(list, 0);
9370 for (i = 1; i < n; ++i) {
9371 isl_basic_set *bset_i;
9372
9373 bset_i = isl_basic_set_list_get_basic_set(list, i);
9374 bset = isl_basic_set_intersect(bset, bset_i);
9375 }
9376
9377 isl_basic_set_list_free(list);
9378 return bset;
9379error:
9380 isl_basic_set_list_free(list);
9381 return NULL;
9382}
9383
9384/* Return the Cartesian product of the basic sets in list (in the given order).
9385 */
9386__isl_give isl_basic_set *isl_basic_set_list_product(
9387 __isl_take struct isl_basic_set_list *list)
9388{
9389 int i;
9390 unsigned dim;
9391 unsigned nparam;
9392 unsigned extra;
9393 unsigned n_eq;
9394 unsigned n_ineq;
9395 struct isl_basic_set *product = NULL;
9396
9397 if (!list)
9398 goto error;
9399 isl_assert(list->ctx, list->n > 0, goto error);
9400 isl_assert(list->ctx, list->p[0], goto error);
9401 nparam = isl_basic_set_n_param(list->p[0]);
9402 dim = isl_basic_set_n_dim(list->p[0]);
9403 extra = list->p[0]->n_div;
9404 n_eq = list->p[0]->n_eq;
9405 n_ineq = list->p[0]->n_ineq;
9406 for (i = 1; i < list->n; ++i) {
9407 isl_assert(list->ctx, list->p[i], goto error);
9408 isl_assert(list->ctx,
9409 nparam == isl_basic_set_n_param(list->p[i]), goto error);
9410 dim += isl_basic_set_n_dim(list->p[i]);
9411 extra += list->p[i]->n_div;
9412 n_eq += list->p[i]->n_eq;
9413 n_ineq += list->p[i]->n_ineq;
9414 }
9415 product = isl_basic_set_alloc(list->ctx, nparam, dim, extra,
9416 n_eq, n_ineq);
9417 if (!product)
9418 goto error;
9419 dim = 0;
9420 for (i = 0; i < list->n; ++i) {
9421 isl_basic_set_add_constraints(product,
9422 isl_basic_set_copy(list->p[i]), dim);
9423 dim += isl_basic_set_n_dim(list->p[i]);
9424 }
9425 isl_basic_set_list_free(list);
9426 return product;
9427error:
9428 isl_basic_set_free(product);
9429 isl_basic_set_list_free(list);
9430 return NULL;
9431}
9432
9433struct isl_basic_map *isl_basic_map_product(
9434 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
9435{
9436 isl_space *dim_result = NULL;
9437 struct isl_basic_map *bmap;
9438 unsigned in1, in2, out1, out2, nparam, total, pos;
9439 struct isl_dim_map *dim_map1, *dim_map2;
9440
9441 if (!bmap1 || !bmap2)
9442 goto error;
9443
9444 isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
9445 bmap2->dim, isl_dim_param), goto error);
9446 dim_result = isl_space_product(isl_space_copy(bmap1->dim),
9447 isl_space_copy(bmap2->dim));
9448
9449 in1 = isl_basic_map_n_in(bmap1);
9450 in2 = isl_basic_map_n_in(bmap2);
9451 out1 = isl_basic_map_n_out(bmap1);
9452 out2 = isl_basic_map_n_out(bmap2);
9453 nparam = isl_basic_map_n_param(bmap1);
9454
9455 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9456 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9457 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9458 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9459 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9460 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9461 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9462 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9463 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9464 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9465 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9466
9467 bmap = isl_basic_map_alloc_space(dim_result,
9468 bmap1->n_div + bmap2->n_div,
9469 bmap1->n_eq + bmap2->n_eq,
9470 bmap1->n_ineq + bmap2->n_ineq);
9471 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9472 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9473 bmap = isl_basic_map_simplify(bmap);
9474 return isl_basic_map_finalize(bmap);
9475error:
9476 isl_basic_map_free(bmap1);
9477 isl_basic_map_free(bmap2);
9478 return NULL;
9479}
9480
9481__isl_give isl_basic_map *isl_basic_map_flat_product(
9482 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9483{
9484 isl_basic_map *prod;
9485
9486 prod = isl_basic_map_product(bmap1, bmap2);
9487 prod = isl_basic_map_flatten(prod);
9488 return prod;
9489}
9490
9491__isl_give isl_basic_set *isl_basic_set_flat_product(
9492 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9493{
9494 return isl_basic_map_flat_range_product(bset1, bset2);
9495}
9496
9497__isl_give isl_basic_map *isl_basic_map_domain_product(
9498 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9499{
9500 isl_space *space_result = NULL;
9501 isl_basic_map *bmap;
9502 unsigned in1, in2, out, nparam, total, pos;
9503 struct isl_dim_map *dim_map1, *dim_map2;
9504
9505 if (!bmap1 || !bmap2)
9506 goto error;
9507
9508 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9509 isl_space_copy(bmap2->dim));
9510
9511 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9512 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9513 out = isl_basic_map_dim(bmap1, isl_dim_out);
9514 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9515
9516 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9517 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9518 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9519 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9520 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9521 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9522 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9523 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9524 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9525 isl_dim_map_div(dim_map1, bmap1, pos += out);
9526 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9527
9528 bmap = isl_basic_map_alloc_space(space_result,
9529 bmap1->n_div + bmap2->n_div,
9530 bmap1->n_eq + bmap2->n_eq,
9531 bmap1->n_ineq + bmap2->n_ineq);
9532 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9533 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9534 bmap = isl_basic_map_simplify(bmap);
9535 return isl_basic_map_finalize(bmap);
9536error:
9537 isl_basic_map_free(bmap1);
9538 isl_basic_map_free(bmap2);
9539 return NULL;
9540}
9541
9542__isl_give isl_basic_map *isl_basic_map_range_product(
9543 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9544{
9545 isl_space *dim_result = NULL;
9546 isl_basic_map *bmap;
9547 unsigned in, out1, out2, nparam, total, pos;
9548 struct isl_dim_map *dim_map1, *dim_map2;
9549
9550 if (!bmap1 || !bmap2)
9551 goto error;
9552
9553 if (!isl_space_match(bmap1->dim, isl_dim_param,
9554 bmap2->dim, isl_dim_param))
9555 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
9556 "parameters don't match", goto error);
9557
9558 dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
9559 isl_space_copy(bmap2->dim));
9560
9561 in = isl_basic_map_dim(bmap1, isl_dim_in);
9562 out1 = isl_basic_map_n_out(bmap1);
9563 out2 = isl_basic_map_n_out(bmap2);
9564 nparam = isl_basic_map_n_param(bmap1);
9565
9566 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
9567 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9568 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9569 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9570 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9571 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9572 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
9573 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
9574 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9575 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9576 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9577
9578 bmap = isl_basic_map_alloc_space(dim_result,
9579 bmap1->n_div + bmap2->n_div,
9580 bmap1->n_eq + bmap2->n_eq,
9581 bmap1->n_ineq + bmap2->n_ineq);
9582 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9583 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9584 bmap = isl_basic_map_simplify(bmap);
9585 return isl_basic_map_finalize(bmap);
9586error:
9587 isl_basic_map_free(bmap1);
9588 isl_basic_map_free(bmap2);
9589 return NULL;
9590}
9591
9592__isl_give isl_basic_map *isl_basic_map_flat_range_product(
9593 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9594{
9595 isl_basic_map *prod;
9596
9597 prod = isl_basic_map_range_product(bmap1, bmap2);
9598 prod = isl_basic_map_flatten_range(prod);
9599 return prod;
9600}
9601
9602/* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
9603 * and collect the results.
9604 * The result live in the space obtained by calling "space_product"
9605 * on the spaces of "map1" and "map2".
9606 * If "remove_duplicates" is set then the result may contain duplicates
9607 * (even if the inputs do not) and so we try and remove the obvious
9608 * duplicates.
9609 */
9610static __isl_give isl_map *map_product(__isl_take isl_map *map1,
9611 __isl_take isl_map *map2,
9612 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
9613 __isl_take isl_space *right),
9614 __isl_give isl_basic_map *(*basic_map_product)(
9615 __isl_take isl_basic_map *left,
9616 __isl_take isl_basic_map *right),
9617 int remove_duplicates)
9618{
9619 unsigned flags = 0;
9620 struct isl_map *result;
9621 int i, j;
9622
9623 if (!map1 || !map2)
9624 goto error;
9625
9626 isl_assert(map1->ctx, isl_space_match(map1->dim, isl_dim_param,
9627 map2->dim, isl_dim_param), goto error);
9628
9629 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
9630 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
9631 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
9632
9633 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
9634 isl_space_copy(map2->dim)),
9635 map1->n * map2->n, flags);
9636 if (!result)
9637 goto error;
9638 for (i = 0; i < map1->n; ++i)
9639 for (j = 0; j < map2->n; ++j) {
9640 struct isl_basic_map *part;
9641 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
9642 isl_basic_map_copy(map2->p[j]));
9643 if (isl_basic_map_is_empty(part))
9644 isl_basic_map_free(part);
9645 else
9646 result = isl_map_add_basic_map(result, part);
9647 if (!result)
9648 goto error;
9649 }
9650 if (remove_duplicates)
9651 result = isl_map_remove_obvious_duplicates(result);
9652 isl_map_free(map1);
9653 isl_map_free(map2);
9654 return result;
9655error:
9656 isl_map_free(map1);
9657 isl_map_free(map2);
9658 return NULL;
9659}
9660
9661/* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
9662 */
9663static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
9664 __isl_take isl_map *map2)
9665{
9666 return map_product(map1, map2, &isl_space_product,
9667 &isl_basic_map_product, 0);
9668}
9669
9670__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
9671 __isl_take isl_map *map2)
9672{
9673 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
9674}
9675
9676/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
9677 */
9678__isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
9679 __isl_take isl_map *map2)
9680{
9681 isl_map *prod;
9682
9683 prod = isl_map_product(map1, map2);
9684 prod = isl_map_flatten(prod);
9685 return prod;
9686}
9687
9688/* Given two set A and B, construct its Cartesian product A x B.
9689 */
9690struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
9691{
9692 return isl_map_range_product(set1, set2);
9693}
9694
9695__isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
9696 __isl_take isl_set *set2)
9697{
9698 return isl_map_flat_range_product(set1, set2);
9699}
9700
9701/* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
9702 */
9703static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
9704 __isl_take isl_map *map2)
9705{
9706 return map_product(map1, map2, &isl_space_domain_product,
9707 &isl_basic_map_domain_product, 1);
9708}
9709
9710/* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
9711 */
9712static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
9713 __isl_take isl_map *map2)
9714{
9715 return map_product(map1, map2, &isl_space_range_product,
9716 &isl_basic_map_range_product, 1);
9717}
9718
9719__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
9720 __isl_take isl_map *map2)
9721{
9722 return isl_map_align_params_map_map_and(map1, map2,
9723 &map_domain_product_aligned);
9724}
9725
9726__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
9727 __isl_take isl_map *map2)
9728{
9729 return isl_map_align_params_map_map_and(map1, map2,
9730 &map_range_product_aligned);
9731}
9732
9733/* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
9734 */
9735__isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
9736{
9737 isl_space *space;
9738 int total1, keep1, total2, keep2;
9739
9740 if (!map)
9741 return NULL;
9742 if (!isl_space_domain_is_wrapping(map->dim) ||
9743 !isl_space_range_is_wrapping(map->dim))
9744 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9745 "not a product", return isl_map_free(map));
9746
9747 space = isl_map_get_space(map);
9748 total1 = isl_space_dim(space, isl_dim_in);
9749 total2 = isl_space_dim(space, isl_dim_out);
9750 space = isl_space_factor_domain(space);
9751 keep1 = isl_space_dim(space, isl_dim_in);
9752 keep2 = isl_space_dim(space, isl_dim_out);
9753 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
9754 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
9755 map = isl_map_reset_space(map, space);
9756
9757 return map;
9758}
9759
9760/* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
9761 */
9762__isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
9763{
9764 isl_space *space;
9765 int total1, keep1, total2, keep2;
9766
9767 if (!map)
9768 return NULL;
9769 if (!isl_space_domain_is_wrapping(map->dim) ||
9770 !isl_space_range_is_wrapping(map->dim))
9771 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9772 "not a product", return isl_map_free(map));
9773
9774 space = isl_map_get_space(map);
9775 total1 = isl_space_dim(space, isl_dim_in);
9776 total2 = isl_space_dim(space, isl_dim_out);
9777 space = isl_space_factor_range(space);
9778 keep1 = isl_space_dim(space, isl_dim_in);
9779 keep2 = isl_space_dim(space, isl_dim_out);
9780 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
9781 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
9782 map = isl_map_reset_space(map, space);
9783
9784 return map;
9785}
9786
9787/* Given a map of the form [A -> B] -> C, return the map A -> C.
9788 */
9789__isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
9790{
9791 isl_space *space;
9792 int total, keep;
9793
9794 if (!map)
9795 return NULL;
9796 if (!isl_space_domain_is_wrapping(map->dim))
9797 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9798 "domain is not a product", return isl_map_free(map));
9799
9800 space = isl_map_get_space(map);
9801 total = isl_space_dim(space, isl_dim_in);
9802 space = isl_space_domain_factor_domain(space);
9803 keep = isl_space_dim(space, isl_dim_in);
9804 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
9805 map = isl_map_reset_space(map, space);
9806
9807 return map;
9808}
9809
9810/* Given a map of the form [A -> B] -> C, return the map B -> C.
9811 */
9812__isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
9813{
9814 isl_space *space;
9815 int total, keep;
9816
9817 if (!map)
9818 return NULL;
9819 if (!isl_space_domain_is_wrapping(map->dim))
9820 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9821 "domain is not a product", return isl_map_free(map));
9822
9823 space = isl_map_get_space(map);
9824 total = isl_space_dim(space, isl_dim_in);
9825 space = isl_space_domain_factor_range(space);
9826 keep = isl_space_dim(space, isl_dim_in);
9827 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
9828 map = isl_map_reset_space(map, space);
9829
9830 return map;
9831}
9832
9833/* Given a map A -> [B -> C], extract the map A -> B.
9834 */
9835__isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
9836{
9837 isl_space *space;
9838 int total, keep;
9839
9840 if (!map)
9841 return NULL;
9842 if (!isl_space_range_is_wrapping(map->dim))
9843 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9844 "range is not a product", return isl_map_free(map));
9845
9846 space = isl_map_get_space(map);
9847 total = isl_space_dim(space, isl_dim_out);
9848 space = isl_space_range_factor_domain(space);
9849 keep = isl_space_dim(space, isl_dim_out);
9850 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
9851 map = isl_map_reset_space(map, space);
9852
9853 return map;
9854}
9855
9856/* Given a map A -> [B -> C], extract the map A -> C.
9857 */
9858__isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
9859{
9860 isl_space *space;
9861 int total, keep;
9862
9863 if (!map)
9864 return NULL;
9865 if (!isl_space_range_is_wrapping(map->dim))
9866 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9867 "range is not a product", return isl_map_free(map));
9868
9869 space = isl_map_get_space(map);
9870 total = isl_space_dim(space, isl_dim_out);
9871 space = isl_space_range_factor_range(space);
9872 keep = isl_space_dim(space, isl_dim_out);
9873 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
9874 map = isl_map_reset_space(map, space);
9875
9876 return map;
9877}
9878
9879/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
9880 */
9881__isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
9882 __isl_take isl_map *map2)
9883{
9884 isl_map *prod;
9885
9886 prod = isl_map_domain_product(map1, map2);
9887 prod = isl_map_flatten_domain(prod);
9888 return prod;
9889}
9890
9891/* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
9892 */
9893__isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
9894 __isl_take isl_map *map2)
9895{
9896 isl_map *prod;
9897
9898 prod = isl_map_range_product(map1, map2);
9899 prod = isl_map_flatten_range(prod);
9900 return prod;
9901}
9902
9903uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
9904{
9905 int i;
9906 uint32_t hash = isl_hash_init();
9907 unsigned total;
9908
9909 if (!bmap)
9910 return 0;
9911 bmap = isl_basic_map_copy(bmap);
9912 bmap = isl_basic_map_normalize(bmap);
9913 if (!bmap)
9914 return 0;
9915 total = isl_basic_map_total_dim(bmap);
9916 isl_hash_byte(hash, bmap->n_eq & 0xFF);
9917 for (i = 0; i < bmap->n_eq; ++i) {
9918 uint32_t c_hash;
9919 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
9920 isl_hash_hash(hash, c_hash);
9921 }
9922 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
9923 for (i = 0; i < bmap->n_ineq; ++i) {
9924 uint32_t c_hash;
9925 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
9926 isl_hash_hash(hash, c_hash);
9927 }
9928 isl_hash_byte(hash, bmap->n_div & 0xFF);
9929 for (i = 0; i < bmap->n_div; ++i) {
9930 uint32_t c_hash;
9931 if (isl_int_is_zero(bmap->div[i][0]))
9932 continue;
9933 isl_hash_byte(hash, i & 0xFF);
9934 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
9935 isl_hash_hash(hash, c_hash);
9936 }
9937 isl_basic_map_free(bmap);
9938 return hash;
9939}
9940
9941uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
9942{
9943 return isl_basic_map_get_hash((isl_basic_map *)bset);
9944}
9945
9946uint32_t isl_map_get_hash(__isl_keep isl_map *map)
9947{
9948 int i;
9949 uint32_t hash;
9950
9951 if (!map)
9952 return 0;
9953 map = isl_map_copy(map);
9954 map = isl_map_normalize(map);
9955 if (!map)
9956 return 0;
9957
9958 hash = isl_hash_init();
9959 for (i = 0; i < map->n; ++i) {
9960 uint32_t bmap_hash;
9961 bmap_hash = isl_basic_map_get_hash(map->p[i]);
9962 isl_hash_hash(hash, bmap_hash);
9963 }
9964
9965 isl_map_free(map);
9966
9967 return hash;
9968}
9969
9970uint32_t isl_set_get_hash(__isl_keep isl_set *set)
9971{
9972 return isl_map_get_hash((isl_map *)set);
9973}
9974
9975/* Check if the value for dimension dim is completely determined
9976 * by the values of the other parameters and variables.
9977 * That is, check if dimension dim is involved in an equality.
9978 */
9979int isl_basic_set_dim_is_unique(struct isl_basic_set *bset, unsigned dim)
9980{
9981 int i;
9982 unsigned nparam;
9983
9984 if (!bset)
9985 return -1;
9986 nparam = isl_basic_set_n_param(bset);
9987 for (i = 0; i < bset->n_eq; ++i)
9988 if (!isl_int_is_zero(bset->eq[i][1 + nparam + dim]))
9989 return 1;
9990 return 0;
9991}
9992
9993/* Check if the value for dimension dim is completely determined
9994 * by the values of the other parameters and variables.
9995 * That is, check if dimension dim is involved in an equality
9996 * for each of the subsets.
9997 */
9998int isl_set_dim_is_unique(struct isl_set *set, unsigned dim)
9999{
10000 int i;
10001
10002 if (!set)
10003 return -1;
10004 for (i = 0; i < set->n; ++i) {
10005 int unique;
10006 unique = isl_basic_set_dim_is_unique(set->p[i], dim);
10007 if (unique != 1)
10008 return unique;
10009 }
10010 return 1;
10011}
10012
10013/* Return the number of basic maps in the (current) representation of "map".
10014 */
10015int isl_map_n_basic_map(__isl_keep isl_map *map)
10016{
10017 return map ? map->n : 0;
10018}
10019
10020int isl_set_n_basic_set(__isl_keep isl_set *set)
10021{
10022 return set ? set->n : 0;
10023}
10024
10025int isl_map_foreach_basic_map(__isl_keep isl_map *map,
10026 int (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10027{
10028 int i;
10029
10030 if (!map)
10031 return -1;
10032
10033 for (i = 0; i < map->n; ++i)
10034 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10035 return -1;
10036
10037 return 0;
10038}
10039
10040int isl_set_foreach_basic_set(__isl_keep isl_set *set,
10041 int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10042{
10043 int i;
10044
10045 if (!set)
10046 return -1;
10047
10048 for (i = 0; i < set->n; ++i)
10049 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10050 return -1;
10051
10052 return 0;
10053}
10054
10055__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10056{
10057 isl_space *dim;
10058
10059 if (!bset)
10060 return NULL;
10061
10062 bset = isl_basic_set_cow(bset);
10063 if (!bset)
10064 return NULL;
10065
10066 dim = isl_basic_set_get_space(bset);
10067 dim = isl_space_lift(dim, bset->n_div);
10068 if (!dim)
10069 goto error;
10070 isl_space_free(bset->dim);
10071 bset->dim = dim;
10072 bset->extra -= bset->n_div;
10073 bset->n_div = 0;
10074
10075 bset = isl_basic_set_finalize(bset);
10076
10077 return bset;
10078error:
10079 isl_basic_set_free(bset);
10080 return NULL;
10081}
10082
10083__isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10084{
10085 int i;
10086 isl_space *dim;
10087 unsigned n_div;
10088
10089 set = isl_set_align_divs(set);
10090
10091 if (!set)
10092 return NULL;
10093
10094 set = isl_set_cow(set);
10095 if (!set)
10096 return NULL;
10097
10098 n_div = set->p[0]->n_div;
10099 dim = isl_set_get_space(set);
10100 dim = isl_space_lift(dim, n_div);
10101 if (!dim)
10102 goto error;
10103 isl_space_free(set->dim);
10104 set->dim = dim;
10105
10106 for (i = 0; i < set->n; ++i) {
10107 set->p[i] = isl_basic_set_lift(set->p[i]);
10108 if (!set->p[i])
10109 goto error;
10110 }
10111
10112 return set;
10113error:
10114 isl_set_free(set);
10115 return NULL;
10116}
10117
10118__isl_give isl_map *isl_set_lifting(__isl_take isl_set *set)
10119{
10120 isl_space *dim;
10121 struct isl_basic_map *bmap;
10122 unsigned n_set;
10123 unsigned n_div;
10124 unsigned n_param;
10125 unsigned total;
10126 int i, k, l;
10127
10128 set = isl_set_align_divs(set);
10129
10130 if (!set)
10131 return NULL;
10132
10133 dim = isl_set_get_space(set);
10134 if (set->n == 0 || set->p[0]->n_div == 0) {
10135 isl_set_free(set);
10136 return isl_map_identity(isl_space_map_from_set(dim));
10137 }
10138
10139 n_div = set->p[0]->n_div;
10140 dim = isl_space_map_from_set(dim);
10141 n_param = isl_space_dim(dim, isl_dim_param);
10142 n_set = isl_space_dim(dim, isl_dim_in);
10143 dim = isl_space_extend(dim, n_param, n_set, n_set + n_div);
10144 bmap = isl_basic_map_alloc_space(dim, 0, n_set, 2 * n_div);
10145 for (i = 0; i < n_set; ++i)
10146 bmap = var_equal(bmap, i);
10147
10148 total = n_param + n_set + n_set + n_div;
10149 for (i = 0; i < n_div; ++i) {
10150 k = isl_basic_map_alloc_inequality(bmap);
10151 if (k < 0)
10152 goto error;
10153 isl_seq_cpy(bmap->ineq[k], set->p[0]->div[i]+1, 1+n_param);
10154 isl_seq_clr(bmap->ineq[k]+1+n_param, n_set);
10155 isl_seq_cpy(bmap->ineq[k]+1+n_param+n_set,
10156 set->p[0]->div[i]+1+1+n_param, n_set + n_div);
10157 isl_int_neg(bmap->ineq[k][1+n_param+n_set+n_set+i],
10158 set->p[0]->div[i][0]);
10159
10160 l = isl_basic_map_alloc_inequality(bmap);
10161 if (l < 0)
10162 goto error;
10163 isl_seq_neg(bmap->ineq[l], bmap->ineq[k], 1 + total);
10164 isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0],
10165 set->p[0]->div[i][0]);
10166 isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
10167 }
10168
10169 isl_set_free(set);
10170 bmap = isl_basic_map_simplify(bmap);
10171 bmap = isl_basic_map_finalize(bmap);
10172 return isl_map_from_basic_map(bmap);
10173error:
10174 isl_set_free(set);
10175 isl_basic_map_free(bmap);
10176 return NULL;
10177}
10178
10179int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10180{
10181 unsigned dim;
10182 int size = 0;
10183
10184 if (!bset)
10185 return -1;
10186
10187 dim = isl_basic_set_total_dim(bset);
10188 size += bset->n_eq * (1 + dim);
10189 size += bset->n_ineq * (1 + dim);
10190 size += bset->n_div * (2 + dim);
10191
10192 return size;
10193}
10194
10195int isl_set_size(__isl_keep isl_set *set)
10196{
10197 int i;
10198 int size = 0;
10199
10200 if (!set)
10201 return -1;
10202
10203 for (i = 0; i < set->n; ++i)
10204 size += isl_basic_set_size(set->p[i]);
10205
10206 return size;
10207}
10208
10209/* Check if there is any lower bound (if lower == 0) and/or upper
10210 * bound (if upper == 0) on the specified dim.
10211 */
10212static int basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10213 enum isl_dim_type type, unsigned pos, int lower, int upper)
10214{
10215 int i;
10216
10217 if (!bmap)
10218 return -1;
10219
10220 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), return -1);
10221
10222 pos += isl_basic_map_offset(bmap, type);
10223
10224 for (i = 0; i < bmap->n_div; ++i) {
10225 if (isl_int_is_zero(bmap->div[i][0]))
10226 continue;
10227 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10228 return 1;
10229 }
10230
10231 for (i = 0; i < bmap->n_eq; ++i)
10232 if (!isl_int_is_zero(bmap->eq[i][pos]))
10233 return 1;
10234
10235 for (i = 0; i < bmap->n_ineq; ++i) {
10236 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10237 if (sgn > 0)
10238 lower = 1;
10239 if (sgn < 0)
10240 upper = 1;
10241 }
10242
10243 return lower && upper;
10244}
10245
10246int isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10247 enum isl_dim_type type, unsigned pos)
10248{
10249 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10250}
10251
10252int isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10253 enum isl_dim_type type, unsigned pos)
10254{
10255 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10256}
10257
10258int isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10259 enum isl_dim_type type, unsigned pos)
10260{
10261 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10262}
10263
10264int isl_map_dim_is_bounded(__isl_keep isl_map *map,
10265 enum isl_dim_type type, unsigned pos)
10266{
10267 int i;
10268
10269 if (!map)
10270 return -1;
10271
10272 for (i = 0; i < map->n; ++i) {
10273 int bounded;
10274 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10275 if (bounded < 0 || !bounded)
10276 return bounded;
10277 }
10278
10279 return 1;
10280}
10281
10282/* Return 1 if the specified dim is involved in both an upper bound
10283 * and a lower bound.
10284 */
10285int isl_set_dim_is_bounded(__isl_keep isl_set *set,
10286 enum isl_dim_type type, unsigned pos)
10287{
10288 return isl_map_dim_is_bounded((isl_map *)set, type, pos);
10289}
10290
10291/* Does "map" have a bound (according to "fn") for any of its basic maps?
10292 */
10293static int has_any_bound(__isl_keep isl_map *map,
10294 enum isl_dim_type type, unsigned pos,
10295 int (*fn)(__isl_keep isl_basic_map *bmap,
10296 enum isl_dim_type type, unsigned pos))
10297{
10298 int i;
10299
10300 if (!map)
10301 return -1;
10302
10303 for (i = 0; i < map->n; ++i) {
10304 int bounded;
10305 bounded = fn(map->p[i], type, pos);
10306 if (bounded < 0 || bounded)
10307 return bounded;
10308 }
10309
10310 return 0;
10311}
10312
10313/* Return 1 if the specified dim is involved in any lower bound.
10314 */
10315int isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10316 enum isl_dim_type type, unsigned pos)
10317{
10318 return has_any_bound(set, type, pos,
10319 &isl_basic_map_dim_has_lower_bound);
10320}
10321
10322/* Return 1 if the specified dim is involved in any upper bound.
10323 */
10324int isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10325 enum isl_dim_type type, unsigned pos)
10326{
10327 return has_any_bound(set, type, pos,
10328 &isl_basic_map_dim_has_upper_bound);
10329}
10330
10331/* Does "map" have a bound (according to "fn") for all of its basic maps?
10332 */
10333static int has_bound(__isl_keep isl_map *map,
10334 enum isl_dim_type type, unsigned pos,
10335 int (*fn)(__isl_keep isl_basic_map *bmap,
10336 enum isl_dim_type type, unsigned pos))
10337{
10338 int i;
10339
10340 if (!map)
10341 return -1;
10342
10343 for (i = 0; i < map->n; ++i) {
10344 int bounded;
10345 bounded = fn(map->p[i], type, pos);
10346 if (bounded < 0 || !bounded)
10347 return bounded;
10348 }
10349
10350 return 1;
10351}
10352
10353/* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10354 */
10355int isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10356 enum isl_dim_type type, unsigned pos)
10357{
10358 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10359}
10360
10361/* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10362 */
10363int isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10364 enum isl_dim_type type, unsigned pos)
10365{
10366 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10367}
10368
10369/* For each of the "n" variables starting at "first", determine
10370 * the sign of the variable and put the results in the first "n"
10371 * elements of the array "signs".
10372 * Sign
10373 * 1 means that the variable is non-negative
10374 * -1 means that the variable is non-positive
10375 * 0 means the variable attains both positive and negative values.
10376 */
10377int isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10378 unsigned first, unsigned n, int *signs)
10379{
10380 isl_vec *bound = NULL;
10381 struct isl_tab *tab = NULL;
10382 struct isl_tab_undo *snap;
10383 int i;
10384
10385 if (!bset || !signs)
10386 return -1;
10387
10388 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10389 tab = isl_tab_from_basic_set(bset, 0);
10390 if (!bound || !tab)
10391 goto error;
10392
10393 isl_seq_clr(bound->el, bound->size);
10394 isl_int_set_si(bound->el[0], -1);
10395
10396 snap = isl_tab_snap(tab);
10397 for (i = 0; i < n; ++i) {
10398 int empty;
10399
10400 isl_int_set_si(bound->el[1 + first + i], -1);
10401 if (isl_tab_add_ineq(tab, bound->el) < 0)
10402 goto error;
10403 empty = tab->empty;
10404 isl_int_set_si(bound->el[1 + first + i], 0);
10405 if (isl_tab_rollback(tab, snap) < 0)
10406 goto error;
10407
10408 if (empty) {
10409 signs[i] = 1;
10410 continue;
10411 }
10412
10413 isl_int_set_si(bound->el[1 + first + i], 1);
10414 if (isl_tab_add_ineq(tab, bound->el) < 0)
10415 goto error;
10416 empty = tab->empty;
10417 isl_int_set_si(bound->el[1 + first + i], 0);
10418 if (isl_tab_rollback(tab, snap) < 0)
10419 goto error;
10420
10421 signs[i] = empty ? -1 : 0;
10422 }
10423
10424 isl_tab_free(tab);
10425 isl_vec_free(bound);
10426 return 0;
10427error:
10428 isl_tab_free(tab);
10429 isl_vec_free(bound);
10430 return -1;
10431}
10432
10433int isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10434 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10435{
10436 if (!bset || !signs)
10437 return -1;
10438 isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
10439 return -1);
10440
10441 first += pos(bset->dim, type) - 1;
10442 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10443}
10444
10445/* Is it possible for the integer division "div" to depend (possibly
10446 * indirectly) on any output dimensions?
10447 *
10448 * If the div is undefined, then we conservatively assume that it
10449 * may depend on them.
10450 * Otherwise, we check if it actually depends on them or on any integer
10451 * divisions that may depend on them.
10452 */
10453static int div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10454{
10455 int i;
10456 unsigned n_out, o_out;
10457 unsigned n_div, o_div;
10458
10459 if (isl_int_is_zero(bmap->div[div][0]))
10460 return 1;
10461
10462 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10463 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10464
10465 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10466 return 1;
10467
10468 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10469 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10470
10471 for (i = 0; i < n_div; ++i) {
10472 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10473 continue;
10474 if (div_may_involve_output(bmap, i))
10475 return 1;
10476 }
10477
10478 return 0;
10479}
10480
10481/* Return the index of the equality of "bmap" that defines
10482 * the output dimension "pos" in terms of earlier dimensions.
10483 * The equality may also involve integer divisions, as long
10484 * as those integer divisions are defined in terms of
10485 * parameters or input dimensions.
10486 * Return bmap->n_eq if there is no such equality.
10487 * Return -1 on error.
10488 */
10489int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
10490 int pos)
10491{
10492 int j, k;
10493 unsigned n_out, o_out;
10494 unsigned n_div, o_div;
10495
10496 if (!bmap)
10497 return -1;
10498
10499 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10500 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10501 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10502 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10503
10504 for (j = 0; j < bmap->n_eq; ++j) {
10505 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
10506 continue;
10507 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
10508 n_out - (pos + 1)) != -1)
10509 continue;
10510 for (k = 0; k < n_div; ++k) {
10511 if (isl_int_is_zero(bmap->eq[j][o_div + k]))
10512 continue;
10513 if (div_may_involve_output(bmap, k))
10514 break;
10515 }
10516 if (k >= n_div)
10517 return j;
10518 }
10519
10520 return bmap->n_eq;
10521}
10522
10523/* Check if the given basic map is obviously single-valued.
10524 * In particular, for each output dimension, check that there is
10525 * an equality that defines the output dimension in terms of
10526 * earlier dimensions.
10527 */
10528int isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
10529{
10530 int i;
10531 unsigned n_out;
10532
10533 if (!bmap)
10534 return -1;
10535
10536 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10537
10538 for (i = 0; i < n_out; ++i) {
10539 int eq;
10540
10541 eq = isl_basic_map_output_defining_equality(bmap, i);
10542 if (eq < 0)
10543 return -1;
10544 if (eq >= bmap->n_eq)
10545 return 0;
10546 }
10547
10548 return 1;
10549}
10550
10551/* Check if the given basic map is single-valued.
10552 * We simply compute
10553 *
10554 * M \circ M^-1
10555 *
10556 * and check if the result is a subset of the identity mapping.
10557 */
10558int isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
10559{
10560 isl_space *space;
10561 isl_basic_map *test;
10562 isl_basic_map *id;
10563 int sv;
10564
10565 sv = isl_basic_map_plain_is_single_valued(bmap);
10566 if (sv < 0 || sv)
10567 return sv;
10568
10569 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
10570 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
10571
10572 space = isl_basic_map_get_space(bmap);
10573 space = isl_space_map_from_set(isl_space_range(space));
10574 id = isl_basic_map_identity(space);
10575
10576 sv = isl_basic_map_is_subset(test, id);
10577
10578 isl_basic_map_free(test);
10579 isl_basic_map_free(id);
10580
10581 return sv;
10582}
10583
10584/* Check if the given map is obviously single-valued.
10585 */
10586int isl_map_plain_is_single_valued(__isl_keep isl_map *map)
10587{
10588 if (!map)
10589 return -1;
10590 if (map->n == 0)
10591 return 1;
10592 if (map->n >= 2)
10593 return 0;
10594
10595 return isl_basic_map_plain_is_single_valued(map->p[0]);
10596}
10597
10598/* Check if the given map is single-valued.
10599 * We simply compute
10600 *
10601 * M \circ M^-1
10602 *
10603 * and check if the result is a subset of the identity mapping.
10604 */
10605int isl_map_is_single_valued(__isl_keep isl_map *map)
10606{
10607 isl_space *dim;
10608 isl_map *test;
10609 isl_map *id;
10610 int sv;
10611
10612 sv = isl_map_plain_is_single_valued(map);
10613 if (sv < 0 || sv)
10614 return sv;
10615
10616 test = isl_map_reverse(isl_map_copy(map));
10617 test = isl_map_apply_range(test, isl_map_copy(map));
10618
10619 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
10620 id = isl_map_identity(dim);
10621
10622 sv = isl_map_is_subset(test, id);
10623
10624 isl_map_free(test);
10625 isl_map_free(id);
10626
10627 return sv;
10628}
10629
10630int isl_map_is_injective(__isl_keep isl_map *map)
10631{
10632 int in;
10633
10634 map = isl_map_copy(map);
10635 map = isl_map_reverse(map);
10636 in = isl_map_is_single_valued(map);
10637 isl_map_free(map);
10638
10639 return in;
10640}
10641
10642/* Check if the given map is obviously injective.
10643 */
10644int isl_map_plain_is_injective(__isl_keep isl_map *map)
10645{
10646 int in;
10647
10648 map = isl_map_copy(map);
10649 map = isl_map_reverse(map);
10650 in = isl_map_plain_is_single_valued(map);
10651 isl_map_free(map);
10652
10653 return in;
10654}
10655
10656int isl_map_is_bijective(__isl_keep isl_map *map)
10657{
10658 int sv;
10659
10660 sv = isl_map_is_single_valued(map);
10661 if (sv < 0 || !sv)
10662 return sv;
10663
10664 return isl_map_is_injective(map);
10665}
10666
10667int isl_set_is_singleton(__isl_keep isl_set *set)
10668{
10669 return isl_map_is_single_valued((isl_map *)set);
10670}
10671
10672int isl_map_is_translation(__isl_keep isl_map *map)
10673{
10674 int ok;
10675 isl_set *delta;
10676
10677 delta = isl_map_deltas(isl_map_copy(map));
10678 ok = isl_set_is_singleton(delta);
10679 isl_set_free(delta);
10680
10681 return ok;
10682}
10683
10684static int unique(isl_int *p, unsigned pos, unsigned len)
10685{
10686 if (isl_seq_first_non_zero(p, pos) != -1)
10687 return 0;
10688 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
10689 return 0;
10690 return 1;
10691}
10692
10693int isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
10694{
10695 int i, j;
10696 unsigned nvar;
10697 unsigned ovar;
10698
10699 if (!bset)
10700 return -1;
10701
10702 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
10703 return 0;
10704
10705 nvar = isl_basic_set_dim(bset, isl_dim_set);
10706 ovar = isl_space_offset(bset->dim, isl_dim_set);
10707 for (j = 0; j < nvar; ++j) {
10708 int lower = 0, upper = 0;
10709 for (i = 0; i < bset->n_eq; ++i) {
10710 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
10711 continue;
10712 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
10713 return 0;
10714 break;
10715 }
10716 if (i < bset->n_eq)
10717 continue;
10718 for (i = 0; i < bset->n_ineq; ++i) {
10719 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
10720 continue;
10721 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
10722 return 0;
10723 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
10724 lower = 1;
10725 else
10726 upper = 1;
10727 }
10728 if (!lower || !upper)
10729 return 0;
10730 }
10731
10732 return 1;
10733}
10734
10735int isl_set_is_box(__isl_keep isl_set *set)
10736{
10737 if (!set)
10738 return -1;
10739 if (set->n != 1)
10740 return 0;
10741
10742 return isl_basic_set_is_box(set->p[0]);
10743}
10744
10745int isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
10746{
10747 if (!bset)
10748 return -1;
10749
10750 return isl_space_is_wrapping(bset->dim);
10751}
10752
10753int isl_set_is_wrapping(__isl_keep isl_set *set)
10754{
10755 if (!set)
10756 return -1;
10757
10758 return isl_space_is_wrapping(set->dim);
10759}
10760
10761/* Is the domain of "map" a wrapped relation?
10762 */
10763int isl_map_domain_is_wrapping(__isl_keep isl_map *map)
10764{
10765 if (!map)
10766 return -1;
10767
10768 return isl_space_domain_is_wrapping(map->dim);
10769}
10770
10771/* Is the range of "map" a wrapped relation?
10772 */
10773int isl_map_range_is_wrapping(__isl_keep isl_map *map)
10774{
10775 if (!map)
10776 return -1;
10777
10778 return isl_space_range_is_wrapping(map->dim);
10779}
10780
10781__isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
10782{
10783 bmap = isl_basic_map_cow(bmap);
10784 if (!bmap)
10785 return NULL;
10786
10787 bmap->dim = isl_space_wrap(bmap->dim);
10788 if (!bmap->dim)
10789 goto error;
10790
10791 bmap = isl_basic_map_finalize(bmap);
10792
10793 return (isl_basic_set *)bmap;
10794error:
10795 isl_basic_map_free(bmap);
10796 return NULL;
10797}
10798
10799__isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
10800{
10801 int i;
10802
10803 map = isl_map_cow(map);
10804 if (!map)
10805 return NULL;
10806
10807 for (i = 0; i < map->n; ++i) {
10808 map->p[i] = (isl_basic_map *)isl_basic_map_wrap(map->p[i]);
10809 if (!map->p[i])
10810 goto error;
10811 }
10812 map->dim = isl_space_wrap(map->dim);
10813 if (!map->dim)
10814 goto error;
10815
10816 return (isl_set *)map;
10817error:
10818 isl_map_free(map);
10819 return NULL;
10820}
10821
10822__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
10823{
10824 bset = isl_basic_set_cow(bset);
10825 if (!bset)
10826 return NULL;
10827
10828 bset->dim = isl_space_unwrap(bset->dim);
10829 if (!bset->dim)
10830 goto error;
10831
10832 bset = isl_basic_set_finalize(bset);
10833
10834 return (isl_basic_map *)bset;
10835error:
10836 isl_basic_set_free(bset);
10837 return NULL;
10838}
10839
10840__isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
10841{
10842 int i;
10843
10844 if (!set)
10845 return NULL;
10846
10847 if (!isl_set_is_wrapping(set))
10848 isl_die(set->ctx, isl_error_invalid, "not a wrapping set",
10849 goto error);
10850
10851 set = isl_set_cow(set);
10852 if (!set)
10853 return NULL;
10854
10855 for (i = 0; i < set->n; ++i) {
10856 set->p[i] = (isl_basic_set *)isl_basic_set_unwrap(set->p[i]);
10857 if (!set->p[i])
10858 goto error;
10859 }
10860
10861 set->dim = isl_space_unwrap(set->dim);
10862 if (!set->dim)
10863 goto error;
10864
10865 return (isl_map *)set;
10866error:
10867 isl_set_free(set);
10868 return NULL;
10869}
10870
10871__isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
10872 enum isl_dim_type type)
10873{
10874 if (!bmap)
10875 return NULL;
10876
10877 if (!isl_space_is_named_or_nested(bmap->dim, type))
10878 return bmap;
10879
10880 bmap = isl_basic_map_cow(bmap);
10881 if (!bmap)
10882 return NULL;
10883
10884 bmap->dim = isl_space_reset(bmap->dim, type);
10885 if (!bmap->dim)
10886 goto error;
10887
10888 bmap = isl_basic_map_finalize(bmap);
10889
10890 return bmap;
10891error:
10892 isl_basic_map_free(bmap);
10893 return NULL;
10894}
10895
10896__isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
10897 enum isl_dim_type type)
10898{
10899 int i;
10900
10901 if (!map)
10902 return NULL;
10903
10904 if (!isl_space_is_named_or_nested(map->dim, type))
10905 return map;
10906
10907 map = isl_map_cow(map);
10908 if (!map)
10909 return NULL;
10910
10911 for (i = 0; i < map->n; ++i) {
10912 map->p[i] = isl_basic_map_reset(map->p[i], type);
10913 if (!map->p[i])
10914 goto error;
10915 }
10916 map->dim = isl_space_reset(map->dim, type);
10917 if (!map->dim)
10918 goto error;
10919
10920 return map;
10921error:
10922 isl_map_free(map);
10923 return NULL;
10924}
10925
10926__isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
10927{
10928 if (!bmap)
10929 return NULL;
10930
10931 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
10932 return bmap;
10933
10934 bmap = isl_basic_map_cow(bmap);
10935 if (!bmap)
10936 return NULL;
10937
10938 bmap->dim = isl_space_flatten(bmap->dim);
10939 if (!bmap->dim)
10940 goto error;
10941
10942 bmap = isl_basic_map_finalize(bmap);
10943
10944 return bmap;
10945error:
10946 isl_basic_map_free(bmap);
10947 return NULL;
10948}
10949
10950__isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
10951{
10952 return (isl_basic_set *)isl_basic_map_flatten((isl_basic_map *)bset);
10953}
10954
10955__isl_give isl_basic_map *isl_basic_map_flatten_domain(
10956 __isl_take isl_basic_map *bmap)
10957{
10958 if (!bmap)
10959 return NULL;
10960
10961 if (!bmap->dim->nested[0])
10962 return bmap;
10963
10964 bmap = isl_basic_map_cow(bmap);
10965 if (!bmap)
10966 return NULL;
10967
10968 bmap->dim = isl_space_flatten_domain(bmap->dim);
10969 if (!bmap->dim)
10970 goto error;
10971
10972 bmap = isl_basic_map_finalize(bmap);
10973
10974 return bmap;
10975error:
10976 isl_basic_map_free(bmap);
10977 return NULL;
10978}
10979
10980__isl_give isl_basic_map *isl_basic_map_flatten_range(
10981 __isl_take isl_basic_map *bmap)
10982{
10983 if (!bmap)
10984 return NULL;
10985
10986 if (!bmap->dim->nested[1])
10987 return bmap;
10988
10989 bmap = isl_basic_map_cow(bmap);
10990 if (!bmap)
10991 return NULL;
10992
10993 bmap->dim = isl_space_flatten_range(bmap->dim);
10994 if (!bmap->dim)
10995 goto error;
10996
10997 bmap = isl_basic_map_finalize(bmap);
10998
10999 return bmap;
11000error:
11001 isl_basic_map_free(bmap);
11002 return NULL;
11003}
11004
11005__isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11006{
11007 int i;
11008
11009 if (!map)
11010 return NULL;
11011
11012 if (!map->dim->nested[0] && !map->dim->nested[1])
11013 return map;
11014
11015 map = isl_map_cow(map);
11016 if (!map)
11017 return NULL;
11018
11019 for (i = 0; i < map->n; ++i) {
11020 map->p[i] = isl_basic_map_flatten(map->p[i]);
11021 if (!map->p[i])
11022 goto error;
11023 }
11024 map->dim = isl_space_flatten(map->dim);
11025 if (!map->dim)
11026 goto error;
11027
11028 return map;
11029error:
11030 isl_map_free(map);
11031 return NULL;
11032}
11033
11034__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11035{
11036 return (isl_set *)isl_map_flatten((isl_map *)set);
11037}
11038
11039__isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11040{
11041 isl_space *dim, *flat_dim;
11042 isl_map *map;
11043
11044 dim = isl_set_get_space(set);
11045 flat_dim = isl_space_flatten(isl_space_copy(dim));
11046 map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
11047 map = isl_map_intersect_domain(map, set);
11048
11049 return map;
11050}
11051
11052__isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11053{
11054 int i;
11055
11056 if (!map)
11057 return NULL;
11058
11059 if (!map->dim->nested[0])
11060 return map;
11061
11062 map = isl_map_cow(map);
11063 if (!map)
11064 return NULL;
11065
11066 for (i = 0; i < map->n; ++i) {
11067 map->p[i] = isl_basic_map_flatten_domain(map->p[i]);
11068 if (!map->p[i])
11069 goto error;
11070 }
11071 map->dim = isl_space_flatten_domain(map->dim);
11072 if (!map->dim)
11073 goto error;
11074
11075 return map;
11076error:
11077 isl_map_free(map);
11078 return NULL;
11079}
11080
11081__isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11082{
11083 int i;
11084
11085 if (!map)
11086 return NULL;
11087
11088 if (!map->dim->nested[1])
11089 return map;
11090
11091 map = isl_map_cow(map);
11092 if (!map)
11093 return NULL;
11094
11095 for (i = 0; i < map->n; ++i) {
11096 map->p[i] = isl_basic_map_flatten_range(map->p[i]);
11097 if (!map->p[i])
11098 goto error;
11099 }
11100 map->dim = isl_space_flatten_range(map->dim);
11101 if (!map->dim)
11102 goto error;
11103
11104 return map;
11105error:
11106 isl_map_free(map);
11107 return NULL;
11108}
11109
11110/* Reorder the dimensions of "bmap" according to the given dim_map
11111 * and set the dimension specification to "dim".
11112 */
11113__isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11114 __isl_take isl_space *dim, __isl_take struct isl_dim_map *dim_map)
11115{
11116 isl_basic_map *res;
11117 unsigned flags;
11118
11119 bmap = isl_basic_map_cow(bmap);
11120 if (!bmap || !dim || !dim_map)
11121 goto error;
11122
11123 flags = bmap->flags;
11124 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11125 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
11126 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11127 res = isl_basic_map_alloc_space(dim,
11128 bmap->n_div, bmap->n_eq, bmap->n_ineq);
11129 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11130 if (res)
11131 res->flags = flags;
11132 res = isl_basic_map_finalize(res);
11133 return res;
11134error:
11135 free(dim_map);
11136 isl_basic_map_free(bmap);
11137 isl_space_free(dim);
11138 return NULL;
11139}
11140
11141/* Reorder the dimensions of "map" according to given reordering.
11142 */
11143__isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11144 __isl_take isl_reordering *r)
11145{
11146 int i;
11147 struct isl_dim_map *dim_map;
11148
11149 map = isl_map_cow(map);
11150 dim_map = isl_dim_map_from_reordering(r);
11151 if (!map || !r || !dim_map)
11152 goto error;
11153
11154 for (i = 0; i < map->n; ++i) {
11155 struct isl_dim_map *dim_map_i;
11156
11157 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11158
11159 map->p[i] = isl_basic_map_realign(map->p[i],
11160 isl_space_copy(r->dim), dim_map_i);
11161
11162 if (!map->p[i])
11163 goto error;
11164 }
11165
11166 map = isl_map_reset_space(map, isl_space_copy(r->dim));
11167
11168 isl_reordering_free(r);
11169 free(dim_map);
11170 return map;
11171error:
11172 free(dim_map);
11173 isl_map_free(map);
11174 isl_reordering_free(r);
11175 return NULL;
11176}
11177
11178__isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11179 __isl_take isl_reordering *r)
11180{
11181 return (isl_set *)isl_map_realign((isl_map *)set, r);
11182}
11183
11184__isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11185 __isl_take isl_space *model)
11186{
11187 isl_ctx *ctx;
11188
11189 if (!map || !model)
11190 goto error;
11191
11192 ctx = isl_space_get_ctx(model);
11193 if (!isl_space_has_named_params(model))
11194 isl_die(ctx, isl_error_invalid,
11195 "model has unnamed parameters", goto error);
11196 if (!isl_space_has_named_params(map->dim))
11197 isl_die(ctx, isl_error_invalid,
11198 "relation has unnamed parameters", goto error);
11199 if (!isl_space_match(map->dim, isl_dim_param, model, isl_dim_param)) {
11200 isl_reordering *exp;
11201
11202 model = isl_space_drop_dims(model, isl_dim_in,
11203 0, isl_space_dim(model, isl_dim_in));
11204 model = isl_space_drop_dims(model, isl_dim_out,
11205 0, isl_space_dim(model, isl_dim_out));
11206 exp = isl_parameter_alignment_reordering(map->dim, model);
11207 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11208 map = isl_map_realign(map, exp);
11209 }
11210
11211 isl_space_free(model);
11212 return map;
11213error:
11214 isl_space_free(model);
11215 isl_map_free(map);
11216 return NULL;
11217}
11218
11219__isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11220 __isl_take isl_space *model)
11221{
11222 return isl_map_align_params(set, model);
11223}
11224
11225/* Align the parameters of "bmap" to those of "model", introducing
11226 * additional parameters if needed.
11227 */
11228__isl_give isl_basic_map *isl_basic_map_align_params(
11229 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11230{
11231 isl_ctx *ctx;
11232
11233 if (!bmap || !model)
11234 goto error;
11235
11236 ctx = isl_space_get_ctx(model);
11237 if (!isl_space_has_named_params(model))
11238 isl_die(ctx, isl_error_invalid,
11239 "model has unnamed parameters", goto error);
11240 if (!isl_space_has_named_params(bmap->dim))
11241 isl_die(ctx, isl_error_invalid,
11242 "relation has unnamed parameters", goto error);
11243 if (!isl_space_match(bmap->dim, isl_dim_param, model, isl_dim_param)) {
11244 isl_reordering *exp;
11245 struct isl_dim_map *dim_map;
11246
11247 model = isl_space_drop_dims(model, isl_dim_in,
11248 0, isl_space_dim(model, isl_dim_in));
11249 model = isl_space_drop_dims(model, isl_dim_out,
11250 0, isl_space_dim(model, isl_dim_out));
11251 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11252 exp = isl_reordering_extend_space(exp,
11253 isl_basic_map_get_space(bmap));
11254 dim_map = isl_dim_map_from_reordering(exp);
11255 bmap = isl_basic_map_realign(bmap,
11256 exp ? isl_space_copy(exp->dim) : NULL,
11257 isl_dim_map_extend(dim_map, bmap));
11258 isl_reordering_free(exp);
11259 free(dim_map);
11260 }
11261
11262 isl_space_free(model);
11263 return bmap;
11264error:
11265 isl_space_free(model);
11266 isl_basic_map_free(bmap);
11267 return NULL;
11268}
11269
11270/* Align the parameters of "bset" to those of "model", introducing
11271 * additional parameters if needed.
11272 */
11273__isl_give isl_basic_set *isl_basic_set_align_params(
11274 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11275{
11276 return isl_basic_map_align_params(bset, model);
11277}
11278
11279__isl_give isl_mat *isl_basic_map_equalities_matrix(
11280 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11281 enum isl_dim_type c2, enum isl_dim_type c3,
11282 enum isl_dim_type c4, enum isl_dim_type c5)
11283{
11284 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11285 struct isl_mat *mat;
11286 int i, j, k;
11287 int pos;
11288
11289 if (!bmap)
11290 return NULL;
11291 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11292 isl_basic_map_total_dim(bmap) + 1);
11293 if (!mat)
11294 return NULL;
11295 for (i = 0; i < bmap->n_eq; ++i)
11296 for (j = 0, pos = 0; j < 5; ++j) {
11297 int off = isl_basic_map_offset(bmap, c[j]);
11298 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11299 isl_int_set(mat->row[i][pos],
11300 bmap->eq[i][off + k]);
11301 ++pos;
11302 }
11303 }
11304
11305 return mat;
11306}
11307
11308__isl_give isl_mat *isl_basic_map_inequalities_matrix(
11309 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11310 enum isl_dim_type c2, enum isl_dim_type c3,
11311 enum isl_dim_type c4, enum isl_dim_type c5)
11312{
11313 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11314 struct isl_mat *mat;
11315 int i, j, k;
11316 int pos;
11317
11318 if (!bmap)
11319 return NULL;
11320 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11321 isl_basic_map_total_dim(bmap) + 1);
11322 if (!mat)
11323 return NULL;
11324 for (i = 0; i < bmap->n_ineq; ++i)
11325 for (j = 0, pos = 0; j < 5; ++j) {
11326 int off = isl_basic_map_offset(bmap, c[j]);
11327 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11328 isl_int_set(mat->row[i][pos],
11329 bmap->ineq[i][off + k]);
11330 ++pos;
11331 }
11332 }
11333
11334 return mat;
11335}
11336
11337__isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11338 __isl_take isl_space *dim,
11339 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11340 enum isl_dim_type c2, enum isl_dim_type c3,
11341 enum isl_dim_type c4, enum isl_dim_type c5)
11342{
11343 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11344 isl_basic_map *bmap;
11345 unsigned total;
11346 unsigned extra;
11347 int i, j, k, l;
11348 int pos;
11349
11350 if (!dim || !eq || !ineq)
11351 goto error;
11352
11353 if (eq->n_col != ineq->n_col)
11354 isl_die(dim->ctx, isl_error_invalid,
11355 "equalities and inequalities matrices should have "
11356 "same number of columns", goto error);
11357
11358 total = 1 + isl_space_dim(dim, isl_dim_all);
11359
11360 if (eq->n_col < total)
11361 isl_die(dim->ctx, isl_error_invalid,
11362 "number of columns too small", goto error);
11363
11364 extra = eq->n_col - total;
11365
11366 bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
11367 eq->n_row, ineq->n_row);
11368 if (!bmap)
11369 goto error;
11370 for (i = 0; i < extra; ++i) {
11371 k = isl_basic_map_alloc_div(bmap);
11372 if (k < 0)
11373 goto error;
11374 isl_int_set_si(bmap->div[k][0], 0);
11375 }
11376 for (i = 0; i < eq->n_row; ++i) {
11377 l = isl_basic_map_alloc_equality(bmap);
11378 if (l < 0)
11379 goto error;
11380 for (j = 0, pos = 0; j < 5; ++j) {
11381 int off = isl_basic_map_offset(bmap, c[j]);
11382 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11383 isl_int_set(bmap->eq[l][off + k],
11384 eq->row[i][pos]);
11385 ++pos;
11386 }
11387 }
11388 }
11389 for (i = 0; i < ineq->n_row; ++i) {
11390 l = isl_basic_map_alloc_inequality(bmap);
11391 if (l < 0)
11392 goto error;
11393 for (j = 0, pos = 0; j < 5; ++j) {
11394 int off = isl_basic_map_offset(bmap, c[j]);
11395 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11396 isl_int_set(bmap->ineq[l][off + k],
11397 ineq->row[i][pos]);
11398 ++pos;
11399 }
11400 }
11401 }
11402
11403 isl_space_free(dim);
11404 isl_mat_free(eq);
11405 isl_mat_free(ineq);
11406
11407 bmap = isl_basic_map_simplify(bmap);
11408 return isl_basic_map_finalize(bmap);
11409error:
11410 isl_space_free(dim);
11411 isl_mat_free(eq);
11412 isl_mat_free(ineq);
11413 return NULL;
11414}
11415
11416__isl_give isl_mat *isl_basic_set_equalities_matrix(
11417 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11418 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11419{
11420 return isl_basic_map_equalities_matrix((isl_basic_map *)bset,
11421 c1, c2, c3, c4, isl_dim_in);
11422}
11423
11424__isl_give isl_mat *isl_basic_set_inequalities_matrix(
11425 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11426 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11427{
11428 return isl_basic_map_inequalities_matrix((isl_basic_map *)bset,
11429 c1, c2, c3, c4, isl_dim_in);
11430}
11431
11432__isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
11433 __isl_take isl_space *dim,
11434 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11435 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11436{
11437 return (isl_basic_set*)
11438 isl_basic_map_from_constraint_matrices(dim, eq, ineq,
11439 c1, c2, c3, c4, isl_dim_in);
11440}
11441
11442int isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
11443{
11444 if (!bmap)
11445 return -1;
11446
11447 return isl_space_can_zip(bmap->dim);
11448}
11449
11450int isl_map_can_zip(__isl_keep isl_map *map)
11451{
11452 if (!map)
11453 return -1;
11454
11455 return isl_space_can_zip(map->dim);
11456}
11457
11458/* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
11459 * (A -> C) -> (B -> D).
11460 */
11461__isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
11462{
11463 unsigned pos;
11464 unsigned n1;
11465 unsigned n2;
11466
11467 if (!bmap)
11468 return NULL;
11469
11470 if (!isl_basic_map_can_zip(bmap))
11471 isl_die(bmap->ctx, isl_error_invalid,
11472 "basic map cannot be zipped", goto error);
11473 pos = isl_basic_map_offset(bmap, isl_dim_in) +
11474 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
11475 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
11476 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
11477 bmap = isl_basic_map_cow(bmap);
11478 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
11479 if (!bmap)
11480 return NULL;
11481 bmap->dim = isl_space_zip(bmap->dim);
11482 if (!bmap->dim)
11483 goto error;
11484 return bmap;
11485error:
11486 isl_basic_map_free(bmap);
11487 return NULL;
11488}
11489
11490/* Given a map (A -> B) -> (C -> D), return the corresponding map
11491 * (A -> C) -> (B -> D).
11492 */
11493__isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
11494{
11495 int i;
11496
11497 if (!map)
11498 return NULL;
11499
11500 if (!isl_map_can_zip(map))
11501 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
11502 goto error);
11503
11504 map = isl_map_cow(map);
11505 if (!map)
11506 return NULL;
11507
11508 for (i = 0; i < map->n; ++i) {
11509 map->p[i] = isl_basic_map_zip(map->p[i]);
11510 if (!map->p[i])
11511 goto error;
11512 }
11513
11514 map->dim = isl_space_zip(map->dim);
11515 if (!map->dim)
11516 goto error;
11517
11518 return map;
11519error:
11520 isl_map_free(map);
11521 return NULL;
11522}
11523
11524/* Can we apply isl_basic_map_curry to "bmap"?
11525 * That is, does it have a nested relation in its domain?
11526 */
11527int isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
11528{
11529 if (!bmap)
11530 return -1;
11531
11532 return isl_space_can_curry(bmap->dim);
11533}
11534
11535/* Can we apply isl_map_curry to "map"?
11536 * That is, does it have a nested relation in its domain?
11537 */
11538int isl_map_can_curry(__isl_keep isl_map *map)
11539{
11540 if (!map)
11541 return -1;
11542
11543 return isl_space_can_curry(map->dim);
11544}
11545
11546/* Given a basic map (A -> B) -> C, return the corresponding basic map
11547 * A -> (B -> C).
11548 */
11549__isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
11550{
11551
11552 if (!bmap)
11553 return NULL;
11554
11555 if (!isl_basic_map_can_curry(bmap))
11556 isl_die(bmap->ctx, isl_error_invalid,
11557 "basic map cannot be curried", goto error);
11558 bmap = isl_basic_map_cow(bmap);
11559 if (!bmap)
11560 return NULL;
11561 bmap->dim = isl_space_curry(bmap->dim);
11562 if (!bmap->dim)
11563 goto error;
11564 return bmap;
11565error:
11566 isl_basic_map_free(bmap);
11567 return NULL;
11568}
11569
11570/* Given a map (A -> B) -> C, return the corresponding map
11571 * A -> (B -> C).
11572 */
11573__isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
11574{
11575 int i;
11576
11577 if (!map)
11578 return NULL;
11579
11580 if (!isl_map_can_curry(map))
11581 isl_die(map->ctx, isl_error_invalid, "map cannot be curried",
11582 goto error);
11583
11584 map = isl_map_cow(map);
11585 if (!map)
11586 return NULL;
11587
11588 for (i = 0; i < map->n; ++i) {
11589 map->p[i] = isl_basic_map_curry(map->p[i]);
11590 if (!map->p[i])
11591 goto error;
11592 }
11593
11594 map->dim = isl_space_curry(map->dim);
11595 if (!map->dim)
11596 goto error;
11597
11598 return map;
11599error:
11600 isl_map_free(map);
11601 return NULL;
11602}
11603
11604/* Can we apply isl_basic_map_uncurry to "bmap"?
11605 * That is, does it have a nested relation in its domain?
11606 */
11607int isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
11608{
11609 if (!bmap)
11610 return -1;
11611
11612 return isl_space_can_uncurry(bmap->dim);
11613}
11614
11615/* Can we apply isl_map_uncurry to "map"?
11616 * That is, does it have a nested relation in its domain?
11617 */
11618int isl_map_can_uncurry(__isl_keep isl_map *map)
11619{
11620 if (!map)
11621 return -1;
11622
11623 return isl_space_can_uncurry(map->dim);
11624}
11625
11626/* Given a basic map A -> (B -> C), return the corresponding basic map
11627 * (A -> B) -> C.
11628 */
11629__isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
11630{
11631
11632 if (!bmap)
11633 return NULL;
11634
11635 if (!isl_basic_map_can_uncurry(bmap))
11636 isl_die(bmap->ctx, isl_error_invalid,
11637 "basic map cannot be uncurried",
11638 return isl_basic_map_free(bmap));
11639 bmap = isl_basic_map_cow(bmap);
11640 if (!bmap)
11641 return NULL;
11642 bmap->dim = isl_space_uncurry(bmap->dim);
11643 if (!bmap->dim)
11644 return isl_basic_map_free(bmap);
11645 return bmap;
11646}
11647
11648/* Given a map A -> (B -> C), return the corresponding map
11649 * (A -> B) -> C.
11650 */
11651__isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
11652{
11653 int i;
11654
11655 if (!map)
11656 return NULL;
11657
11658 if (!isl_map_can_uncurry(map))
11659 isl_die(map->ctx, isl_error_invalid, "map cannot be uncurried",
11660 return isl_map_free(map));
11661
11662 map = isl_map_cow(map);
11663 if (!map)
11664 return NULL;
11665
11666 for (i = 0; i < map->n; ++i) {
11667 map->p[i] = isl_basic_map_uncurry(map->p[i]);
11668 if (!map->p[i])
11669 return isl_map_free(map);
11670 }
11671
11672 map->dim = isl_space_uncurry(map->dim);
11673 if (!map->dim)
11674 return isl_map_free(map);
11675
11676 return map;
11677}
11678
11679/* Construct a basic map mapping the domain of the affine expression
11680 * to a one-dimensional range prescribed by the affine expression.
11681 */
11682__isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff)
11683{
11684 int k;
11685 int pos;
11686 isl_local_space *ls;
11687 isl_basic_map *bmap;
11688
11689 if (!aff)
11690 return NULL;
11691
11692 ls = isl_aff_get_local_space(aff);
11693 bmap = isl_basic_map_from_local_space(ls);
11694 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
11695 k = isl_basic_map_alloc_equality(bmap);
11696 if (k < 0)
11697 goto error;
11698
11699 pos = isl_basic_map_offset(bmap, isl_dim_out);
11700 isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos);
11701 isl_int_neg(bmap->eq[k][pos], aff->v->el[0]);
11702 isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos,
11703 aff->v->size - (pos + 1));
11704
11705 isl_aff_free(aff);
11706 bmap = isl_basic_map_finalize(bmap);
11707 return bmap;
11708error:
11709 isl_aff_free(aff);
11710 isl_basic_map_free(bmap);
11711 return NULL;
11712}
11713
11714/* Construct a map mapping the domain of the affine expression
11715 * to a one-dimensional range prescribed by the affine expression.
11716 */
11717__isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff)
11718{
11719 isl_basic_map *bmap;
11720
11721 bmap = isl_basic_map_from_aff(aff);
11722 return isl_map_from_basic_map(bmap);
11723}
11724
11725/* Construct a basic map mapping the domain the multi-affine expression
11726 * to its range, with each dimension in the range equated to the
11727 * corresponding affine expression.
11728 */
11729__isl_give isl_basic_map *isl_basic_map_from_multi_aff(
11730 __isl_take isl_multi_aff *maff)
11731{
11732 int i;
11733 isl_space *space;
11734 isl_basic_map *bmap;
11735
11736 if (!maff)
11737 return NULL;
11738
11739 if (isl_space_dim(maff->space, isl_dim_out) != maff->n)
11740 isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal,
11741 "invalid space", goto error);
11742
11743 space = isl_space_domain(isl_multi_aff_get_space(maff));
11744 bmap = isl_basic_map_universe(isl_space_from_domain(space));
11745
11746 for (i = 0; i < maff->n; ++i) {
11747 isl_aff *aff;
11748 isl_basic_map *bmap_i;
11749
11750 aff = isl_aff_copy(maff->p[i]);
11751 bmap_i = isl_basic_map_from_aff(aff);
11752
11753 bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11754 }
11755
11756 bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff));
11757
11758 isl_multi_aff_free(maff);
11759 return bmap;
11760error:
11761 isl_multi_aff_free(maff);
11762 return NULL;
11763}
11764
11765/* Construct a map mapping the domain the multi-affine expression
11766 * to its range, with each dimension in the range equated to the
11767 * corresponding affine expression.
11768 */
11769__isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff)
11770{
11771 isl_basic_map *bmap;
11772
11773 bmap = isl_basic_map_from_multi_aff(maff);
11774 return isl_map_from_basic_map(bmap);
11775}
11776
11777/* Construct a basic map mapping a domain in the given space to
11778 * to an n-dimensional range, with n the number of elements in the list,
11779 * where each coordinate in the range is prescribed by the
11780 * corresponding affine expression.
11781 * The domains of all affine expressions in the list are assumed to match
11782 * domain_dim.
11783 */
11784__isl_give isl_basic_map *isl_basic_map_from_aff_list(
11785 __isl_take isl_space *domain_dim, __isl_take isl_aff_list *list)
11786{
11787 int i;
11788 isl_space *dim;
11789 isl_basic_map *bmap;
11790
11791 if (!list)
11792 return NULL;
11793
11794 dim = isl_space_from_domain(domain_dim);
11795 bmap = isl_basic_map_universe(dim);
11796
11797 for (i = 0; i < list->n; ++i) {
11798 isl_aff *aff;
11799 isl_basic_map *bmap_i;
11800
11801 aff = isl_aff_copy(list->p[i]);
11802 bmap_i = isl_basic_map_from_aff(aff);
11803
11804 bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11805 }
11806
11807 isl_aff_list_free(list);
11808 return bmap;
11809}
11810
11811__isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
11812 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11813{
11814 return isl_map_equate(set, type1, pos1, type2, pos2);
11815}
11816
11817/* Construct a basic map where the given dimensions are equal to each other.
11818 */
11819static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
11820 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11821{
11822 isl_basic_map *bmap = NULL;
11823 int i;
11824
11825 if (!space)
11826 return NULL;
11827
11828 if (pos1 >= isl_space_dim(space, type1))
11829 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11830 "index out of bounds", goto error);
11831 if (pos2 >= isl_space_dim(space, type2))
11832 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11833 "index out of bounds", goto error);
11834
11835 if (type1 == type2 && pos1 == pos2)
11836 return isl_basic_map_universe(space);
11837
11838 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
11839 i = isl_basic_map_alloc_equality(bmap);
11840 if (i < 0)
11841 goto error;
11842 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11843 pos1 += isl_basic_map_offset(bmap, type1);
11844 pos2 += isl_basic_map_offset(bmap, type2);
11845 isl_int_set_si(bmap->eq[i][pos1], -1);
11846 isl_int_set_si(bmap->eq[i][pos2], 1);
11847 bmap = isl_basic_map_finalize(bmap);
11848 isl_space_free(space);
11849 return bmap;
11850error:
11851 isl_space_free(space);
11852 isl_basic_map_free(bmap);
11853 return NULL;
11854}
11855
11856/* Add a constraint imposing that the given two dimensions are equal.
11857 */
11858__isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
11859 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11860{
11861 isl_basic_map *eq;
11862
11863 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
11864
11865 bmap = isl_basic_map_intersect(bmap, eq);
11866
11867 return bmap;
11868}
11869
11870/* Add a constraint imposing that the given two dimensions are equal.
11871 */
11872__isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
11873 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11874{
11875 isl_basic_map *bmap;
11876
11877 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
11878
11879 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11880
11881 return map;
11882}
11883
11884/* Add a constraint imposing that the given two dimensions have opposite values.
11885 */
11886__isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
11887 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11888{
11889 isl_basic_map *bmap = NULL;
11890 int i;
11891
11892 if (!map)
11893 return NULL;
11894
11895 if (pos1 >= isl_map_dim(map, type1))
11896 isl_die(map->ctx, isl_error_invalid,
11897 "index out of bounds", goto error);
11898 if (pos2 >= isl_map_dim(map, type2))
11899 isl_die(map->ctx, isl_error_invalid,
11900 "index out of bounds", goto error);
11901
11902 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
11903 i = isl_basic_map_alloc_equality(bmap);
11904 if (i < 0)
11905 goto error;
11906 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11907 pos1 += isl_basic_map_offset(bmap, type1);
11908 pos2 += isl_basic_map_offset(bmap, type2);
11909 isl_int_set_si(bmap->eq[i][pos1], 1);
11910 isl_int_set_si(bmap->eq[i][pos2], 1);
11911 bmap = isl_basic_map_finalize(bmap);
11912
11913 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11914
11915 return map;
11916error:
11917 isl_basic_map_free(bmap);
11918 isl_map_free(map);
11919 return NULL;
11920}
11921
11922/* Construct a constraint imposing that the value of the first dimension is
11923 * greater than or equal to that of the second.
11924 */
11925static __isl_give isl_constraint *constraint_order_ge(
11926 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
11927 enum isl_dim_type type2, int pos2)
11928{
11929 isl_constraint *c;
11930
11931 if (!space)
11932 return NULL;
11933
11934 c = isl_inequality_alloc(isl_local_space_from_space(space));
11935
11936 if (pos1 >= isl_constraint_dim(c, type1))
11937 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
11938 "index out of bounds", return isl_constraint_free(c));
11939 if (pos2 >= isl_constraint_dim(c, type2))
11940 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
11941 "index out of bounds", return isl_constraint_free(c));
11942
11943 if (type1 == type2 && pos1 == pos2)
11944 return c;
11945
11946 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
11947 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
11948
11949 return c;
11950}
11951
11952/* Add a constraint imposing that the value of the first dimension is
11953 * greater than or equal to that of the second.
11954 */
11955__isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
11956 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11957{
11958 isl_constraint *c;
11959 isl_space *space;
11960
11961 if (type1 == type2 && pos1 == pos2)
11962 return bmap;
11963 space = isl_basic_map_get_space(bmap);
11964 c = constraint_order_ge(space, type1, pos1, type2, pos2);
11965 bmap = isl_basic_map_add_constraint(bmap, c);
11966
11967 return bmap;
11968}
11969
11970/* Add a constraint imposing that the value of the first dimension is
11971 * greater than or equal to that of the second.
11972 */
11973__isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
11974 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11975{
11976 isl_constraint *c;
11977 isl_space *space;
11978
11979 if (type1 == type2 && pos1 == pos2)
11980 return map;
11981 space = isl_map_get_space(map);
11982 c = constraint_order_ge(space, type1, pos1, type2, pos2);
11983 map = isl_map_add_constraint(map, c);
11984
11985 return map;
11986}
11987
11988/* Add a constraint imposing that the value of the first dimension is
11989 * less than or equal to that of the second.
11990 */
11991__isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
11992 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11993{
11994 return isl_map_order_ge(map, type2, pos2, type1, pos1);
11995}
11996
11997/* Construct a basic map where the value of the first dimension is
11998 * greater than that of the second.
11999 */
12000static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12001 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12002{
12003 isl_basic_map *bmap = NULL;
12004 int i;
12005
12006 if (!space)
12007 return NULL;
12008
12009 if (pos1 >= isl_space_dim(space, type1))
12010 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12011 "index out of bounds", goto error);
12012 if (pos2 >= isl_space_dim(space, type2))
12013 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12014 "index out of bounds", goto error);
12015
12016 if (type1 == type2 && pos1 == pos2)
12017 return isl_basic_map_empty(space);
12018
12019 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12020 i = isl_basic_map_alloc_inequality(bmap);
12021 if (i < 0)
12022 return isl_basic_map_free(bmap);
12023 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12024 pos1 += isl_basic_map_offset(bmap, type1);
12025 pos2 += isl_basic_map_offset(bmap, type2);
12026 isl_int_set_si(bmap->ineq[i][pos1], 1);
12027 isl_int_set_si(bmap->ineq[i][pos2], -1);
12028 isl_int_set_si(bmap->ineq[i][0], -1);
12029 bmap = isl_basic_map_finalize(bmap);
12030
12031 return bmap;
12032error:
12033 isl_space_free(space);
12034 isl_basic_map_free(bmap);
12035 return NULL;
12036}
12037
12038/* Add a constraint imposing that the value of the first dimension is
12039 * greater than that of the second.
12040 */
12041__isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12042 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12043{
12044 isl_basic_map *gt;
12045
12046 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12047
12048 bmap = isl_basic_map_intersect(bmap, gt);
12049
12050 return bmap;
12051}
12052
12053/* Add a constraint imposing that the value of the first dimension is
12054 * greater than that of the second.
12055 */
12056__isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12057 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12058{
12059 isl_basic_map *bmap;
12060
12061 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12062
12063 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12064
12065 return map;
12066}
12067
12068/* Add a constraint imposing that the value of the first dimension is
12069 * smaller than that of the second.
12070 */
12071__isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12072 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12073{
12074 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12075}
12076
12077__isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12078 int pos)
12079{
12080 isl_aff *div;
12081 isl_local_space *ls;
12082
12083 if (!bmap)
12084 return NULL;
12085
12086 if (!isl_basic_map_divs_known(bmap))
12087 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12088 "some divs are unknown", return NULL);
12089
12090 ls = isl_basic_map_get_local_space(bmap);
12091 div = isl_local_space_get_div(ls, pos);
12092 isl_local_space_free(ls);
12093
12094 return div;
12095}
12096
12097__isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12098 int pos)
12099{
12100 return isl_basic_map_get_div(bset, pos);
12101}
12102
12103/* Plug in "subs" for dimension "type", "pos" of "bset".
12104 *
12105 * Let i be the dimension to replace and let "subs" be of the form
12106 *
12107 * f/d
12108 *
12109 * Any integer division with a non-zero coefficient for i,
12110 *
12111 * floor((a i + g)/m)
12112 *
12113 * is replaced by
12114 *
12115 * floor((a f + d g)/(m d))
12116 *
12117 * Constraints of the form
12118 *
12119 * a i + g
12120 *
12121 * are replaced by
12122 *
12123 * a f + d g
12124 *
12125 * We currently require that "subs" is an integral expression.
12126 * Handling rational expressions may require us to add stride constraints
12127 * as we do in isl_basic_set_preimage_multi_aff.
12128 */
12129__isl_give isl_basic_set *isl_basic_set_substitute(
12130 __isl_take isl_basic_set *bset,
12131 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12132{
12133 int i;
12134 isl_int v;
12135 isl_ctx *ctx;
12136
12137 if (bset && isl_basic_set_plain_is_empty(bset))
12138 return bset;
12139
12140 bset = isl_basic_set_cow(bset);
12141 if (!bset || !subs)
12142 goto error;
12143
12144 ctx = isl_basic_set_get_ctx(bset);
12145 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12146 isl_die(ctx, isl_error_invalid,
12147 "spaces don't match", goto error);
12148 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12149 isl_die(ctx, isl_error_unsupported,
12150 "cannot handle divs yet", goto error);
12151 if (!isl_int_is_one(subs->v->el[0]))
12152 isl_die(ctx, isl_error_invalid,
12153 "can only substitute integer expressions", goto error);
12154
12155 pos += isl_basic_set_offset(bset, type);
12156
12157 isl_int_init(v);
12158
12159 for (i = 0; i < bset->n_eq; ++i) {
12160 if (isl_int_is_zero(bset->eq[i][pos]))
12161 continue;
12162 isl_int_set(v, bset->eq[i][pos]);
12163 isl_int_set_si(bset->eq[i][pos], 0);
12164 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12165 v, subs->v->el + 1, subs->v->size - 1);
12166 }
12167
12168 for (i = 0; i < bset->n_ineq; ++i) {
12169 if (isl_int_is_zero(bset->ineq[i][pos]))
12170 continue;
12171 isl_int_set(v, bset->ineq[i][pos]);
12172 isl_int_set_si(bset->ineq[i][pos], 0);
12173 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12174 v, subs->v->el + 1, subs->v->size - 1);
12175 }
12176
12177 for (i = 0; i < bset->n_div; ++i) {
12178 if (isl_int_is_zero(bset->div[i][1 + pos]))
12179 continue;
12180 isl_int_set(v, bset->div[i][1 + pos]);
12181 isl_int_set_si(bset->div[i][1 + pos], 0);
12182 isl_seq_combine(bset->div[i] + 1,
12183 subs->v->el[0], bset->div[i] + 1,
12184 v, subs->v->el + 1, subs->v->size - 1);
12185 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12186 }
12187
12188 isl_int_clear(v);
12189
12190 bset = isl_basic_set_simplify(bset);
12191 return isl_basic_set_finalize(bset);
12192error:
12193 isl_basic_set_free(bset);
12194 return NULL;
12195}
12196
12197/* Plug in "subs" for dimension "type", "pos" of "set".
12198 */
12199__isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12200 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12201{
12202 int i;
12203
12204 if (set && isl_set_plain_is_empty(set))
12205 return set;
12206
12207 set = isl_set_cow(set);
12208 if (!set || !subs)
12209 goto error;
12210
12211 for (i = set->n - 1; i >= 0; --i) {
12212 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12213 if (remove_if_empty(set, i) < 0)
12214 goto error;
12215 }
12216
12217 return set;
12218error:
12219 isl_set_free(set);
12220 return NULL;
12221}
12222
12223/* Check if the range of "ma" is compatible with the domain or range
12224 * (depending on "type") of "bmap".
12225 * Return -1 if anything is wrong.
12226 */
12227static int check_basic_map_compatible_range_multi_aff(
12228 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12229 __isl_keep isl_multi_aff *ma)
12230{
12231 int m;
12232 isl_space *ma_space;
12233
12234 ma_space = isl_multi_aff_get_space(ma);
12235
12236 m = isl_space_match(bmap->dim, isl_dim_param, ma_space, isl_dim_param);
12237 if (m < 0)
12238 goto error;
12239 if (!m)
12240 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12241 "parameters don't match", goto error);
12242 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12243 if (m < 0)
12244 goto error;
12245 if (!m)
12246 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12247 "spaces don't match", goto error);
12248
12249 isl_space_free(ma_space);
12250 return m;
12251error:
12252 isl_space_free(ma_space);
12253 return -1;
12254}
12255
12256/* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12257 * coefficients before the transformed range of dimensions,
12258 * the "n_after" coefficients after the transformed range of dimensions
12259 * and the coefficients of the other divs in "bmap".
12260 */
12261static int set_ma_divs(__isl_keep isl_basic_map *bmap,
12262 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12263{
12264 int i;
12265 int n_param;
12266 int n_set;
12267 isl_local_space *ls;
12268
12269 if (n_div == 0)
12270 return 0;
12271
12272 ls = isl_aff_get_domain_local_space(ma->p[0]);
12273 if (!ls)
12274 return -1;
12275
12276 n_param = isl_local_space_dim(ls, isl_dim_param);
12277 n_set = isl_local_space_dim(ls, isl_dim_set);
12278 for (i = 0; i < n_div; ++i) {
12279 int o_bmap = 0, o_ls = 0;
12280
12281 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12282 o_bmap += 1 + 1 + n_param;
12283 o_ls += 1 + 1 + n_param;
12284 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12285 o_bmap += n_before;
12286 isl_seq_cpy(bmap->div[i] + o_bmap,
12287 ls->div->row[i] + o_ls, n_set);
12288 o_bmap += n_set;
12289 o_ls += n_set;
12290 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12291 o_bmap += n_after;
12292 isl_seq_cpy(bmap->div[i] + o_bmap,
12293 ls->div->row[i] + o_ls, n_div);
12294 o_bmap += n_div;
12295 o_ls += n_div;
12296 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12297 if (isl_basic_set_add_div_constraints(bmap, i) < 0)
12298 goto error;
12299 }
12300
12301 isl_local_space_free(ls);
12302 return 0;
12303error:
12304 isl_local_space_free(ls);
12305 return -1;
12306}
12307
12308/* How many stride constraints does "ma" enforce?
12309 * That is, how many of the affine expressions have a denominator
12310 * different from one?
12311 */
12312static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12313{
12314 int i;
12315 int strides = 0;
12316
12317 for (i = 0; i < ma->n; ++i)
12318 if (!isl_int_is_one(ma->p[i]->v->el[0]))
12319 strides++;
12320
12321 return strides;
12322}
12323
12324/* For each affine expression in ma of the form
12325 *
12326 * x_i = (f_i y + h_i)/m_i
12327 *
12328 * with m_i different from one, add a constraint to "bmap"
12329 * of the form
12330 *
12331 * f_i y + h_i = m_i alpha_i
12332 *
12333 * with alpha_i an additional existentially quantified variable.
12334 */
12335static __isl_give isl_basic_map *add_ma_strides(
12336 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12337 int n_before, int n_after)
12338{
12339 int i, k;
12340 int div;
12341 int total;
12342 int n_param;
12343 int n_in;
12344 int n_div;
12345
12346 total = isl_basic_map_total_dim(bmap);
12347 n_param = isl_multi_aff_dim(ma, isl_dim_param);
12348 n_in = isl_multi_aff_dim(ma, isl_dim_in);
12349 n_div = isl_multi_aff_dim(ma, isl_dim_div);
12350 for (i = 0; i < ma->n; ++i) {
12351 int o_bmap = 0, o_ma = 1;
12352
12353 if (isl_int_is_one(ma->p[i]->v->el[0]))
12354 continue;
12355 div = isl_basic_map_alloc_div(bmap);
12356 k = isl_basic_map_alloc_equality(bmap);
12357 if (div < 0 || k < 0)
12358 goto error;
12359 isl_int_set_si(bmap->div[div][0], 0);
12360 isl_seq_cpy(bmap->eq[k] + o_bmap,
12361 ma->p[i]->v->el + o_ma, 1 + n_param);
12362 o_bmap += 1 + n_param;
12363 o_ma += 1 + n_param;
12364 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12365 o_bmap += n_before;
12366 isl_seq_cpy(bmap->eq[k] + o_bmap,
12367 ma->p[i]->v->el + o_ma, n_in);
12368 o_bmap += n_in;
12369 o_ma += n_in;
12370 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12371 o_bmap += n_after;
12372 isl_seq_cpy(bmap->eq[k] + o_bmap,
12373 ma->p[i]->v->el + o_ma, n_div);
12374 o_bmap += n_div;
12375 o_ma += n_div;
12376 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12377 isl_int_neg(bmap->eq[k][1 + total], ma->p[i]->v->el[0]);
12378 total++;
12379 }
12380
12381 return bmap;
12382error:
12383 isl_basic_map_free(bmap);
12384 return NULL;
12385}
12386
12387/* Replace the domain or range space (depending on "type) of "space" by "set".
12388 */
12389static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12390 enum isl_dim_type type, __isl_take isl_space *set)
12391{
12392 if (type == isl_dim_in) {
12393 space = isl_space_range(space);
12394 space = isl_space_map_from_domain_and_range(set, space);
12395 } else {
12396 space = isl_space_domain(space);
12397 space = isl_space_map_from_domain_and_range(space, set);
12398 }
12399
12400 return space;
12401}
12402
12403/* Compute the preimage of the domain or range (depending on "type")
12404 * of "bmap" under the function represented by "ma".
12405 * In other words, plug in "ma" in the domain or range of "bmap".
12406 * The result is a basic map that lives in the same space as "bmap"
12407 * except that the domain or range has been replaced by
12408 * the domain space of "ma".
12409 *
12410 * If bmap is represented by
12411 *
12412 * A(p) + S u + B x + T v + C(divs) >= 0,
12413 *
12414 * where u and x are input and output dimensions if type == isl_dim_out
12415 * while x and v are input and output dimensions if type == isl_dim_in,
12416 * and ma is represented by
12417 *
12418 * x = D(p) + F(y) + G(divs')
12419 *
12420 * then the result is
12421 *
12422 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12423 *
12424 * The divs in the input set are similarly adjusted.
12425 * In particular
12426 *
12427 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12428 *
12429 * becomes
12430 *
12431 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12432 * B_i G(divs') + c_i(divs))/n_i)
12433 *
12434 * If bmap is not a rational map and if F(y) involves any denominators
12435 *
12436 * x_i = (f_i y + h_i)/m_i
12437 *
12438 * then additional constraints are added to ensure that we only
12439 * map back integer points. That is we enforce
12440 *
12441 * f_i y + h_i = m_i alpha_i
12442 *
12443 * with alpha_i an additional existentially quantified variable.
12444 *
12445 * We first copy over the divs from "ma".
12446 * Then we add the modified constraints and divs from "bmap".
12447 * Finally, we add the stride constraints, if needed.
12448 */
12449__isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12450 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12451 __isl_take isl_multi_aff *ma)
12452{
12453 int i, k;
12454 isl_space *space;
12455 isl_basic_map *res = NULL;
12456 int n_before, n_after, n_div_bmap, n_div_ma;
12457 isl_int f, c1, c2, g;
12458 int rational, strides;
12459
12460 isl_int_init(f);
12461 isl_int_init(c1);
12462 isl_int_init(c2);
12463 isl_int_init(g);
12464
12465 ma = isl_multi_aff_align_divs(ma);
12466 if (!bmap || !ma)
12467 goto error;
12468 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12469 goto error;
12470
12471 if (type == isl_dim_in) {
12472 n_before = 0;
12473 n_after = isl_basic_map_dim(bmap, isl_dim_out);
12474 } else {
12475 n_before = isl_basic_map_dim(bmap, isl_dim_in);
12476 n_after = 0;
12477 }
12478 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12479 n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
12480
12481 space = isl_multi_aff_get_domain_space(ma);
12482 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12483 rational = isl_basic_map_is_rational(bmap);
12484 strides = rational ? 0 : multi_aff_strides(ma);
12485 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12486 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12487 if (rational)
12488 res = isl_basic_map_set_rational(res);
12489
12490 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12491 if (isl_basic_map_alloc_div(res) < 0)
12492 goto error;
12493
12494 if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
12495 goto error;
12496
12497 for (i = 0; i < bmap->n_eq; ++i) {
12498 k = isl_basic_map_alloc_equality(res);
12499 if (k < 0)
12500 goto error;
12501 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
12502 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12503 }
12504
12505 for (i = 0; i < bmap->n_ineq; ++i) {
12506 k = isl_basic_map_alloc_inequality(res);
12507 if (k < 0)
12508 goto error;
12509 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
12510 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12511 }
12512
12513 for (i = 0; i < bmap->n_div; ++i) {
12514 if (isl_int_is_zero(bmap->div[i][0])) {
12515 isl_int_set_si(res->div[n_div_ma + i][0], 0);
12516 continue;
12517 }
12518 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
12519 n_before, n_after, n_div_ma, n_div_bmap,
12520 f, c1, c2, g, 1);
12521 }
12522
12523 if (strides)
12524 res = add_ma_strides(res, ma, n_before, n_after);
12525
12526 isl_int_clear(f);
12527 isl_int_clear(c1);
12528 isl_int_clear(c2);
12529 isl_int_clear(g);
12530 isl_basic_map_free(bmap);
12531 isl_multi_aff_free(ma);
12532 res = isl_basic_set_simplify(res);
12533 return isl_basic_map_finalize(res);
12534error:
12535 isl_int_clear(f);
12536 isl_int_clear(c1);
12537 isl_int_clear(c2);
12538 isl_int_clear(g);
12539 isl_basic_map_free(bmap);
12540 isl_multi_aff_free(ma);
12541 isl_basic_map_free(res);
12542 return NULL;
12543}
12544
12545/* Compute the preimage of "bset" under the function represented by "ma".
12546 * In other words, plug in "ma" in "bset". The result is a basic set
12547 * that lives in the domain space of "ma".
12548 */
12549__isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
12550 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
12551{
12552 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
12553}
12554
12555/* Compute the preimage of the domain of "bmap" under the function
12556 * represented by "ma".
12557 * In other words, plug in "ma" in the domain of "bmap".
12558 * The result is a basic map that lives in the same space as "bmap"
12559 * except that the domain has been replaced by the domain space of "ma".
12560 */
12561__isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
12562 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12563{
12564 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
12565}
12566
12567/* Compute the preimage of the range of "bmap" under the function
12568 * represented by "ma".
12569 * In other words, plug in "ma" in the range of "bmap".
12570 * The result is a basic map that lives in the same space as "bmap"
12571 * except that the range has been replaced by the domain space of "ma".
12572 */
12573__isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
12574 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12575{
12576 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
12577}
12578
12579/* Check if the range of "ma" is compatible with the domain or range
12580 * (depending on "type") of "map".
12581 * Return -1 if anything is wrong.
12582 */
12583static int check_map_compatible_range_multi_aff(
12584 __isl_keep isl_map *map, enum isl_dim_type type,
12585 __isl_keep isl_multi_aff *ma)
12586{
12587 int m;
12588 isl_space *ma_space;
12589
12590 ma_space = isl_multi_aff_get_space(ma);
12591 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
12592 isl_space_free(ma_space);
12593 if (m >= 0 && !m)
12594 isl_die(isl_map_get_ctx(map), isl_error_invalid,
12595 "spaces don't match", return -1);
12596 return m;
12597}
12598
12599/* Compute the preimage of the domain or range (depending on "type")
12600 * of "map" under the function represented by "ma".
12601 * In other words, plug in "ma" in the domain or range of "map".
12602 * The result is a map that lives in the same space as "map"
12603 * except that the domain or range has been replaced by
12604 * the domain space of "ma".
12605 *
12606 * The parameters are assumed to have been aligned.
12607 */
12608static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
12609 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12610{
12611 int i;
12612 isl_space *space;
12613
12614 map = isl_map_cow(map);
12615 ma = isl_multi_aff_align_divs(ma);
12616 if (!map || !ma)
12617 goto error;
12618 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
12619 goto error;
12620
12621 for (i = 0; i < map->n; ++i) {
12622 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
12623 isl_multi_aff_copy(ma));
12624 if (!map->p[i])
12625 goto error;
12626 }
12627
12628 space = isl_multi_aff_get_domain_space(ma);
12629 space = isl_space_set(isl_map_get_space(map), type, space);
12630
12631 isl_space_free(map->dim);
12632 map->dim = space;
12633 if (!map->dim)
12634 goto error;
12635
12636 isl_multi_aff_free(ma);
12637 if (map->n > 1)
12638 ISL_F_CLR(map, ISL_MAP_DISJOINT);
12639 ISL_F_CLR(map, ISL_SET_NORMALIZED);
12640 return map;
12641error:
12642 isl_multi_aff_free(ma);
12643 isl_map_free(map);
12644 return NULL;
12645}
12646
12647/* Compute the preimage of the domain or range (depending on "type")
12648 * of "map" under the function represented by "ma".
12649 * In other words, plug in "ma" in the domain or range of "map".
12650 * The result is a map that lives in the same space as "map"
12651 * except that the domain or range has been replaced by
12652 * the domain space of "ma".
12653 */
12654__isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
12655 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12656{
12657 if (!map || !ma)
12658 goto error;
12659
12660 if (isl_space_match(map->dim, isl_dim_param, ma->space, isl_dim_param))
12661 return map_preimage_multi_aff(map, type, ma);
12662
12663 if (!isl_space_has_named_params(map->dim) ||
12664 !isl_space_has_named_params(ma->space))
12665 isl_die(map->ctx, isl_error_invalid,
12666 "unaligned unnamed parameters", goto error);
12667 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
12668 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
12669
12670 return map_preimage_multi_aff(map, type, ma);
12671error:
12672 isl_multi_aff_free(ma);
12673 return isl_map_free(map);
12674}
12675
12676/* Compute the preimage of "set" under the function represented by "ma".
12677 * In other words, plug in "ma" in "set". The result is a set
12678 * that lives in the domain space of "ma".
12679 */
12680__isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
12681 __isl_take isl_multi_aff *ma)
12682{
12683 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
12684}
12685
12686/* Compute the preimage of the domain of "map" under the function
12687 * represented by "ma".
12688 * In other words, plug in "ma" in the domain of "map".
12689 * The result is a map that lives in the same space as "map"
12690 * except that the domain has been replaced by the domain space of "ma".
12691 */
12692__isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
12693 __isl_take isl_multi_aff *ma)
12694{
12695 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
12696}
12697
12698/* Compute the preimage of the range of "map" under the function
12699 * represented by "ma".
12700 * In other words, plug in "ma" in the range of "map".
12701 * The result is a map that lives in the same space as "map"
12702 * except that the range has been replaced by the domain space of "ma".
12703 */
12704__isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
12705 __isl_take isl_multi_aff *ma)
12706{
12707 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
12708}
12709
12710/* Compute the preimage of "map" under the function represented by "pma".
12711 * In other words, plug in "pma" in the domain or range of "map".
12712 * The result is a map that lives in the same space as "map",
12713 * except that the space of type "type" has been replaced by
12714 * the domain space of "pma".
12715 *
12716 * The parameters of "map" and "pma" are assumed to have been aligned.
12717 */
12718static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
12719 __isl_take isl_map *map, enum isl_dim_type type,
12720 __isl_take isl_pw_multi_aff *pma)
12721{
12722 int i;
12723 isl_map *res;
12724
12725 if (!pma)
12726 goto error;
12727
12728 if (pma->n == 0) {
12729 isl_pw_multi_aff_free(pma);
12730 res = isl_map_empty(isl_map_get_space(map));
12731 isl_map_free(map);
12732 return res;
12733 }
12734
12735 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
12736 isl_multi_aff_copy(pma->p[0].maff));
12737 if (type == isl_dim_in)
12738 res = isl_map_intersect_domain(res,
12739 isl_map_copy(pma->p[0].set));
12740 else
12741 res = isl_map_intersect_range(res,
12742 isl_map_copy(pma->p[0].set));
12743
12744 for (i = 1; i < pma->n; ++i) {
12745 isl_map *res_i;
12746
12747 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
12748 isl_multi_aff_copy(pma->p[i].maff));
12749 if (type == isl_dim_in)
12750 res_i = isl_map_intersect_domain(res_i,
12751 isl_map_copy(pma->p[i].set));
12752 else
12753 res_i = isl_map_intersect_range(res_i,
12754 isl_map_copy(pma->p[i].set));
12755 res = isl_map_union(res, res_i);
12756 }
12757
12758 isl_pw_multi_aff_free(pma);
12759 isl_map_free(map);
12760 return res;
12761error:
12762 isl_pw_multi_aff_free(pma);
12763 isl_map_free(map);
12764 return NULL;
12765}
12766
12767/* Compute the preimage of "map" under the function represented by "pma".
12768 * In other words, plug in "pma" in the domain or range of "map".
12769 * The result is a map that lives in the same space as "map",
12770 * except that the space of type "type" has been replaced by
12771 * the domain space of "pma".
12772 */
12773__isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
12774 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
12775{
12776 if (!map || !pma)
12777 goto error;
12778
12779 if (isl_space_match(map->dim, isl_dim_param, pma->dim, isl_dim_param))
12780 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
12781
12782 if (!isl_space_has_named_params(map->dim) ||
12783 !isl_space_has_named_params(pma->dim))
12784 isl_die(map->ctx, isl_error_invalid,
12785 "unaligned unnamed parameters", goto error);
12786 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
12787 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
12788
12789 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
12790error:
12791 isl_pw_multi_aff_free(pma);
12792 return isl_map_free(map);
12793}
12794
12795/* Compute the preimage of "set" under the function represented by "pma".
12796 * In other words, plug in "pma" in "set". The result is a set
12797 * that lives in the domain space of "pma".
12798 */
12799__isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
12800 __isl_take isl_pw_multi_aff *pma)
12801{
12802 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
12803}
12804
12805/* Compute the preimage of the domain of "map" under the function
12806 * represented by "pma".
12807 * In other words, plug in "pma" in the domain of "map".
12808 * The result is a map that lives in the same space as "map",
12809 * except that domain space has been replaced by the domain space of "pma".
12810 */
12811__isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
12812 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
12813{
12814 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
12815}
12816
12817/* Compute the preimage of the range of "map" under the function
12818 * represented by "pma".
12819 * In other words, plug in "pma" in the range of "map".
12820 * The result is a map that lives in the same space as "map",
12821 * except that range space has been replaced by the domain space of "pma".
12822 */
12823__isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
12824 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
12825{
12826 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
12827}
12828
12829/* Compute the preimage of "map" under the function represented by "mpa".
12830 * In other words, plug in "mpa" in the domain or range of "map".
12831 * The result is a map that lives in the same space as "map",
12832 * except that the space of type "type" has been replaced by
12833 * the domain space of "mpa".
12834 *
12835 * If the map does not involve any constraints that refer to the
12836 * dimensions of the substituted space, then the only possible
12837 * effect of "mpa" on the map is to map the space to a different space.
12838 * We create a separate isl_multi_aff to effectuate this change
12839 * in order to avoid spurious splitting of the map along the pieces
12840 * of "mpa".
12841 */
12842__isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
12843 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
12844{
12845 int n;
12846 isl_pw_multi_aff *pma;
12847
12848 if (!map || !mpa)
12849 goto error;
12850
12851 n = isl_map_dim(map, type);
12852 if (!isl_map_involves_dims(map, type, 0, n)) {
12853 isl_space *space;
12854 isl_multi_aff *ma;
12855
12856 space = isl_multi_pw_aff_get_space(mpa);
12857 isl_multi_pw_aff_free(mpa);
12858 ma = isl_multi_aff_zero(space);
12859 return isl_map_preimage_multi_aff(map, type, ma);
12860 }
12861
12862 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
12863 return isl_map_preimage_pw_multi_aff(map, type, pma);
12864error:
12865 isl_map_free(map);
12866 isl_multi_pw_aff_free(mpa);
12867 return NULL;
12868}
12869
12870/* Compute the preimage of "map" under the function represented by "mpa".
12871 * In other words, plug in "mpa" in the domain "map".
12872 * The result is a map that lives in the same space as "map",
12873 * except that domain space has been replaced by the domain space of "mpa".
12874 */
12875__isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
12876 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
12877{
12878 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
12879}
12880
12881/* Compute the preimage of "set" by the function represented by "mpa".
12882 * In other words, plug in "mpa" in "set".
12883 */
12884__isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
12885 __isl_take isl_multi_pw_aff *mpa)
12886{
12887 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
12888}