1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2010      INRIA Saclay
4  * Copyright 2012-2014 Ecole Normale Superieure
5  * Copyright 2014      INRIA Rocquencourt
6  * Copyright 2016      INRIA Paris
7  * Copyright 2016      Sven Verdoolaege
8  *
9  * Use of this software is governed by the MIT license
10  *
11  * Written by Sven Verdoolaege, K.U.Leuven, Departement
12  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
13  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
14  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
15  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
16  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
17  * B.P. 105 - 78153 Le Chesnay, France
18  * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
19  * CS 42112, 75589 Paris Cedex 12, France
20  */
21 
22 #include <string.h>
23 #include <isl_ctx_private.h>
24 #include <isl_map_private.h>
25 #include <isl_blk.h>
26 #include <isl/id.h>
27 #include <isl/constraint.h>
28 #include "isl_space_private.h"
29 #include "isl_equalities.h"
30 #include <isl_lp_private.h>
31 #include <isl_seq.h>
32 #include <isl/set.h>
33 #include <isl/map.h>
34 #include <isl_reordering.h>
35 #include "isl_sample.h"
36 #include <isl_sort.h>
37 #include "isl_tab.h"
38 #include <isl/vec.h>
39 #include <isl_mat_private.h>
40 #include <isl_vec_private.h>
41 #include <isl_dim_map.h>
42 #include <isl_local_space_private.h>
43 #include <isl_aff_private.h>
44 #include <isl_options_private.h>
45 #include <isl_morph.h>
46 #include <isl_val_private.h>
47 
48 #include <bset_to_bmap.c>
49 #include <bset_from_bmap.c>
50 #include <set_to_map.c>
51 #include <set_from_map.c>
52 
n(__isl_keep isl_space * dim,enum isl_dim_type type)53 static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
54 {
55 	switch (type) {
56 	case isl_dim_param:	return dim->nparam;
57 	case isl_dim_in:	return dim->n_in;
58 	case isl_dim_out:	return dim->n_out;
59 	case isl_dim_all:	return dim->nparam + dim->n_in + dim->n_out;
60 	default:		return 0;
61 	}
62 }
63 
pos(__isl_keep isl_space * dim,enum isl_dim_type type)64 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
65 {
66 	switch (type) {
67 	case isl_dim_param:	return 1;
68 	case isl_dim_in:	return 1 + dim->nparam;
69 	case isl_dim_out:	return 1 + dim->nparam + dim->n_in;
70 	default:		return 0;
71 	}
72 }
73 
isl_basic_map_dim(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)74 unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
75 				enum isl_dim_type type)
76 {
77 	if (!bmap)
78 		return 0;
79 	switch (type) {
80 	case isl_dim_cst:	return 1;
81 	case isl_dim_param:
82 	case isl_dim_in:
83 	case isl_dim_out:	return isl_space_dim(bmap->dim, type);
84 	case isl_dim_div:	return bmap->n_div;
85 	case isl_dim_all:	return isl_basic_map_total_dim(bmap);
86 	default:		return 0;
87 	}
88 }
89 
90 /* Return the space of "map".
91  */
isl_map_peek_space(__isl_keep const isl_map * map)92 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
93 {
94 	return map ? map->dim : NULL;
95 }
96 
isl_map_dim(__isl_keep isl_map * map,enum isl_dim_type type)97 unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
98 {
99 	return map ? n(map->dim, type) : 0;
100 }
101 
isl_set_dim(__isl_keep isl_set * set,enum isl_dim_type type)102 unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
103 {
104 	return set ? n(set->dim, type) : 0;
105 }
106 
isl_basic_map_offset(struct isl_basic_map * bmap,enum isl_dim_type type)107 unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
108 					enum isl_dim_type type)
109 {
110 	isl_space *space;
111 
112 	if (!bmap)
113 		return 0;
114 
115 	space = bmap->dim;
116 	switch (type) {
117 	case isl_dim_cst:	return 0;
118 	case isl_dim_param:	return 1;
119 	case isl_dim_in:	return 1 + space->nparam;
120 	case isl_dim_out:	return 1 + space->nparam + space->n_in;
121 	case isl_dim_div:	return 1 + space->nparam + space->n_in +
122 								space->n_out;
123 	default:		return 0;
124 	}
125 }
126 
isl_basic_set_offset(__isl_keep isl_basic_set * bset,enum isl_dim_type type)127 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
128 					enum isl_dim_type type)
129 {
130 	return isl_basic_map_offset(bset, type);
131 }
132 
map_offset(__isl_keep isl_map * map,enum isl_dim_type type)133 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
134 {
135 	return pos(map->dim, type);
136 }
137 
isl_basic_set_dim(__isl_keep isl_basic_set * bset,enum isl_dim_type type)138 unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
139 				enum isl_dim_type type)
140 {
141 	return isl_basic_map_dim(bset, type);
142 }
143 
isl_basic_set_n_dim(__isl_keep isl_basic_set * bset)144 unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
145 {
146 	return isl_basic_set_dim(bset, isl_dim_set);
147 }
148 
isl_basic_set_n_param(__isl_keep isl_basic_set * bset)149 unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
150 {
151 	return isl_basic_set_dim(bset, isl_dim_param);
152 }
153 
isl_basic_set_total_dim(__isl_keep const isl_basic_set * bset)154 unsigned isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
155 {
156 	if (!bset)
157 		return 0;
158 	return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
159 }
160 
isl_set_n_dim(__isl_keep isl_set * set)161 unsigned isl_set_n_dim(__isl_keep isl_set *set)
162 {
163 	return isl_set_dim(set, isl_dim_set);
164 }
165 
isl_set_n_param(__isl_keep isl_set * set)166 unsigned isl_set_n_param(__isl_keep isl_set *set)
167 {
168 	return isl_set_dim(set, isl_dim_param);
169 }
170 
isl_basic_map_n_in(__isl_keep const isl_basic_map * bmap)171 unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap)
172 {
173 	return bmap ? bmap->dim->n_in : 0;
174 }
175 
isl_basic_map_n_out(__isl_keep const isl_basic_map * bmap)176 unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap)
177 {
178 	return bmap ? bmap->dim->n_out : 0;
179 }
180 
isl_basic_map_n_param(__isl_keep const isl_basic_map * bmap)181 unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap)
182 {
183 	return bmap ? bmap->dim->nparam : 0;
184 }
185 
isl_basic_map_n_div(__isl_keep const isl_basic_map * bmap)186 unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap)
187 {
188 	return bmap ? bmap->n_div : 0;
189 }
190 
isl_basic_map_total_dim(__isl_keep const isl_basic_map * bmap)191 unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
192 {
193 	return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
194 }
195 
isl_map_n_in(__isl_keep const isl_map * map)196 unsigned isl_map_n_in(__isl_keep const isl_map *map)
197 {
198 	return map ? map->dim->n_in : 0;
199 }
200 
isl_map_n_out(__isl_keep const isl_map * map)201 unsigned isl_map_n_out(__isl_keep const isl_map *map)
202 {
203 	return map ? map->dim->n_out : 0;
204 }
205 
isl_map_n_param(__isl_keep const isl_map * map)206 unsigned isl_map_n_param(__isl_keep const isl_map *map)
207 {
208 	return map ? map->dim->nparam : 0;
209 }
210 
211 /* Return the number of equality constraints in the description of "bmap".
212  * Return -1 on error.
213  */
isl_basic_map_n_equality(__isl_keep isl_basic_map * bmap)214 int isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
215 {
216 	if (!bmap)
217 		return -1;
218 	return bmap->n_eq;
219 }
220 
221 /* Return the number of equality constraints in the description of "bset".
222  * Return -1 on error.
223  */
isl_basic_set_n_equality(__isl_keep isl_basic_set * bset)224 int isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
225 {
226 	return isl_basic_map_n_equality(bset_to_bmap(bset));
227 }
228 
229 /* Return the number of inequality constraints in the description of "bmap".
230  * Return -1 on error.
231  */
isl_basic_map_n_inequality(__isl_keep isl_basic_map * bmap)232 int isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
233 {
234 	if (!bmap)
235 		return -1;
236 	return bmap->n_ineq;
237 }
238 
239 /* Return the number of inequality constraints in the description of "bset".
240  * Return -1 on error.
241  */
isl_basic_set_n_inequality(__isl_keep isl_basic_set * bset)242 int isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
243 {
244 	return isl_basic_map_n_inequality(bset_to_bmap(bset));
245 }
246 
247 /* Do "bmap1" and "bmap2" have the same parameters?
248  */
isl_basic_map_has_equal_params(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)249 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
250 	__isl_keep isl_basic_map *bmap2)
251 {
252 	isl_space *space1, *space2;
253 
254 	space1 = isl_basic_map_peek_space(bmap1);
255 	space2 = isl_basic_map_peek_space(bmap2);
256 	return isl_space_has_equal_params(space1, space2);
257 }
258 
259 /* Do "map1" and "map2" have the same parameters?
260  */
isl_map_has_equal_params(__isl_keep isl_map * map1,__isl_keep isl_map * map2)261 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
262 	__isl_keep isl_map *map2)
263 {
264 	isl_space *space1, *space2;
265 
266 	space1 = isl_map_peek_space(map1);
267 	space2 = isl_map_peek_space(map2);
268 	return isl_space_has_equal_params(space1, space2);
269 }
270 
271 /* Do "map" and "set" have the same parameters?
272  */
isl_map_set_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_set * set)273 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
274 	__isl_keep isl_set *set)
275 {
276 	return isl_map_has_equal_params(map, set_to_map(set));
277 }
278 
isl_map_compatible_domain(__isl_keep isl_map * map,__isl_keep isl_set * set)279 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
280 	__isl_keep isl_set *set)
281 {
282 	isl_bool m;
283 	if (!map || !set)
284 		return isl_bool_error;
285 	m = isl_map_has_equal_params(map, set_to_map(set));
286 	if (m < 0 || !m)
287 		return m;
288 	return isl_space_tuple_is_equal(map->dim, isl_dim_in,
289 					set->dim, isl_dim_set);
290 }
291 
isl_basic_map_compatible_domain(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)292 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
293 	__isl_keep isl_basic_set *bset)
294 {
295 	isl_bool m;
296 	if (!bmap || !bset)
297 		return isl_bool_error;
298 	m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
299 	if (m < 0 || !m)
300 		return m;
301 	return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
302 					bset->dim, isl_dim_set);
303 }
304 
isl_map_compatible_range(__isl_keep isl_map * map,__isl_keep isl_set * set)305 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
306 	__isl_keep isl_set *set)
307 {
308 	isl_bool m;
309 	if (!map || !set)
310 		return isl_bool_error;
311 	m = isl_map_has_equal_params(map, set_to_map(set));
312 	if (m < 0 || !m)
313 		return m;
314 	return isl_space_tuple_is_equal(map->dim, isl_dim_out,
315 					set->dim, isl_dim_set);
316 }
317 
isl_basic_map_compatible_range(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)318 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
319 	__isl_keep isl_basic_set *bset)
320 {
321 	isl_bool m;
322 	if (!bmap || !bset)
323 		return isl_bool_error;
324 	m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
325 	if (m < 0 || !m)
326 		return m;
327 	return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
328 					bset->dim, isl_dim_set);
329 }
330 
isl_basic_map_get_ctx(__isl_keep isl_basic_map * bmap)331 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
332 {
333 	return bmap ? bmap->ctx : NULL;
334 }
335 
isl_basic_set_get_ctx(__isl_keep isl_basic_set * bset)336 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
337 {
338 	return bset ? bset->ctx : NULL;
339 }
340 
isl_map_get_ctx(__isl_keep isl_map * map)341 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
342 {
343 	return map ? map->ctx : NULL;
344 }
345 
isl_set_get_ctx(__isl_keep isl_set * set)346 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
347 {
348 	return set ? set->ctx : NULL;
349 }
350 
351 /* Return the space of "bmap".
352  */
isl_basic_map_peek_space(__isl_keep const isl_basic_map * bmap)353 __isl_keep isl_space *isl_basic_map_peek_space(
354 	__isl_keep const isl_basic_map *bmap)
355 {
356 	return bmap ? bmap->dim : NULL;
357 }
358 
359 /* Return the space of "bset".
360  */
isl_basic_set_peek_space(__isl_keep isl_basic_set * bset)361 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
362 {
363 	return isl_basic_map_peek_space(bset_to_bmap(bset));
364 }
365 
isl_basic_map_get_space(__isl_keep isl_basic_map * bmap)366 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
367 {
368 	return isl_space_copy(isl_basic_map_peek_space(bmap));
369 }
370 
isl_basic_set_get_space(__isl_keep isl_basic_set * bset)371 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
372 {
373 	return isl_basic_map_get_space(bset_to_bmap(bset));
374 }
375 
376 /* Extract the divs in "bmap" as a matrix.
377  */
isl_basic_map_get_divs(__isl_keep isl_basic_map * bmap)378 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
379 {
380 	int i;
381 	isl_ctx *ctx;
382 	isl_mat *div;
383 	unsigned total;
384 	unsigned cols;
385 
386 	if (!bmap)
387 		return NULL;
388 
389 	ctx = isl_basic_map_get_ctx(bmap);
390 	total = isl_space_dim(bmap->dim, isl_dim_all);
391 	cols = 1 + 1 + total + bmap->n_div;
392 	div = isl_mat_alloc(ctx, bmap->n_div, cols);
393 	if (!div)
394 		return NULL;
395 
396 	for (i = 0; i < bmap->n_div; ++i)
397 		isl_seq_cpy(div->row[i], bmap->div[i], cols);
398 
399 	return div;
400 }
401 
402 /* Extract the divs in "bset" as a matrix.
403  */
isl_basic_set_get_divs(__isl_keep isl_basic_set * bset)404 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
405 {
406 	return isl_basic_map_get_divs(bset);
407 }
408 
isl_basic_map_get_local_space(__isl_keep isl_basic_map * bmap)409 __isl_give isl_local_space *isl_basic_map_get_local_space(
410 	__isl_keep isl_basic_map *bmap)
411 {
412 	isl_mat *div;
413 
414 	if (!bmap)
415 		return NULL;
416 
417 	div = isl_basic_map_get_divs(bmap);
418 	return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
419 }
420 
isl_basic_set_get_local_space(__isl_keep isl_basic_set * bset)421 __isl_give isl_local_space *isl_basic_set_get_local_space(
422 	__isl_keep isl_basic_set *bset)
423 {
424 	return isl_basic_map_get_local_space(bset);
425 }
426 
427 /* For each known div d = floor(f/m), add the constraints
428  *
429  *		f - m d >= 0
430  *		-(f-(m-1)) + m d >= 0
431  *
432  * Do not finalize the result.
433  */
add_known_div_constraints(__isl_take isl_basic_map * bmap)434 static __isl_give isl_basic_map *add_known_div_constraints(
435 	__isl_take isl_basic_map *bmap)
436 {
437 	int i;
438 	unsigned n_div;
439 
440 	if (!bmap)
441 		return NULL;
442 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
443 	if (n_div == 0)
444 		return bmap;
445 	bmap = isl_basic_map_cow(bmap);
446 	bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
447 	if (!bmap)
448 		return NULL;
449 	for (i = 0; i < n_div; ++i) {
450 		if (isl_int_is_zero(bmap->div[i][0]))
451 			continue;
452 		if (isl_basic_map_add_div_constraints(bmap, i) < 0)
453 			return isl_basic_map_free(bmap);
454 	}
455 
456 	return bmap;
457 }
458 
isl_basic_map_from_local_space(__isl_take isl_local_space * ls)459 __isl_give isl_basic_map *isl_basic_map_from_local_space(
460 	__isl_take isl_local_space *ls)
461 {
462 	int i;
463 	int n_div;
464 	isl_basic_map *bmap;
465 
466 	if (!ls)
467 		return NULL;
468 
469 	n_div = isl_local_space_dim(ls, isl_dim_div);
470 	bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
471 					n_div, 0, 2 * n_div);
472 
473 	for (i = 0; i < n_div; ++i)
474 		if (isl_basic_map_alloc_div(bmap) < 0)
475 			goto error;
476 
477 	for (i = 0; i < n_div; ++i)
478 		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
479 	bmap = add_known_div_constraints(bmap);
480 
481 	isl_local_space_free(ls);
482 	return bmap;
483 error:
484 	isl_local_space_free(ls);
485 	isl_basic_map_free(bmap);
486 	return NULL;
487 }
488 
isl_basic_set_from_local_space(__isl_take isl_local_space * ls)489 __isl_give isl_basic_set *isl_basic_set_from_local_space(
490 	__isl_take isl_local_space *ls)
491 {
492 	return isl_basic_map_from_local_space(ls);
493 }
494 
isl_map_get_space(__isl_keep isl_map * map)495 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
496 {
497 	return isl_space_copy(isl_map_peek_space(map));
498 }
499 
isl_set_get_space(__isl_keep isl_set * set)500 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
501 {
502 	if (!set)
503 		return NULL;
504 	return isl_space_copy(set->dim);
505 }
506 
isl_basic_map_set_tuple_name(__isl_take isl_basic_map * bmap,enum isl_dim_type type,const char * s)507 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
508 	__isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
509 {
510 	bmap = isl_basic_map_cow(bmap);
511 	if (!bmap)
512 		return NULL;
513 	bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
514 	if (!bmap->dim)
515 		goto error;
516 	bmap = isl_basic_map_finalize(bmap);
517 	return bmap;
518 error:
519 	isl_basic_map_free(bmap);
520 	return NULL;
521 }
522 
isl_basic_set_set_tuple_name(__isl_take isl_basic_set * bset,const char * s)523 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
524 	__isl_take isl_basic_set *bset, const char *s)
525 {
526 	return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
527 }
528 
isl_basic_map_get_tuple_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)529 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
530 	enum isl_dim_type type)
531 {
532 	return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
533 }
534 
isl_map_set_tuple_name(__isl_take isl_map * map,enum isl_dim_type type,const char * s)535 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
536 	enum isl_dim_type type, const char *s)
537 {
538 	int i;
539 
540 	map = isl_map_cow(map);
541 	if (!map)
542 		return NULL;
543 
544 	map->dim = isl_space_set_tuple_name(map->dim, type, s);
545 	if (!map->dim)
546 		goto error;
547 
548 	for (i = 0; i < map->n; ++i) {
549 		map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
550 		if (!map->p[i])
551 			goto error;
552 	}
553 
554 	return map;
555 error:
556 	isl_map_free(map);
557 	return NULL;
558 }
559 
560 /* Replace the identifier of the tuple of type "type" by "id".
561  */
isl_basic_map_set_tuple_id(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_id * id)562 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
563 	__isl_take isl_basic_map *bmap,
564 	enum isl_dim_type type, __isl_take isl_id *id)
565 {
566 	bmap = isl_basic_map_cow(bmap);
567 	if (!bmap)
568 		goto error;
569 	bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
570 	if (!bmap->dim)
571 		return isl_basic_map_free(bmap);
572 	bmap = isl_basic_map_finalize(bmap);
573 	return bmap;
574 error:
575 	isl_id_free(id);
576 	return NULL;
577 }
578 
579 /* Replace the identifier of the tuple by "id".
580  */
isl_basic_set_set_tuple_id(__isl_take isl_basic_set * bset,__isl_take isl_id * id)581 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
582 	__isl_take isl_basic_set *bset, __isl_take isl_id *id)
583 {
584 	return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
585 }
586 
587 /* Does the input or output tuple have a name?
588  */
isl_map_has_tuple_name(__isl_keep isl_map * map,enum isl_dim_type type)589 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
590 {
591 	return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
592 }
593 
isl_map_get_tuple_name(__isl_keep isl_map * map,enum isl_dim_type type)594 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
595 	enum isl_dim_type type)
596 {
597 	return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
598 }
599 
isl_set_set_tuple_name(__isl_take isl_set * set,const char * s)600 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
601 	const char *s)
602 {
603 	return set_from_map(isl_map_set_tuple_name(set_to_map(set),
604 						isl_dim_set, s));
605 }
606 
isl_map_set_tuple_id(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_id * id)607 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
608 	enum isl_dim_type type, __isl_take isl_id *id)
609 {
610 	map = isl_map_cow(map);
611 	if (!map)
612 		goto error;
613 
614 	map->dim = isl_space_set_tuple_id(map->dim, type, id);
615 
616 	return isl_map_reset_space(map, isl_space_copy(map->dim));
617 error:
618 	isl_id_free(id);
619 	return NULL;
620 }
621 
isl_set_set_tuple_id(__isl_take isl_set * set,__isl_take isl_id * id)622 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
623 	__isl_take isl_id *id)
624 {
625 	return isl_map_set_tuple_id(set, isl_dim_set, id);
626 }
627 
isl_map_reset_tuple_id(__isl_take isl_map * map,enum isl_dim_type type)628 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
629 	enum isl_dim_type type)
630 {
631 	map = isl_map_cow(map);
632 	if (!map)
633 		return NULL;
634 
635 	map->dim = isl_space_reset_tuple_id(map->dim, type);
636 
637 	return isl_map_reset_space(map, isl_space_copy(map->dim));
638 }
639 
isl_set_reset_tuple_id(__isl_take isl_set * set)640 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
641 {
642 	return isl_map_reset_tuple_id(set, isl_dim_set);
643 }
644 
isl_map_has_tuple_id(__isl_keep isl_map * map,enum isl_dim_type type)645 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
646 {
647 	return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
648 }
649 
isl_map_get_tuple_id(__isl_keep isl_map * map,enum isl_dim_type type)650 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
651 	enum isl_dim_type type)
652 {
653 	return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
654 }
655 
isl_set_has_tuple_id(__isl_keep isl_set * set)656 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
657 {
658 	return isl_map_has_tuple_id(set, isl_dim_set);
659 }
660 
isl_set_get_tuple_id(__isl_keep isl_set * set)661 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
662 {
663 	return isl_map_get_tuple_id(set, isl_dim_set);
664 }
665 
666 /* Does the set tuple have a name?
667  */
isl_set_has_tuple_name(__isl_keep isl_set * set)668 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
669 {
670 	if (!set)
671 		return isl_bool_error;
672 	return isl_space_has_tuple_name(set->dim, isl_dim_set);
673 }
674 
675 
isl_basic_set_get_tuple_name(__isl_keep isl_basic_set * bset)676 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
677 {
678 	return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
679 }
680 
isl_set_get_tuple_name(__isl_keep isl_set * set)681 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
682 {
683 	return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
684 }
685 
isl_basic_map_get_dim_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)686 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
687 	enum isl_dim_type type, unsigned pos)
688 {
689 	return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
690 }
691 
isl_basic_set_get_dim_name(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned pos)692 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
693 	enum isl_dim_type type, unsigned pos)
694 {
695 	return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
696 }
697 
698 /* Does the given dimension have a name?
699  */
isl_map_has_dim_name(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)700 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
701 	enum isl_dim_type type, unsigned pos)
702 {
703 	if (!map)
704 		return isl_bool_error;
705 	return isl_space_has_dim_name(map->dim, type, pos);
706 }
707 
isl_map_get_dim_name(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)708 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
709 	enum isl_dim_type type, unsigned pos)
710 {
711 	return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
712 }
713 
isl_set_get_dim_name(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)714 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
715 	enum isl_dim_type type, unsigned pos)
716 {
717 	return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
718 }
719 
720 /* Does the given dimension have a name?
721  */
isl_set_has_dim_name(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)722 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
723 	enum isl_dim_type type, unsigned pos)
724 {
725 	if (!set)
726 		return isl_bool_error;
727 	return isl_space_has_dim_name(set->dim, type, pos);
728 }
729 
isl_basic_map_set_dim_name(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,const char * s)730 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
731 	__isl_take isl_basic_map *bmap,
732 	enum isl_dim_type type, unsigned pos, const char *s)
733 {
734 	bmap = isl_basic_map_cow(bmap);
735 	if (!bmap)
736 		return NULL;
737 	bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
738 	if (!bmap->dim)
739 		goto error;
740 	return isl_basic_map_finalize(bmap);
741 error:
742 	isl_basic_map_free(bmap);
743 	return NULL;
744 }
745 
isl_map_set_dim_name(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,const char * s)746 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
747 	enum isl_dim_type type, unsigned pos, const char *s)
748 {
749 	int i;
750 
751 	map = isl_map_cow(map);
752 	if (!map)
753 		return NULL;
754 
755 	map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
756 	if (!map->dim)
757 		goto error;
758 
759 	for (i = 0; i < map->n; ++i) {
760 		map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
761 		if (!map->p[i])
762 			goto error;
763 	}
764 
765 	return map;
766 error:
767 	isl_map_free(map);
768 	return NULL;
769 }
770 
isl_basic_set_set_dim_name(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,const char * s)771 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
772 	__isl_take isl_basic_set *bset,
773 	enum isl_dim_type type, unsigned pos, const char *s)
774 {
775 	return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
776 							type, pos, s));
777 }
778 
isl_set_set_dim_name(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,const char * s)779 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
780 	enum isl_dim_type type, unsigned pos, const char *s)
781 {
782 	return set_from_map(isl_map_set_dim_name(set_to_map(set),
783 							type, pos, s));
784 }
785 
isl_basic_map_has_dim_id(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)786 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
787 	enum isl_dim_type type, unsigned pos)
788 {
789 	if (!bmap)
790 		return isl_bool_error;
791 	return isl_space_has_dim_id(bmap->dim, type, pos);
792 }
793 
isl_basic_set_get_dim_id(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned pos)794 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
795 	enum isl_dim_type type, unsigned pos)
796 {
797 	return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
798 }
799 
isl_map_has_dim_id(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)800 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
801 	enum isl_dim_type type, unsigned pos)
802 {
803 	return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
804 }
805 
isl_map_get_dim_id(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)806 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
807 	enum isl_dim_type type, unsigned pos)
808 {
809 	return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
810 }
811 
isl_set_has_dim_id(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)812 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
813 	enum isl_dim_type type, unsigned pos)
814 {
815 	return isl_map_has_dim_id(set, type, pos);
816 }
817 
isl_set_get_dim_id(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)818 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
819 	enum isl_dim_type type, unsigned pos)
820 {
821 	return isl_map_get_dim_id(set, type, pos);
822 }
823 
isl_map_set_dim_id(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_id * id)824 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
825 	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
826 {
827 	map = isl_map_cow(map);
828 	if (!map)
829 		goto error;
830 
831 	map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
832 
833 	return isl_map_reset_space(map, isl_space_copy(map->dim));
834 error:
835 	isl_id_free(id);
836 	return NULL;
837 }
838 
isl_set_set_dim_id(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_id * id)839 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
840 	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
841 {
842 	return isl_map_set_dim_id(set, type, pos, id);
843 }
844 
isl_map_find_dim_by_id(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_id * id)845 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
846 	__isl_keep isl_id *id)
847 {
848 	if (!map)
849 		return -1;
850 	return isl_space_find_dim_by_id(map->dim, type, id);
851 }
852 
isl_set_find_dim_by_id(__isl_keep isl_set * set,enum isl_dim_type type,__isl_keep isl_id * id)853 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
854 	__isl_keep isl_id *id)
855 {
856 	return isl_map_find_dim_by_id(set, type, id);
857 }
858 
859 /* Return the position of the dimension of the given type and name
860  * in "bmap".
861  * Return -1 if no such dimension can be found.
862  */
isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,const char * name)863 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
864 	enum isl_dim_type type, const char *name)
865 {
866 	if (!bmap)
867 		return -1;
868 	return isl_space_find_dim_by_name(bmap->dim, type, name);
869 }
870 
isl_map_find_dim_by_name(__isl_keep isl_map * map,enum isl_dim_type type,const char * name)871 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
872 	const char *name)
873 {
874 	if (!map)
875 		return -1;
876 	return isl_space_find_dim_by_name(map->dim, type, name);
877 }
878 
isl_set_find_dim_by_name(__isl_keep isl_set * set,enum isl_dim_type type,const char * name)879 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
880 	const char *name)
881 {
882 	return isl_map_find_dim_by_name(set, type, name);
883 }
884 
885 /* Check whether equality i of bset is a pure stride constraint
886  * on a single dimension, i.e., of the form
887  *
888  *	v = k e
889  *
890  * with k a constant and e an existentially quantified variable.
891  */
isl_basic_set_eq_is_stride(__isl_keep isl_basic_set * bset,int i)892 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
893 {
894 	unsigned nparam;
895 	unsigned d;
896 	unsigned n_div;
897 	int pos1;
898 	int pos2;
899 
900 	if (!bset)
901 		return isl_bool_error;
902 
903 	if (!isl_int_is_zero(bset->eq[i][0]))
904 		return isl_bool_false;
905 
906 	nparam = isl_basic_set_dim(bset, isl_dim_param);
907 	d = isl_basic_set_dim(bset, isl_dim_set);
908 	n_div = isl_basic_set_dim(bset, isl_dim_div);
909 
910 	if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
911 		return isl_bool_false;
912 	pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
913 	if (pos1 == -1)
914 		return isl_bool_false;
915 	if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
916 					d - pos1 - 1) != -1)
917 		return isl_bool_false;
918 
919 	pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
920 	if (pos2 == -1)
921 		return isl_bool_false;
922 	if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d  + pos2 + 1,
923 				   n_div - pos2 - 1) != -1)
924 		return isl_bool_false;
925 	if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
926 	    !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
927 		return isl_bool_false;
928 
929 	return isl_bool_true;
930 }
931 
932 /* Reset the user pointer on all identifiers of parameters and tuples
933  * of the space of "map".
934  */
isl_map_reset_user(__isl_take isl_map * map)935 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
936 {
937 	isl_space *space;
938 
939 	space = isl_map_get_space(map);
940 	space = isl_space_reset_user(space);
941 	map = isl_map_reset_space(map, space);
942 
943 	return map;
944 }
945 
946 /* Reset the user pointer on all identifiers of parameters and tuples
947  * of the space of "set".
948  */
isl_set_reset_user(__isl_take isl_set * set)949 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
950 {
951 	return isl_map_reset_user(set);
952 }
953 
isl_basic_map_is_rational(__isl_keep isl_basic_map * bmap)954 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
955 {
956 	if (!bmap)
957 		return isl_bool_error;
958 	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
959 }
960 
961 /* Has "map" been marked as a rational map?
962  * In particular, have all basic maps in "map" been marked this way?
963  * An empty map is not considered to be rational.
964  * Maps where only some of the basic maps are marked rational
965  * are not allowed.
966  */
isl_map_is_rational(__isl_keep isl_map * map)967 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
968 {
969 	int i;
970 	isl_bool rational;
971 
972 	if (!map)
973 		return isl_bool_error;
974 	if (map->n == 0)
975 		return isl_bool_false;
976 	rational = isl_basic_map_is_rational(map->p[0]);
977 	if (rational < 0)
978 		return rational;
979 	for (i = 1; i < map->n; ++i) {
980 		isl_bool rational_i;
981 
982 		rational_i = isl_basic_map_is_rational(map->p[i]);
983 		if (rational_i < 0)
984 			return rational_i;
985 		if (rational != rational_i)
986 			isl_die(isl_map_get_ctx(map), isl_error_unsupported,
987 				"mixed rational and integer basic maps "
988 				"not supported", return isl_bool_error);
989 	}
990 
991 	return rational;
992 }
993 
994 /* Has "set" been marked as a rational set?
995  * In particular, have all basic set in "set" been marked this way?
996  * An empty set is not considered to be rational.
997  * Sets where only some of the basic sets are marked rational
998  * are not allowed.
999  */
isl_set_is_rational(__isl_keep isl_set * set)1000 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1001 {
1002 	return isl_map_is_rational(set);
1003 }
1004 
isl_basic_set_is_rational(__isl_keep isl_basic_set * bset)1005 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1006 {
1007 	return isl_basic_map_is_rational(bset);
1008 }
1009 
1010 /* Does "bmap" contain any rational points?
1011  *
1012  * If "bmap" has an equality for each dimension, equating the dimension
1013  * to an integer constant, then it has no rational points, even if it
1014  * is marked as rational.
1015  */
isl_basic_map_has_rational(__isl_keep isl_basic_map * bmap)1016 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1017 {
1018 	isl_bool has_rational = isl_bool_true;
1019 	unsigned total;
1020 
1021 	if (!bmap)
1022 		return isl_bool_error;
1023 	if (isl_basic_map_plain_is_empty(bmap))
1024 		return isl_bool_false;
1025 	if (!isl_basic_map_is_rational(bmap))
1026 		return isl_bool_false;
1027 	bmap = isl_basic_map_copy(bmap);
1028 	bmap = isl_basic_map_implicit_equalities(bmap);
1029 	if (!bmap)
1030 		return isl_bool_error;
1031 	total = isl_basic_map_total_dim(bmap);
1032 	if (bmap->n_eq == total) {
1033 		int i, j;
1034 		for (i = 0; i < bmap->n_eq; ++i) {
1035 			j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1036 			if (j < 0)
1037 				break;
1038 			if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1039 			    !isl_int_is_negone(bmap->eq[i][1 + j]))
1040 				break;
1041 			j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1042 						    total - j - 1);
1043 			if (j >= 0)
1044 				break;
1045 		}
1046 		if (i == bmap->n_eq)
1047 			has_rational = isl_bool_false;
1048 	}
1049 	isl_basic_map_free(bmap);
1050 
1051 	return has_rational;
1052 }
1053 
1054 /* Does "map" contain any rational points?
1055  */
isl_map_has_rational(__isl_keep isl_map * map)1056 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1057 {
1058 	int i;
1059 	isl_bool has_rational;
1060 
1061 	if (!map)
1062 		return isl_bool_error;
1063 	for (i = 0; i < map->n; ++i) {
1064 		has_rational = isl_basic_map_has_rational(map->p[i]);
1065 		if (has_rational < 0 || has_rational)
1066 			return has_rational;
1067 	}
1068 	return isl_bool_false;
1069 }
1070 
1071 /* Does "set" contain any rational points?
1072  */
isl_set_has_rational(__isl_keep isl_set * set)1073 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1074 {
1075 	return isl_map_has_rational(set);
1076 }
1077 
1078 /* Is this basic set a parameter domain?
1079  */
isl_basic_set_is_params(__isl_keep isl_basic_set * bset)1080 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1081 {
1082 	if (!bset)
1083 		return isl_bool_error;
1084 	return isl_space_is_params(bset->dim);
1085 }
1086 
1087 /* Is this set a parameter domain?
1088  */
isl_set_is_params(__isl_keep isl_set * set)1089 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1090 {
1091 	if (!set)
1092 		return isl_bool_error;
1093 	return isl_space_is_params(set->dim);
1094 }
1095 
1096 /* Is this map actually a parameter domain?
1097  * Users should never call this function.  Outside of isl,
1098  * a map can never be a parameter domain.
1099  */
isl_map_is_params(__isl_keep isl_map * map)1100 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1101 {
1102 	if (!map)
1103 		return isl_bool_error;
1104 	return isl_space_is_params(map->dim);
1105 }
1106 
basic_map_init(struct isl_ctx * ctx,struct isl_basic_map * bmap,unsigned extra,unsigned n_eq,unsigned n_ineq)1107 static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
1108 		struct isl_basic_map *bmap, unsigned extra,
1109 		unsigned n_eq, unsigned n_ineq)
1110 {
1111 	int i;
1112 	size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
1113 
1114 	bmap->ctx = ctx;
1115 	isl_ctx_ref(ctx);
1116 
1117 	bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1118 	if (isl_blk_is_error(bmap->block))
1119 		goto error;
1120 
1121 	bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1122 	if ((n_ineq + n_eq) && !bmap->ineq)
1123 		goto error;
1124 
1125 	if (extra == 0) {
1126 		bmap->block2 = isl_blk_empty();
1127 		bmap->div = NULL;
1128 	} else {
1129 		bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1130 		if (isl_blk_is_error(bmap->block2))
1131 			goto error;
1132 
1133 		bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1134 		if (!bmap->div)
1135 			goto error;
1136 	}
1137 
1138 	for (i = 0; i < n_ineq + n_eq; ++i)
1139 		bmap->ineq[i] = bmap->block.data + i * row_size;
1140 
1141 	for (i = 0; i < extra; ++i)
1142 		bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1143 
1144 	bmap->ref = 1;
1145 	bmap->flags = 0;
1146 	bmap->c_size = n_eq + n_ineq;
1147 	bmap->eq = bmap->ineq + n_ineq;
1148 	bmap->extra = extra;
1149 	bmap->n_eq = 0;
1150 	bmap->n_ineq = 0;
1151 	bmap->n_div = 0;
1152 	bmap->sample = NULL;
1153 
1154 	return bmap;
1155 error:
1156 	isl_basic_map_free(bmap);
1157 	return NULL;
1158 }
1159 
isl_basic_set_alloc(struct isl_ctx * ctx,unsigned nparam,unsigned dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1160 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1161 		unsigned nparam, unsigned dim, unsigned extra,
1162 		unsigned n_eq, unsigned n_ineq)
1163 {
1164 	struct isl_basic_map *bmap;
1165 	isl_space *space;
1166 
1167 	space = isl_space_set_alloc(ctx, nparam, dim);
1168 	if (!space)
1169 		return NULL;
1170 
1171 	bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1172 	return bset_from_bmap(bmap);
1173 }
1174 
isl_basic_set_alloc_space(__isl_take isl_space * dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1175 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1176 		unsigned extra, unsigned n_eq, unsigned n_ineq)
1177 {
1178 	struct isl_basic_map *bmap;
1179 	if (!dim)
1180 		return NULL;
1181 	isl_assert(dim->ctx, dim->n_in == 0, goto error);
1182 	bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1183 	return bset_from_bmap(bmap);
1184 error:
1185 	isl_space_free(dim);
1186 	return NULL;
1187 }
1188 
isl_basic_map_alloc_space(__isl_take isl_space * dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1189 struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
1190 		unsigned extra, unsigned n_eq, unsigned n_ineq)
1191 {
1192 	struct isl_basic_map *bmap;
1193 
1194 	if (!dim)
1195 		return NULL;
1196 	bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
1197 	if (!bmap)
1198 		goto error;
1199 	bmap->dim = dim;
1200 
1201 	return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
1202 error:
1203 	isl_space_free(dim);
1204 	return NULL;
1205 }
1206 
isl_basic_map_alloc(struct isl_ctx * ctx,unsigned nparam,unsigned in,unsigned out,unsigned extra,unsigned n_eq,unsigned n_ineq)1207 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1208 		unsigned nparam, unsigned in, unsigned out, unsigned extra,
1209 		unsigned n_eq, unsigned n_ineq)
1210 {
1211 	struct isl_basic_map *bmap;
1212 	isl_space *dim;
1213 
1214 	dim = isl_space_alloc(ctx, nparam, in, out);
1215 	if (!dim)
1216 		return NULL;
1217 
1218 	bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1219 	return bmap;
1220 }
1221 
dup_constraints(struct isl_basic_map * dst,struct isl_basic_map * src)1222 static void dup_constraints(
1223 		struct isl_basic_map *dst, struct isl_basic_map *src)
1224 {
1225 	int i;
1226 	unsigned total = isl_basic_map_total_dim(src);
1227 
1228 	for (i = 0; i < src->n_eq; ++i) {
1229 		int j = isl_basic_map_alloc_equality(dst);
1230 		isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1231 	}
1232 
1233 	for (i = 0; i < src->n_ineq; ++i) {
1234 		int j = isl_basic_map_alloc_inequality(dst);
1235 		isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1236 	}
1237 
1238 	for (i = 0; i < src->n_div; ++i) {
1239 		int j = isl_basic_map_alloc_div(dst);
1240 		isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1241 	}
1242 	ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1243 }
1244 
isl_basic_map_dup(__isl_keep isl_basic_map * bmap)1245 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1246 {
1247 	struct isl_basic_map *dup;
1248 
1249 	if (!bmap)
1250 		return NULL;
1251 	dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1252 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
1253 	if (!dup)
1254 		return NULL;
1255 	dup_constraints(dup, bmap);
1256 	dup->flags = bmap->flags;
1257 	dup->sample = isl_vec_copy(bmap->sample);
1258 	return dup;
1259 }
1260 
isl_basic_set_dup(struct isl_basic_set * bset)1261 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1262 {
1263 	struct isl_basic_map *dup;
1264 
1265 	dup = isl_basic_map_dup(bset_to_bmap(bset));
1266 	return bset_from_bmap(dup);
1267 }
1268 
isl_basic_set_copy(__isl_keep isl_basic_set * bset)1269 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1270 {
1271 	if (!bset)
1272 		return NULL;
1273 
1274 	if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1275 		bset->ref++;
1276 		return bset;
1277 	}
1278 	return isl_basic_set_dup(bset);
1279 }
1280 
isl_set_copy(__isl_keep isl_set * set)1281 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1282 {
1283 	if (!set)
1284 		return NULL;
1285 
1286 	set->ref++;
1287 	return set;
1288 }
1289 
isl_basic_map_copy(__isl_keep isl_basic_map * bmap)1290 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1291 {
1292 	if (!bmap)
1293 		return NULL;
1294 
1295 	if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1296 		bmap->ref++;
1297 		return bmap;
1298 	}
1299 	bmap = isl_basic_map_dup(bmap);
1300 	if (bmap)
1301 		ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1302 	return bmap;
1303 }
1304 
isl_map_copy(__isl_keep isl_map * map)1305 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1306 {
1307 	if (!map)
1308 		return NULL;
1309 
1310 	map->ref++;
1311 	return map;
1312 }
1313 
isl_basic_map_free(__isl_take isl_basic_map * bmap)1314 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1315 {
1316 	if (!bmap)
1317 		return NULL;
1318 
1319 	if (--bmap->ref > 0)
1320 		return NULL;
1321 
1322 	isl_ctx_deref(bmap->ctx);
1323 	free(bmap->div);
1324 	isl_blk_free(bmap->ctx, bmap->block2);
1325 	free(bmap->ineq);
1326 	isl_blk_free(bmap->ctx, bmap->block);
1327 	isl_vec_free(bmap->sample);
1328 	isl_space_free(bmap->dim);
1329 	free(bmap);
1330 
1331 	return NULL;
1332 }
1333 
isl_basic_set_free(__isl_take isl_basic_set * bset)1334 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1335 {
1336 	return isl_basic_map_free(bset_to_bmap(bset));
1337 }
1338 
room_for_con(struct isl_basic_map * bmap,unsigned n)1339 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1340 {
1341 	return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1342 }
1343 
1344 /* Check that "map" has only named parameters, reporting an error
1345  * if it does not.
1346  */
isl_map_check_named_params(__isl_keep isl_map * map)1347 isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1348 {
1349 	return isl_space_check_named_params(isl_map_peek_space(map));
1350 }
1351 
1352 /* Check that "bmap" has only named parameters, reporting an error
1353  * if it does not.
1354  */
isl_basic_map_check_named_params(__isl_keep isl_basic_map * bmap)1355 static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
1356 {
1357 	return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
1358 }
1359 
1360 /* Check that "bmap1" and "bmap2" have the same parameters,
1361  * reporting an error if they do not.
1362  */
isl_basic_map_check_equal_params(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)1363 static isl_stat isl_basic_map_check_equal_params(
1364 	__isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1365 {
1366 	isl_bool match;
1367 
1368 	match = isl_basic_map_has_equal_params(bmap1, bmap2);
1369 	if (match < 0)
1370 		return isl_stat_error;
1371 	if (!match)
1372 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1373 			"parameters don't match", return isl_stat_error);
1374 	return isl_stat_ok;
1375 }
1376 
isl_map_align_params_map_map_and(__isl_take isl_map * map1,__isl_take isl_map * map2,__isl_give isl_map * (* fn)(__isl_take isl_map * map1,__isl_take isl_map * map2))1377 __isl_give isl_map *isl_map_align_params_map_map_and(
1378 	__isl_take isl_map *map1, __isl_take isl_map *map2,
1379 	__isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1380 				    __isl_take isl_map *map2))
1381 {
1382 	if (!map1 || !map2)
1383 		goto error;
1384 	if (isl_map_has_equal_params(map1, map2))
1385 		return fn(map1, map2);
1386 	if (isl_map_check_named_params(map1) < 0)
1387 		goto error;
1388 	if (isl_map_check_named_params(map2) < 0)
1389 		goto error;
1390 	map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1391 	map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1392 	return fn(map1, map2);
1393 error:
1394 	isl_map_free(map1);
1395 	isl_map_free(map2);
1396 	return NULL;
1397 }
1398 
isl_map_align_params_map_map_and_test(__isl_keep isl_map * map1,__isl_keep isl_map * map2,isl_bool (* fn)(__isl_keep isl_map * map1,__isl_keep isl_map * map2))1399 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1400 	__isl_keep isl_map *map2,
1401 	isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1402 {
1403 	isl_bool r;
1404 
1405 	if (!map1 || !map2)
1406 		return isl_bool_error;
1407 	if (isl_map_has_equal_params(map1, map2))
1408 		return fn(map1, map2);
1409 	if (isl_map_check_named_params(map1) < 0)
1410 		return isl_bool_error;
1411 	if (isl_map_check_named_params(map2) < 0)
1412 		return isl_bool_error;
1413 	map1 = isl_map_copy(map1);
1414 	map2 = isl_map_copy(map2);
1415 	map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1416 	map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1417 	r = fn(map1, map2);
1418 	isl_map_free(map1);
1419 	isl_map_free(map2);
1420 	return r;
1421 }
1422 
isl_basic_map_alloc_equality(struct isl_basic_map * bmap)1423 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1424 {
1425 	struct isl_ctx *ctx;
1426 	if (!bmap)
1427 		return -1;
1428 	ctx = bmap->ctx;
1429 	isl_assert(ctx, room_for_con(bmap, 1), return -1);
1430 	isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1431 			return -1);
1432 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1433 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1434 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1435 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1436 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1437 	if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1438 		isl_int *t;
1439 		int j = isl_basic_map_alloc_inequality(bmap);
1440 		if (j < 0)
1441 			return -1;
1442 		t = bmap->ineq[j];
1443 		bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1444 		bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1445 		bmap->eq[-1] = t;
1446 		bmap->n_eq++;
1447 		bmap->n_ineq--;
1448 		bmap->eq--;
1449 		return 0;
1450 	}
1451 	isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1452 		      bmap->extra - bmap->n_div);
1453 	return bmap->n_eq++;
1454 }
1455 
isl_basic_set_alloc_equality(struct isl_basic_set * bset)1456 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1457 {
1458 	return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1459 }
1460 
isl_basic_map_free_equality(struct isl_basic_map * bmap,unsigned n)1461 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1462 {
1463 	if (!bmap)
1464 		return -1;
1465 	isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1466 	bmap->n_eq -= n;
1467 	return 0;
1468 }
1469 
isl_basic_set_free_equality(struct isl_basic_set * bset,unsigned n)1470 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1471 {
1472 	return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1473 }
1474 
isl_basic_map_drop_equality(struct isl_basic_map * bmap,unsigned pos)1475 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1476 {
1477 	isl_int *t;
1478 	if (!bmap)
1479 		return -1;
1480 	isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1481 
1482 	if (pos != bmap->n_eq - 1) {
1483 		t = bmap->eq[pos];
1484 		bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1485 		bmap->eq[bmap->n_eq - 1] = t;
1486 	}
1487 	bmap->n_eq--;
1488 	return 0;
1489 }
1490 
1491 /* Turn inequality "pos" of "bmap" into an equality.
1492  *
1493  * In particular, we move the inequality in front of the equalities
1494  * and move the last inequality in the position of the moved inequality.
1495  * Note that isl_tab_make_equalities_explicit depends on this particular
1496  * change in the ordering of the constraints.
1497  */
isl_basic_map_inequality_to_equality(struct isl_basic_map * bmap,unsigned pos)1498 void isl_basic_map_inequality_to_equality(
1499 		struct isl_basic_map *bmap, unsigned pos)
1500 {
1501 	isl_int *t;
1502 
1503 	t = bmap->ineq[pos];
1504 	bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1505 	bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1506 	bmap->eq[-1] = t;
1507 	bmap->n_eq++;
1508 	bmap->n_ineq--;
1509 	bmap->eq--;
1510 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1511 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1512 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1513 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1514 }
1515 
room_for_ineq(struct isl_basic_map * bmap,unsigned n)1516 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1517 {
1518 	return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1519 }
1520 
isl_basic_map_alloc_inequality(__isl_keep isl_basic_map * bmap)1521 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1522 {
1523 	struct isl_ctx *ctx;
1524 	if (!bmap)
1525 		return -1;
1526 	ctx = bmap->ctx;
1527 	isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1528 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1529 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1530 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1531 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1532 	isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1533 		      1 + isl_basic_map_total_dim(bmap),
1534 		      bmap->extra - bmap->n_div);
1535 	return bmap->n_ineq++;
1536 }
1537 
isl_basic_set_alloc_inequality(__isl_keep isl_basic_set * bset)1538 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1539 {
1540 	return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1541 }
1542 
isl_basic_map_free_inequality(struct isl_basic_map * bmap,unsigned n)1543 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1544 {
1545 	if (!bmap)
1546 		return -1;
1547 	isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1548 	bmap->n_ineq -= n;
1549 	return 0;
1550 }
1551 
isl_basic_set_free_inequality(struct isl_basic_set * bset,unsigned n)1552 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1553 {
1554 	return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1555 }
1556 
isl_basic_map_drop_inequality(struct isl_basic_map * bmap,unsigned pos)1557 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1558 {
1559 	isl_int *t;
1560 	if (!bmap)
1561 		return -1;
1562 	isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1563 
1564 	if (pos != bmap->n_ineq - 1) {
1565 		t = bmap->ineq[pos];
1566 		bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1567 		bmap->ineq[bmap->n_ineq - 1] = t;
1568 		ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1569 	}
1570 	bmap->n_ineq--;
1571 	return 0;
1572 }
1573 
isl_basic_set_drop_inequality(struct isl_basic_set * bset,unsigned pos)1574 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1575 {
1576 	return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1577 }
1578 
isl_basic_map_add_eq(__isl_take isl_basic_map * bmap,isl_int * eq)1579 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1580 	isl_int *eq)
1581 {
1582 	int k;
1583 
1584 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1585 	if (!bmap)
1586 		return NULL;
1587 	k = isl_basic_map_alloc_equality(bmap);
1588 	if (k < 0)
1589 		goto error;
1590 	isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1591 	return bmap;
1592 error:
1593 	isl_basic_map_free(bmap);
1594 	return NULL;
1595 }
1596 
isl_basic_set_add_eq(__isl_take isl_basic_set * bset,isl_int * eq)1597 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1598 	isl_int *eq)
1599 {
1600 	return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1601 }
1602 
isl_basic_map_add_ineq(__isl_take isl_basic_map * bmap,isl_int * ineq)1603 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1604 	isl_int *ineq)
1605 {
1606 	int k;
1607 
1608 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1609 	if (!bmap)
1610 		return NULL;
1611 	k = isl_basic_map_alloc_inequality(bmap);
1612 	if (k < 0)
1613 		goto error;
1614 	isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1615 	return bmap;
1616 error:
1617 	isl_basic_map_free(bmap);
1618 	return NULL;
1619 }
1620 
isl_basic_set_add_ineq(__isl_take isl_basic_set * bset,isl_int * ineq)1621 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1622 	isl_int *ineq)
1623 {
1624 	return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1625 }
1626 
isl_basic_map_alloc_div(struct isl_basic_map * bmap)1627 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1628 {
1629 	if (!bmap)
1630 		return -1;
1631 	isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1632 	isl_seq_clr(bmap->div[bmap->n_div] +
1633 		      1 + 1 + isl_basic_map_total_dim(bmap),
1634 		      bmap->extra - bmap->n_div);
1635 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1636 	return bmap->n_div++;
1637 }
1638 
isl_basic_set_alloc_div(struct isl_basic_set * bset)1639 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1640 {
1641 	return isl_basic_map_alloc_div(bset_to_bmap(bset));
1642 }
1643 
1644 /* Check that there are "n" dimensions of type "type" starting at "first"
1645  * in "bmap".
1646  */
isl_basic_map_check_range(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)1647 static isl_stat isl_basic_map_check_range(__isl_keep isl_basic_map *bmap,
1648 	enum isl_dim_type type, unsigned first, unsigned n)
1649 {
1650 	unsigned dim;
1651 
1652 	if (!bmap)
1653 		return isl_stat_error;
1654 	dim = isl_basic_map_dim(bmap, type);
1655 	if (first + n > dim || first + n < first)
1656 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1657 			"position or range out of bounds",
1658 			return isl_stat_error);
1659 	return isl_stat_ok;
1660 }
1661 
1662 /* Insert an extra integer division, prescribed by "div", to "bmap"
1663  * at (integer division) position "pos".
1664  *
1665  * The integer division is first added at the end and then moved
1666  * into the right position.
1667  */
isl_basic_map_insert_div(__isl_take isl_basic_map * bmap,int pos,__isl_keep isl_vec * div)1668 __isl_give isl_basic_map *isl_basic_map_insert_div(
1669 	__isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1670 {
1671 	int i, k;
1672 
1673 	bmap = isl_basic_map_cow(bmap);
1674 	if (!bmap || !div)
1675 		return isl_basic_map_free(bmap);
1676 
1677 	if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1678 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1679 			"unexpected size", return isl_basic_map_free(bmap));
1680 	if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1681 		return isl_basic_map_free(bmap);
1682 
1683 	bmap = isl_basic_map_extend_space(bmap,
1684 					isl_basic_map_get_space(bmap), 1, 0, 2);
1685 	k = isl_basic_map_alloc_div(bmap);
1686 	if (k < 0)
1687 		return isl_basic_map_free(bmap);
1688 	isl_seq_cpy(bmap->div[k], div->el, div->size);
1689 	isl_int_set_si(bmap->div[k][div->size], 0);
1690 
1691 	for (i = k; i > pos; --i)
1692 		isl_basic_map_swap_div(bmap, i, i - 1);
1693 
1694 	return bmap;
1695 }
1696 
isl_basic_map_free_div(struct isl_basic_map * bmap,unsigned n)1697 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1698 {
1699 	if (!bmap)
1700 		return isl_stat_error;
1701 	isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1702 	bmap->n_div -= n;
1703 	return isl_stat_ok;
1704 }
1705 
1706 /* Copy constraint from src to dst, putting the vars of src at offset
1707  * dim_off in dst and the divs of src at offset div_off in dst.
1708  * If both sets are actually map, then dim_off applies to the input
1709  * variables.
1710  */
copy_constraint(struct isl_basic_map * dst_map,isl_int * dst,struct isl_basic_map * src_map,isl_int * src,unsigned in_off,unsigned out_off,unsigned div_off)1711 static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
1712 			    struct isl_basic_map *src_map, isl_int *src,
1713 			    unsigned in_off, unsigned out_off, unsigned div_off)
1714 {
1715 	unsigned src_nparam = isl_basic_map_dim(src_map, isl_dim_param);
1716 	unsigned dst_nparam = isl_basic_map_dim(dst_map, isl_dim_param);
1717 	unsigned src_in = isl_basic_map_dim(src_map, isl_dim_in);
1718 	unsigned dst_in = isl_basic_map_dim(dst_map, isl_dim_in);
1719 	unsigned src_out = isl_basic_map_dim(src_map, isl_dim_out);
1720 	unsigned dst_out = isl_basic_map_dim(dst_map, isl_dim_out);
1721 	isl_int_set(dst[0], src[0]);
1722 	isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
1723 	if (dst_nparam > src_nparam)
1724 		isl_seq_clr(dst+1+src_nparam,
1725 				dst_nparam - src_nparam);
1726 	isl_seq_clr(dst+1+dst_nparam, in_off);
1727 	isl_seq_cpy(dst+1+dst_nparam+in_off,
1728 		    src+1+src_nparam,
1729 		    isl_min(dst_in-in_off, src_in));
1730 	if (dst_in-in_off > src_in)
1731 		isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
1732 				dst_in - in_off - src_in);
1733 	isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
1734 	isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
1735 		    src+1+src_nparam+src_in,
1736 		    isl_min(dst_out-out_off, src_out));
1737 	if (dst_out-out_off > src_out)
1738 		isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
1739 				dst_out - out_off - src_out);
1740 	isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
1741 	isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
1742 		    src+1+src_nparam+src_in+src_out,
1743 		    isl_min(dst_map->extra-div_off, src_map->n_div));
1744 	if (dst_map->n_div-div_off > src_map->n_div)
1745 		isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
1746 				div_off+src_map->n_div,
1747 				dst_map->n_div - div_off - src_map->n_div);
1748 }
1749 
copy_div(struct isl_basic_map * dst_map,isl_int * dst,struct isl_basic_map * src_map,isl_int * src,unsigned in_off,unsigned out_off,unsigned div_off)1750 static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
1751 		     struct isl_basic_map *src_map, isl_int *src,
1752 		     unsigned in_off, unsigned out_off, unsigned div_off)
1753 {
1754 	isl_int_set(dst[0], src[0]);
1755 	copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
1756 }
1757 
add_constraints(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2,unsigned i_pos,unsigned o_pos)1758 static __isl_give isl_basic_map *add_constraints(
1759 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1760 	unsigned i_pos, unsigned o_pos)
1761 {
1762 	int i;
1763 	unsigned div_off;
1764 
1765 	if (!bmap1 || !bmap2)
1766 		goto error;
1767 
1768 	div_off = bmap1->n_div;
1769 
1770 	for (i = 0; i < bmap2->n_eq; ++i) {
1771 		int i1 = isl_basic_map_alloc_equality(bmap1);
1772 		if (i1 < 0)
1773 			goto error;
1774 		copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
1775 				i_pos, o_pos, div_off);
1776 	}
1777 
1778 	for (i = 0; i < bmap2->n_ineq; ++i) {
1779 		int i1 = isl_basic_map_alloc_inequality(bmap1);
1780 		if (i1 < 0)
1781 			goto error;
1782 		copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
1783 				i_pos, o_pos, div_off);
1784 	}
1785 
1786 	for (i = 0; i < bmap2->n_div; ++i) {
1787 		int i1 = isl_basic_map_alloc_div(bmap1);
1788 		if (i1 < 0)
1789 			goto error;
1790 		copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
1791 			 i_pos, o_pos, div_off);
1792 	}
1793 
1794 	isl_basic_map_free(bmap2);
1795 
1796 	return bmap1;
1797 
1798 error:
1799 	isl_basic_map_free(bmap1);
1800 	isl_basic_map_free(bmap2);
1801 	return NULL;
1802 }
1803 
isl_basic_set_add_constraints(struct isl_basic_set * bset1,struct isl_basic_set * bset2,unsigned pos)1804 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1805 		struct isl_basic_set *bset2, unsigned pos)
1806 {
1807 	return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1808 						bset_to_bmap(bset2), 0, pos));
1809 }
1810 
isl_basic_map_extend_space(__isl_take isl_basic_map * base,__isl_take isl_space * dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1811 __isl_give isl_basic_map *isl_basic_map_extend_space(
1812 	__isl_take isl_basic_map *base, __isl_take isl_space *dim,
1813 	unsigned extra, unsigned n_eq, unsigned n_ineq)
1814 {
1815 	struct isl_basic_map *ext;
1816 	unsigned flags;
1817 	int dims_ok;
1818 
1819 	if (!dim)
1820 		goto error;
1821 
1822 	if (!base)
1823 		goto error;
1824 
1825 	dims_ok = isl_space_is_equal(base->dim, dim) &&
1826 		  base->extra >= base->n_div + extra;
1827 
1828 	if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1829 		       room_for_ineq(base, n_ineq)) {
1830 		isl_space_free(dim);
1831 		return base;
1832 	}
1833 
1834 	isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
1835 	isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
1836 	isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
1837 	extra += base->extra;
1838 	n_eq += base->n_eq;
1839 	n_ineq += base->n_ineq;
1840 
1841 	ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1842 	dim = NULL;
1843 	if (!ext)
1844 		goto error;
1845 
1846 	if (dims_ok)
1847 		ext->sample = isl_vec_copy(base->sample);
1848 	flags = base->flags;
1849 	ext = add_constraints(ext, base, 0, 0);
1850 	if (ext) {
1851 		ext->flags = flags;
1852 		ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1853 	}
1854 
1855 	return ext;
1856 
1857 error:
1858 	isl_space_free(dim);
1859 	isl_basic_map_free(base);
1860 	return NULL;
1861 }
1862 
isl_basic_set_extend_space(__isl_take isl_basic_set * base,__isl_take isl_space * dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1863 __isl_give isl_basic_set *isl_basic_set_extend_space(
1864 	__isl_take isl_basic_set *base,
1865 		__isl_take isl_space *dim, unsigned extra,
1866 		unsigned n_eq, unsigned n_ineq)
1867 {
1868 	return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1869 						    dim, extra, n_eq, n_ineq));
1870 }
1871 
isl_basic_map_extend_constraints(struct isl_basic_map * base,unsigned n_eq,unsigned n_ineq)1872 struct isl_basic_map *isl_basic_map_extend_constraints(
1873 		struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1874 {
1875 	if (!base)
1876 		return NULL;
1877 	return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1878 					0, n_eq, n_ineq);
1879 }
1880 
isl_basic_map_extend(struct isl_basic_map * base,unsigned nparam,unsigned n_in,unsigned n_out,unsigned extra,unsigned n_eq,unsigned n_ineq)1881 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1882 		unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1883 		unsigned n_eq, unsigned n_ineq)
1884 {
1885 	struct isl_basic_map *bmap;
1886 	isl_space *dim;
1887 
1888 	if (!base)
1889 		return NULL;
1890 	dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1891 	if (!dim)
1892 		goto error;
1893 
1894 	bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1895 	return bmap;
1896 error:
1897 	isl_basic_map_free(base);
1898 	return NULL;
1899 }
1900 
isl_basic_set_extend(struct isl_basic_set * base,unsigned nparam,unsigned dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1901 struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
1902 		unsigned nparam, unsigned dim, unsigned extra,
1903 		unsigned n_eq, unsigned n_ineq)
1904 {
1905 	return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
1906 					nparam, 0, dim, extra, n_eq, n_ineq));
1907 }
1908 
isl_basic_set_extend_constraints(struct isl_basic_set * base,unsigned n_eq,unsigned n_ineq)1909 struct isl_basic_set *isl_basic_set_extend_constraints(
1910 		struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1911 {
1912 	isl_basic_map *bmap = bset_to_bmap(base);
1913 	bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1914 	return bset_from_bmap(bmap);
1915 }
1916 
isl_basic_set_cow(__isl_take isl_basic_set * bset)1917 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1918 {
1919 	return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1920 }
1921 
isl_basic_map_cow(__isl_take isl_basic_map * bmap)1922 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1923 {
1924 	if (!bmap)
1925 		return NULL;
1926 
1927 	if (bmap->ref > 1) {
1928 		bmap->ref--;
1929 		bmap = isl_basic_map_dup(bmap);
1930 	}
1931 	if (bmap) {
1932 		ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1933 		ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1934 	}
1935 	return bmap;
1936 }
1937 
1938 /* Clear all cached information in "map", either because it is about
1939  * to be modified or because it is being freed.
1940  * Always return the same pointer that is passed in.
1941  * This is needed for the use in isl_map_free.
1942  */
clear_caches(__isl_take isl_map * map)1943 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1944 {
1945 	isl_basic_map_free(map->cached_simple_hull[0]);
1946 	isl_basic_map_free(map->cached_simple_hull[1]);
1947 	map->cached_simple_hull[0] = NULL;
1948 	map->cached_simple_hull[1] = NULL;
1949 	return map;
1950 }
1951 
isl_set_cow(__isl_take isl_set * set)1952 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
1953 {
1954 	return isl_map_cow(set);
1955 }
1956 
1957 /* Return an isl_map that is equal to "map" and that has only
1958  * a single reference.
1959  *
1960  * If the original input already has only one reference, then
1961  * simply return it, but clear all cached information, since
1962  * it may be rendered invalid by the operations that will be
1963  * performed on the result.
1964  *
1965  * Otherwise, create a duplicate (without any cached information).
1966  */
isl_map_cow(__isl_take isl_map * map)1967 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
1968 {
1969 	if (!map)
1970 		return NULL;
1971 
1972 	if (map->ref == 1)
1973 		return clear_caches(map);
1974 	map->ref--;
1975 	return isl_map_dup(map);
1976 }
1977 
swap_vars(struct isl_blk blk,isl_int * a,unsigned a_len,unsigned b_len)1978 static void swap_vars(struct isl_blk blk, isl_int *a,
1979 			unsigned a_len, unsigned b_len)
1980 {
1981 	isl_seq_cpy(blk.data, a+a_len, b_len);
1982 	isl_seq_cpy(blk.data+b_len, a, a_len);
1983 	isl_seq_cpy(a, blk.data, b_len+a_len);
1984 }
1985 
isl_basic_map_swap_vars(__isl_take isl_basic_map * bmap,unsigned pos,unsigned n1,unsigned n2)1986 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1987 	__isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1988 {
1989 	int i;
1990 	struct isl_blk blk;
1991 
1992 	if (!bmap)
1993 		goto error;
1994 
1995 	isl_assert(bmap->ctx,
1996 		pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
1997 
1998 	if (n1 == 0 || n2 == 0)
1999 		return bmap;
2000 
2001 	bmap = isl_basic_map_cow(bmap);
2002 	if (!bmap)
2003 		return NULL;
2004 
2005 	blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2006 	if (isl_blk_is_error(blk))
2007 		goto error;
2008 
2009 	for (i = 0; i < bmap->n_eq; ++i)
2010 		swap_vars(blk,
2011 			  bmap->eq[i] + pos, n1, n2);
2012 
2013 	for (i = 0; i < bmap->n_ineq; ++i)
2014 		swap_vars(blk,
2015 			  bmap->ineq[i] + pos, n1, n2);
2016 
2017 	for (i = 0; i < bmap->n_div; ++i)
2018 		swap_vars(blk,
2019 			  bmap->div[i]+1 + pos, n1, n2);
2020 
2021 	isl_blk_free(bmap->ctx, blk);
2022 
2023 	ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
2024 	bmap = isl_basic_map_gauss(bmap, NULL);
2025 	return isl_basic_map_finalize(bmap);
2026 error:
2027 	isl_basic_map_free(bmap);
2028 	return NULL;
2029 }
2030 
isl_basic_map_set_to_empty(__isl_take isl_basic_map * bmap)2031 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2032 	__isl_take isl_basic_map *bmap)
2033 {
2034 	int i = 0;
2035 	unsigned total;
2036 	if (!bmap)
2037 		goto error;
2038 	total = isl_basic_map_total_dim(bmap);
2039 	if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2040 		return isl_basic_map_free(bmap);
2041 	isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2042 	if (bmap->n_eq > 0)
2043 		isl_basic_map_free_equality(bmap, bmap->n_eq-1);
2044 	else {
2045 		i = isl_basic_map_alloc_equality(bmap);
2046 		if (i < 0)
2047 			goto error;
2048 	}
2049 	isl_int_set_si(bmap->eq[i][0], 1);
2050 	isl_seq_clr(bmap->eq[i]+1, total);
2051 	ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2052 	isl_vec_free(bmap->sample);
2053 	bmap->sample = NULL;
2054 	return isl_basic_map_finalize(bmap);
2055 error:
2056 	isl_basic_map_free(bmap);
2057 	return NULL;
2058 }
2059 
isl_basic_set_set_to_empty(__isl_take isl_basic_set * bset)2060 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2061 	__isl_take isl_basic_set *bset)
2062 {
2063 	return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2064 }
2065 
isl_basic_map_set_rational(__isl_take isl_basic_map * bmap)2066 __isl_give isl_basic_map *isl_basic_map_set_rational(
2067 	__isl_take isl_basic_map *bmap)
2068 {
2069 	if (!bmap)
2070 		return NULL;
2071 
2072 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2073 		return bmap;
2074 
2075 	bmap = isl_basic_map_cow(bmap);
2076 	if (!bmap)
2077 		return NULL;
2078 
2079 	ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2080 
2081 	return isl_basic_map_finalize(bmap);
2082 }
2083 
isl_basic_set_set_rational(__isl_take isl_basic_set * bset)2084 __isl_give isl_basic_set *isl_basic_set_set_rational(
2085 	__isl_take isl_basic_set *bset)
2086 {
2087 	return isl_basic_map_set_rational(bset);
2088 }
2089 
isl_basic_set_set_integral(__isl_take isl_basic_set * bset)2090 __isl_give isl_basic_set *isl_basic_set_set_integral(
2091 	__isl_take isl_basic_set *bset)
2092 {
2093 	if (!bset)
2094 		return NULL;
2095 
2096 	if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2097 		return bset;
2098 
2099 	bset = isl_basic_set_cow(bset);
2100 	if (!bset)
2101 		return NULL;
2102 
2103 	ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2104 
2105 	return isl_basic_set_finalize(bset);
2106 }
2107 
isl_map_set_rational(__isl_take isl_map * map)2108 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2109 {
2110 	int i;
2111 
2112 	map = isl_map_cow(map);
2113 	if (!map)
2114 		return NULL;
2115 	for (i = 0; i < map->n; ++i) {
2116 		map->p[i] = isl_basic_map_set_rational(map->p[i]);
2117 		if (!map->p[i])
2118 			goto error;
2119 	}
2120 	return map;
2121 error:
2122 	isl_map_free(map);
2123 	return NULL;
2124 }
2125 
isl_set_set_rational(__isl_take isl_set * set)2126 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2127 {
2128 	return isl_map_set_rational(set);
2129 }
2130 
2131 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2132  * of "bmap").
2133  */
swap_div(__isl_keep isl_basic_map * bmap,int a,int b)2134 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2135 {
2136 	isl_int *t = bmap->div[a];
2137 	bmap->div[a] = bmap->div[b];
2138 	bmap->div[b] = t;
2139 }
2140 
2141 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2142  * div definitions accordingly.
2143  */
isl_basic_map_swap_div(struct isl_basic_map * bmap,int a,int b)2144 void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
2145 {
2146 	int i;
2147 	unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
2148 
2149 	swap_div(bmap, a, b);
2150 
2151 	for (i = 0; i < bmap->n_eq; ++i)
2152 		isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2153 
2154 	for (i = 0; i < bmap->n_ineq; ++i)
2155 		isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2156 
2157 	for (i = 0; i < bmap->n_div; ++i)
2158 		isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2159 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2160 }
2161 
2162 /* Swap divs "a" and "b" in "bset" and adjust the constraints and
2163  * div definitions accordingly.
2164  */
isl_basic_set_swap_div(__isl_keep isl_basic_set * bset,int a,int b)2165 void isl_basic_set_swap_div(__isl_keep isl_basic_set *bset, int a, int b)
2166 {
2167 	isl_basic_map_swap_div(bset, a, b);
2168 }
2169 
constraint_drop_vars(isl_int * c,unsigned n,unsigned rem)2170 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2171 {
2172 	isl_seq_cpy(c, c + n, rem);
2173 	isl_seq_clr(c + rem, n);
2174 }
2175 
2176 /* Drop n dimensions starting at first.
2177  *
2178  * In principle, this frees up some extra variables as the number
2179  * of columns remains constant, but we would have to extend
2180  * the div array too as the number of rows in this array is assumed
2181  * to be equal to extra.
2182  */
isl_basic_set_drop_dims(__isl_take isl_basic_set * bset,unsigned first,unsigned n)2183 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2184 	__isl_take isl_basic_set *bset, unsigned first, unsigned n)
2185 {
2186 	return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2187 }
2188 
2189 /* Move "n" divs starting at "first" to the end of the list of divs.
2190  */
move_divs_last(struct isl_basic_map * bmap,unsigned first,unsigned n)2191 static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
2192 	unsigned first, unsigned n)
2193 {
2194 	isl_int **div;
2195 	int i;
2196 
2197 	if (first + n == bmap->n_div)
2198 		return bmap;
2199 
2200 	div = isl_alloc_array(bmap->ctx, isl_int *, n);
2201 	if (!div)
2202 		goto error;
2203 	for (i = 0; i < n; ++i)
2204 		div[i] = bmap->div[first + i];
2205 	for (i = 0; i < bmap->n_div - first - n; ++i)
2206 		bmap->div[first + i] = bmap->div[first + n + i];
2207 	for (i = 0; i < n; ++i)
2208 		bmap->div[bmap->n_div - n + i] = div[i];
2209 	free(div);
2210 	return bmap;
2211 error:
2212 	isl_basic_map_free(bmap);
2213 	return NULL;
2214 }
2215 
2216 /* Check that there are "n" dimensions of type "type" starting at "first"
2217  * in "map".
2218  */
isl_map_check_range(__isl_keep isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2219 static isl_stat isl_map_check_range(__isl_keep isl_map *map,
2220 	enum isl_dim_type type, unsigned first, unsigned n)
2221 {
2222 	if (!map)
2223 		return isl_stat_error;
2224 	if (first + n > isl_map_dim(map, type) || first + n < first)
2225 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
2226 			"position or range out of bounds",
2227 			return isl_stat_error);
2228 	return isl_stat_ok;
2229 }
2230 
2231 /* Drop "n" dimensions of type "type" starting at "first".
2232  *
2233  * In principle, this frees up some extra variables as the number
2234  * of columns remains constant, but we would have to extend
2235  * the div array too as the number of rows in this array is assumed
2236  * to be equal to extra.
2237  */
isl_basic_map_drop(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2238 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2239 	enum isl_dim_type type, unsigned first, unsigned n)
2240 {
2241 	int i;
2242 	unsigned dim;
2243 	unsigned offset;
2244 	unsigned left;
2245 
2246 	if (!bmap)
2247 		goto error;
2248 
2249 	dim = isl_basic_map_dim(bmap, type);
2250 	isl_assert(bmap->ctx, first + n <= dim, goto error);
2251 
2252 	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2253 		return bmap;
2254 
2255 	bmap = isl_basic_map_cow(bmap);
2256 	if (!bmap)
2257 		return NULL;
2258 
2259 	offset = isl_basic_map_offset(bmap, type) + first;
2260 	left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
2261 	for (i = 0; i < bmap->n_eq; ++i)
2262 		constraint_drop_vars(bmap->eq[i]+offset, n, left);
2263 
2264 	for (i = 0; i < bmap->n_ineq; ++i)
2265 		constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2266 
2267 	for (i = 0; i < bmap->n_div; ++i)
2268 		constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2269 
2270 	if (type == isl_dim_div) {
2271 		bmap = move_divs_last(bmap, first, n);
2272 		if (!bmap)
2273 			goto error;
2274 		if (isl_basic_map_free_div(bmap, n) < 0)
2275 			return isl_basic_map_free(bmap);
2276 	} else
2277 		bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2278 	if (!bmap->dim)
2279 		goto error;
2280 
2281 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2282 	bmap = isl_basic_map_simplify(bmap);
2283 	return isl_basic_map_finalize(bmap);
2284 error:
2285 	isl_basic_map_free(bmap);
2286 	return NULL;
2287 }
2288 
isl_basic_set_drop(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2289 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2290 	enum isl_dim_type type, unsigned first, unsigned n)
2291 {
2292 	return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2293 							type, first, n));
2294 }
2295 
2296 /* No longer consider "map" to be normalized.
2297  */
isl_map_unmark_normalized(__isl_take isl_map * map)2298 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2299 {
2300 	if (!map)
2301 		return NULL;
2302 	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2303 	return map;
2304 }
2305 
isl_map_drop(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2306 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2307 	enum isl_dim_type type, unsigned first, unsigned n)
2308 {
2309 	int i;
2310 
2311 	if (isl_map_check_range(map, type, first, n) < 0)
2312 		return isl_map_free(map);
2313 
2314 	if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2315 		return map;
2316 	map = isl_map_cow(map);
2317 	if (!map)
2318 		goto error;
2319 	map->dim = isl_space_drop_dims(map->dim, type, first, n);
2320 	if (!map->dim)
2321 		goto error;
2322 
2323 	for (i = 0; i < map->n; ++i) {
2324 		map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2325 		if (!map->p[i])
2326 			goto error;
2327 	}
2328 	map = isl_map_unmark_normalized(map);
2329 
2330 	return map;
2331 error:
2332 	isl_map_free(map);
2333 	return NULL;
2334 }
2335 
isl_set_drop(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2336 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2337 	enum isl_dim_type type, unsigned first, unsigned n)
2338 {
2339 	return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2340 }
2341 
2342 /*
2343  * We don't cow, as the div is assumed to be redundant.
2344  */
isl_basic_map_drop_div(__isl_take isl_basic_map * bmap,unsigned div)2345 __isl_give isl_basic_map *isl_basic_map_drop_div(
2346 	__isl_take isl_basic_map *bmap, unsigned div)
2347 {
2348 	int i;
2349 	unsigned pos;
2350 
2351 	if (!bmap)
2352 		goto error;
2353 
2354 	pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
2355 
2356 	isl_assert(bmap->ctx, div < bmap->n_div, goto error);
2357 
2358 	for (i = 0; i < bmap->n_eq; ++i)
2359 		constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
2360 
2361 	for (i = 0; i < bmap->n_ineq; ++i) {
2362 		if (!isl_int_is_zero(bmap->ineq[i][pos])) {
2363 			isl_basic_map_drop_inequality(bmap, i);
2364 			--i;
2365 			continue;
2366 		}
2367 		constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
2368 	}
2369 
2370 	for (i = 0; i < bmap->n_div; ++i)
2371 		constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
2372 
2373 	if (div != bmap->n_div - 1) {
2374 		int j;
2375 		isl_int *t = bmap->div[div];
2376 
2377 		for (j = div; j < bmap->n_div - 1; ++j)
2378 			bmap->div[j] = bmap->div[j+1];
2379 
2380 		bmap->div[bmap->n_div - 1] = t;
2381 	}
2382 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2383 	if (isl_basic_map_free_div(bmap, 1) < 0)
2384 		return isl_basic_map_free(bmap);
2385 
2386 	return bmap;
2387 error:
2388 	isl_basic_map_free(bmap);
2389 	return NULL;
2390 }
2391 
2392 /* Eliminate the specified n dimensions starting at first from the
2393  * constraints, without removing the dimensions from the space.
2394  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2395  */
isl_map_eliminate(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2396 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2397 	enum isl_dim_type type, unsigned first, unsigned n)
2398 {
2399 	int i;
2400 
2401 	if (n == 0)
2402 		return map;
2403 
2404 	if (isl_map_check_range(map, type, first, n) < 0)
2405 		return isl_map_free(map);
2406 
2407 	map = isl_map_cow(map);
2408 	if (!map)
2409 		return NULL;
2410 
2411 	for (i = 0; i < map->n; ++i) {
2412 		map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2413 		if (!map->p[i])
2414 			goto error;
2415 	}
2416 	return map;
2417 error:
2418 	isl_map_free(map);
2419 	return NULL;
2420 }
2421 
2422 /* Eliminate the specified n dimensions starting at first from the
2423  * constraints, without removing the dimensions from the space.
2424  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2425  */
isl_set_eliminate(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2426 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2427 	enum isl_dim_type type, unsigned first, unsigned n)
2428 {
2429 	return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2430 }
2431 
2432 /* Eliminate the specified n dimensions starting at first from the
2433  * constraints, without removing the dimensions from the space.
2434  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2435  */
isl_set_eliminate_dims(__isl_take isl_set * set,unsigned first,unsigned n)2436 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2437 	unsigned first, unsigned n)
2438 {
2439 	return isl_set_eliminate(set, isl_dim_set, first, n);
2440 }
2441 
isl_basic_map_remove_divs(__isl_take isl_basic_map * bmap)2442 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2443 	__isl_take isl_basic_map *bmap)
2444 {
2445 	if (!bmap)
2446 		return NULL;
2447 	bmap = isl_basic_map_eliminate_vars(bmap,
2448 			    isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
2449 	if (!bmap)
2450 		return NULL;
2451 	bmap->n_div = 0;
2452 	return isl_basic_map_finalize(bmap);
2453 }
2454 
isl_basic_set_remove_divs(__isl_take isl_basic_set * bset)2455 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2456 	__isl_take isl_basic_set *bset)
2457 {
2458 	return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2459 }
2460 
isl_map_remove_divs(__isl_take isl_map * map)2461 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2462 {
2463 	int i;
2464 
2465 	if (!map)
2466 		return NULL;
2467 	if (map->n == 0)
2468 		return map;
2469 
2470 	map = isl_map_cow(map);
2471 	if (!map)
2472 		return NULL;
2473 
2474 	for (i = 0; i < map->n; ++i) {
2475 		map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2476 		if (!map->p[i])
2477 			goto error;
2478 	}
2479 	return map;
2480 error:
2481 	isl_map_free(map);
2482 	return NULL;
2483 }
2484 
isl_set_remove_divs(__isl_take isl_set * set)2485 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2486 {
2487 	return isl_map_remove_divs(set);
2488 }
2489 
isl_basic_map_remove_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2490 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2491 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
2492 	unsigned first, unsigned n)
2493 {
2494 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2495 		return isl_basic_map_free(bmap);
2496 	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2497 		return bmap;
2498 	bmap = isl_basic_map_eliminate_vars(bmap,
2499 			isl_basic_map_offset(bmap, type) - 1 + first, n);
2500 	if (!bmap)
2501 		return bmap;
2502 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2503 		return bmap;
2504 	bmap = isl_basic_map_drop(bmap, type, first, n);
2505 	return bmap;
2506 }
2507 
2508 /* Return true if the definition of the given div (recursively) involves
2509  * any of the given variables.
2510  */
div_involves_vars(__isl_keep isl_basic_map * bmap,int div,unsigned first,unsigned n)2511 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2512 	unsigned first, unsigned n)
2513 {
2514 	int i;
2515 	unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2516 
2517 	if (isl_int_is_zero(bmap->div[div][0]))
2518 		return isl_bool_false;
2519 	if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2520 		return isl_bool_true;
2521 
2522 	for (i = bmap->n_div - 1; i >= 0; --i) {
2523 		isl_bool involves;
2524 
2525 		if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2526 			continue;
2527 		involves = div_involves_vars(bmap, i, first, n);
2528 		if (involves < 0 || involves)
2529 			return involves;
2530 	}
2531 
2532 	return isl_bool_false;
2533 }
2534 
2535 /* Try and add a lower and/or upper bound on "div" to "bmap"
2536  * based on inequality "i".
2537  * "total" is the total number of variables (excluding the divs).
2538  * "v" is a temporary object that can be used during the calculations.
2539  * If "lb" is set, then a lower bound should be constructed.
2540  * If "ub" is set, then an upper bound should be constructed.
2541  *
2542  * The calling function has already checked that the inequality does not
2543  * reference "div", but we still need to check that the inequality is
2544  * of the right form.  We'll consider the case where we want to construct
2545  * a lower bound.  The construction of upper bounds is similar.
2546  *
2547  * Let "div" be of the form
2548  *
2549  *	q = floor((a + f(x))/d)
2550  *
2551  * We essentially check if constraint "i" is of the form
2552  *
2553  *	b + f(x) >= 0
2554  *
2555  * so that we can use it to derive a lower bound on "div".
2556  * However, we allow a slightly more general form
2557  *
2558  *	b + g(x) >= 0
2559  *
2560  * with the condition that the coefficients of g(x) - f(x) are all
2561  * divisible by d.
2562  * Rewriting this constraint as
2563  *
2564  *	0 >= -b - g(x)
2565  *
2566  * adding a + f(x) to both sides and dividing by d, we obtain
2567  *
2568  *	(a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2569  *
2570  * Taking the floor on both sides, we obtain
2571  *
2572  *	q >= floor((a-b)/d) + (f(x)-g(x))/d
2573  *
2574  * or
2575  *
2576  *	(g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2577  *
2578  * In the case of an upper bound, we construct the constraint
2579  *
2580  *	(g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2581  *
2582  */
insert_bounds_on_div_from_ineq(__isl_take isl_basic_map * bmap,int div,int i,unsigned total,isl_int v,int lb,int ub)2583 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2584 	__isl_take isl_basic_map *bmap, int div, int i,
2585 	unsigned total, isl_int v, int lb, int ub)
2586 {
2587 	int j;
2588 
2589 	for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2590 		if (lb) {
2591 			isl_int_sub(v, bmap->ineq[i][1 + j],
2592 					bmap->div[div][1 + 1 + j]);
2593 			lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2594 		}
2595 		if (ub) {
2596 			isl_int_add(v, bmap->ineq[i][1 + j],
2597 					bmap->div[div][1 + 1 + j]);
2598 			ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2599 		}
2600 	}
2601 	if (!lb && !ub)
2602 		return bmap;
2603 
2604 	bmap = isl_basic_map_cow(bmap);
2605 	bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2606 	if (lb) {
2607 		int k = isl_basic_map_alloc_inequality(bmap);
2608 		if (k < 0)
2609 			goto error;
2610 		for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2611 			isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2612 					bmap->div[div][1 + j]);
2613 			isl_int_cdiv_q(bmap->ineq[k][j],
2614 					bmap->ineq[k][j], bmap->div[div][0]);
2615 		}
2616 		isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2617 	}
2618 	if (ub) {
2619 		int k = isl_basic_map_alloc_inequality(bmap);
2620 		if (k < 0)
2621 			goto error;
2622 		for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2623 			isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2624 					bmap->div[div][1 + j]);
2625 			isl_int_fdiv_q(bmap->ineq[k][j],
2626 					bmap->ineq[k][j], bmap->div[div][0]);
2627 		}
2628 		isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2629 	}
2630 
2631 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2632 	return bmap;
2633 error:
2634 	isl_basic_map_free(bmap);
2635 	return NULL;
2636 }
2637 
2638 /* This function is called right before "div" is eliminated from "bmap"
2639  * using Fourier-Motzkin.
2640  * Look through the constraints of "bmap" for constraints on the argument
2641  * of the integer division and use them to construct constraints on the
2642  * integer division itself.  These constraints can then be combined
2643  * during the Fourier-Motzkin elimination.
2644  * Note that it is only useful to introduce lower bounds on "div"
2645  * if "bmap" already contains upper bounds on "div" as the newly
2646  * introduce lower bounds can then be combined with the pre-existing
2647  * upper bounds.  Similarly for upper bounds.
2648  * We therefore first check if "bmap" contains any lower and/or upper bounds
2649  * on "div".
2650  *
2651  * It is interesting to note that the introduction of these constraints
2652  * can indeed lead to more accurate results, even when compared to
2653  * deriving constraints on the argument of "div" from constraints on "div".
2654  * Consider, for example, the set
2655  *
2656  *	{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2657  *
2658  * The second constraint can be rewritten as
2659  *
2660  *	2 * [(-i-2j+3)/4] + k >= 0
2661  *
2662  * from which we can derive
2663  *
2664  *	-i - 2j + 3 >= -2k
2665  *
2666  * or
2667  *
2668  *	i + 2j <= 3 + 2k
2669  *
2670  * Combined with the first constraint, we obtain
2671  *
2672  *	-3 <= 3 + 2k	or	k >= -3
2673  *
2674  * If, on the other hand we derive a constraint on [(i+2j)/4] from
2675  * the first constraint, we obtain
2676  *
2677  *	[(i + 2j)/4] >= [-3/4] = -1
2678  *
2679  * Combining this constraint with the second constraint, we obtain
2680  *
2681  *	k >= -2
2682  */
insert_bounds_on_div(__isl_take isl_basic_map * bmap,int div)2683 static __isl_give isl_basic_map *insert_bounds_on_div(
2684 	__isl_take isl_basic_map *bmap, int div)
2685 {
2686 	int i;
2687 	int check_lb, check_ub;
2688 	isl_int v;
2689 	unsigned total;
2690 
2691 	if (!bmap)
2692 		return NULL;
2693 
2694 	if (isl_int_is_zero(bmap->div[div][0]))
2695 		return bmap;
2696 
2697 	total = isl_space_dim(bmap->dim, isl_dim_all);
2698 
2699 	check_lb = 0;
2700 	check_ub = 0;
2701 	for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2702 		int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2703 		if (s > 0)
2704 			check_ub = 1;
2705 		if (s < 0)
2706 			check_lb = 1;
2707 	}
2708 
2709 	if (!check_lb && !check_ub)
2710 		return bmap;
2711 
2712 	isl_int_init(v);
2713 
2714 	for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2715 		if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2716 			continue;
2717 
2718 		bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2719 							check_lb, check_ub);
2720 	}
2721 
2722 	isl_int_clear(v);
2723 
2724 	return bmap;
2725 }
2726 
2727 /* Remove all divs (recursively) involving any of the given dimensions
2728  * in their definitions.
2729  */
isl_basic_map_remove_divs_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2730 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2731 	__isl_take isl_basic_map *bmap,
2732 	enum isl_dim_type type, unsigned first, unsigned n)
2733 {
2734 	int i;
2735 
2736 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2737 		return isl_basic_map_free(bmap);
2738 	first += isl_basic_map_offset(bmap, type);
2739 
2740 	for (i = bmap->n_div - 1; i >= 0; --i) {
2741 		isl_bool involves;
2742 
2743 		involves = div_involves_vars(bmap, i, first, n);
2744 		if (involves < 0)
2745 			return isl_basic_map_free(bmap);
2746 		if (!involves)
2747 			continue;
2748 		bmap = insert_bounds_on_div(bmap, i);
2749 		bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2750 		if (!bmap)
2751 			return NULL;
2752 		i = bmap->n_div;
2753 	}
2754 
2755 	return bmap;
2756 }
2757 
isl_basic_set_remove_divs_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2758 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2759 	__isl_take isl_basic_set *bset,
2760 	enum isl_dim_type type, unsigned first, unsigned n)
2761 {
2762 	return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2763 }
2764 
isl_map_remove_divs_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2765 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2766 	enum isl_dim_type type, unsigned first, unsigned n)
2767 {
2768 	int i;
2769 
2770 	if (!map)
2771 		return NULL;
2772 	if (map->n == 0)
2773 		return map;
2774 
2775 	map = isl_map_cow(map);
2776 	if (!map)
2777 		return NULL;
2778 
2779 	for (i = 0; i < map->n; ++i) {
2780 		map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2781 								type, first, n);
2782 		if (!map->p[i])
2783 			goto error;
2784 	}
2785 	return map;
2786 error:
2787 	isl_map_free(map);
2788 	return NULL;
2789 }
2790 
isl_set_remove_divs_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2791 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2792 	enum isl_dim_type type, unsigned first, unsigned n)
2793 {
2794 	return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2795 							      type, first, n));
2796 }
2797 
2798 /* Does the description of "bmap" depend on the specified dimensions?
2799  * We also check whether the dimensions appear in any of the div definitions.
2800  * In principle there is no need for this check.  If the dimensions appear
2801  * in a div definition, they also appear in the defining constraints of that
2802  * div.
2803  */
isl_basic_map_involves_dims(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2804 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2805 	enum isl_dim_type type, unsigned first, unsigned n)
2806 {
2807 	int i;
2808 
2809 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2810 		return isl_bool_error;
2811 
2812 	first += isl_basic_map_offset(bmap, type);
2813 	for (i = 0; i < bmap->n_eq; ++i)
2814 		if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2815 			return isl_bool_true;
2816 	for (i = 0; i < bmap->n_ineq; ++i)
2817 		if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2818 			return isl_bool_true;
2819 	for (i = 0; i < bmap->n_div; ++i) {
2820 		if (isl_int_is_zero(bmap->div[i][0]))
2821 			continue;
2822 		if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2823 			return isl_bool_true;
2824 	}
2825 
2826 	return isl_bool_false;
2827 }
2828 
isl_map_involves_dims(__isl_keep isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2829 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2830 	enum isl_dim_type type, unsigned first, unsigned n)
2831 {
2832 	int i;
2833 
2834 	if (isl_map_check_range(map, type, first, n) < 0)
2835 		return isl_bool_error;
2836 
2837 	for (i = 0; i < map->n; ++i) {
2838 		isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2839 							    type, first, n);
2840 		if (involves < 0 || involves)
2841 			return involves;
2842 	}
2843 
2844 	return isl_bool_false;
2845 }
2846 
isl_basic_set_involves_dims(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2847 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2848 	enum isl_dim_type type, unsigned first, unsigned n)
2849 {
2850 	return isl_basic_map_involves_dims(bset, type, first, n);
2851 }
2852 
isl_set_involves_dims(__isl_keep isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2853 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2854 	enum isl_dim_type type, unsigned first, unsigned n)
2855 {
2856 	return isl_map_involves_dims(set, type, first, n);
2857 }
2858 
2859 /* Drop all constraints in bmap that involve any of the dimensions
2860  * first to first+n-1.
2861  */
isl_basic_map_drop_constraints_involving(__isl_take isl_basic_map * bmap,unsigned first,unsigned n)2862 static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2863 	__isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2864 {
2865 	int i;
2866 
2867 	if (n == 0)
2868 		return bmap;
2869 
2870 	bmap = isl_basic_map_cow(bmap);
2871 
2872 	if (!bmap)
2873 		return NULL;
2874 
2875 	for (i = bmap->n_eq - 1; i >= 0; --i) {
2876 		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2877 			continue;
2878 		isl_basic_map_drop_equality(bmap, i);
2879 	}
2880 
2881 	for (i = bmap->n_ineq - 1; i >= 0; --i) {
2882 		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2883 			continue;
2884 		isl_basic_map_drop_inequality(bmap, i);
2885 	}
2886 
2887 	bmap = isl_basic_map_add_known_div_constraints(bmap);
2888 	return bmap;
2889 }
2890 
2891 /* Drop all constraints in bset that involve any of the dimensions
2892  * first to first+n-1.
2893  */
isl_basic_set_drop_constraints_involving(__isl_take isl_basic_set * bset,unsigned first,unsigned n)2894 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2895 	__isl_take isl_basic_set *bset, unsigned first, unsigned n)
2896 {
2897 	return isl_basic_map_drop_constraints_involving(bset, first, n);
2898 }
2899 
2900 /* Drop all constraints in bmap that do not involve any of the dimensions
2901  * first to first + n - 1 of the given type.
2902  */
isl_basic_map_drop_constraints_not_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2903 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2904 	__isl_take isl_basic_map *bmap,
2905 	enum isl_dim_type type, unsigned first, unsigned n)
2906 {
2907 	int i;
2908 
2909 	if (n == 0) {
2910 		isl_space *space = isl_basic_map_get_space(bmap);
2911 		isl_basic_map_free(bmap);
2912 		return isl_basic_map_universe(space);
2913 	}
2914 	bmap = isl_basic_map_cow(bmap);
2915 	if (!bmap)
2916 		return NULL;
2917 
2918 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2919 		return isl_basic_map_free(bmap);
2920 
2921 	first += isl_basic_map_offset(bmap, type) - 1;
2922 
2923 	for (i = bmap->n_eq - 1; i >= 0; --i) {
2924 		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2925 			continue;
2926 		isl_basic_map_drop_equality(bmap, i);
2927 	}
2928 
2929 	for (i = bmap->n_ineq - 1; i >= 0; --i) {
2930 		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2931 			continue;
2932 		isl_basic_map_drop_inequality(bmap, i);
2933 	}
2934 
2935 	bmap = isl_basic_map_add_known_div_constraints(bmap);
2936 	return bmap;
2937 }
2938 
2939 /* Drop all constraints in bset that do not involve any of the dimensions
2940  * first to first + n - 1 of the given type.
2941  */
isl_basic_set_drop_constraints_not_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2942 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2943 	__isl_take isl_basic_set *bset,
2944 	enum isl_dim_type type, unsigned first, unsigned n)
2945 {
2946 	return isl_basic_map_drop_constraints_not_involving_dims(bset,
2947 							    type, first, n);
2948 }
2949 
2950 /* Drop all constraints in bmap that involve any of the dimensions
2951  * first to first + n - 1 of the given type.
2952  */
isl_basic_map_drop_constraints_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2953 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2954 	__isl_take isl_basic_map *bmap,
2955 	enum isl_dim_type type, unsigned first, unsigned n)
2956 {
2957 	if (!bmap)
2958 		return NULL;
2959 	if (n == 0)
2960 		return bmap;
2961 
2962 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2963 		return isl_basic_map_free(bmap);
2964 
2965 	bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2966 	first += isl_basic_map_offset(bmap, type) - 1;
2967 	return isl_basic_map_drop_constraints_involving(bmap, first, n);
2968 }
2969 
2970 /* Drop all constraints in bset that involve any of the dimensions
2971  * first to first + n - 1 of the given type.
2972  */
isl_basic_set_drop_constraints_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2973 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2974 	__isl_take isl_basic_set *bset,
2975 	enum isl_dim_type type, unsigned first, unsigned n)
2976 {
2977 	return isl_basic_map_drop_constraints_involving_dims(bset,
2978 							    type, first, n);
2979 }
2980 
2981 /* Drop constraints from "map" by applying "drop" to each basic map.
2982  */
drop_constraints(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n,__isl_give isl_basic_map * (* drop)(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n))2983 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2984 	enum isl_dim_type type, unsigned first, unsigned n,
2985 	__isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2986 		enum isl_dim_type type, unsigned first, unsigned n))
2987 {
2988 	int i;
2989 
2990 	if (isl_map_check_range(map, type, first, n) < 0)
2991 		return isl_map_free(map);
2992 
2993 	map = isl_map_cow(map);
2994 	if (!map)
2995 		return NULL;
2996 
2997 	for (i = 0; i < map->n; ++i) {
2998 		map->p[i] = drop(map->p[i], type, first, n);
2999 		if (!map->p[i])
3000 			return isl_map_free(map);
3001 	}
3002 
3003 	if (map->n > 1)
3004 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
3005 
3006 	return map;
3007 }
3008 
3009 /* Drop all constraints in map that involve any of the dimensions
3010  * first to first + n - 1 of the given type.
3011  */
isl_map_drop_constraints_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3012 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
3013 	__isl_take isl_map *map,
3014 	enum isl_dim_type type, unsigned first, unsigned n)
3015 {
3016 	if (n == 0)
3017 		return map;
3018 	return drop_constraints(map, type, first, n,
3019 				&isl_basic_map_drop_constraints_involving_dims);
3020 }
3021 
3022 /* Drop all constraints in "map" that do not involve any of the dimensions
3023  * first to first + n - 1 of the given type.
3024  */
isl_map_drop_constraints_not_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3025 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3026 	__isl_take isl_map *map,
3027 	enum isl_dim_type type, unsigned first, unsigned n)
3028 {
3029 	if (n == 0) {
3030 		isl_space *space = isl_map_get_space(map);
3031 		isl_map_free(map);
3032 		return isl_map_universe(space);
3033 	}
3034 	return drop_constraints(map, type, first, n,
3035 			    &isl_basic_map_drop_constraints_not_involving_dims);
3036 }
3037 
3038 /* Drop all constraints in set that involve any of the dimensions
3039  * first to first + n - 1 of the given type.
3040  */
isl_set_drop_constraints_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)3041 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3042 	__isl_take isl_set *set,
3043 	enum isl_dim_type type, unsigned first, unsigned n)
3044 {
3045 	return isl_map_drop_constraints_involving_dims(set, type, first, n);
3046 }
3047 
3048 /* Drop all constraints in "set" that do not involve any of the dimensions
3049  * first to first + n - 1 of the given type.
3050  */
isl_set_drop_constraints_not_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)3051 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3052 	__isl_take isl_set *set,
3053 	enum isl_dim_type type, unsigned first, unsigned n)
3054 {
3055 	return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3056 }
3057 
3058 /* Does local variable "div" of "bmap" have a complete explicit representation?
3059  * Having a complete explicit representation requires not only
3060  * an explicit representation, but also that all local variables
3061  * that appear in this explicit representation in turn have
3062  * a complete explicit representation.
3063  */
isl_basic_map_div_is_known(__isl_keep isl_basic_map * bmap,int div)3064 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3065 {
3066 	int i;
3067 	unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3068 	isl_bool marked;
3069 
3070 	marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3071 	if (marked < 0 || marked)
3072 		return isl_bool_not(marked);
3073 
3074 	for (i = bmap->n_div - 1; i >= 0; --i) {
3075 		isl_bool known;
3076 
3077 		if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3078 			continue;
3079 		known = isl_basic_map_div_is_known(bmap, i);
3080 		if (known < 0 || !known)
3081 			return known;
3082 	}
3083 
3084 	return isl_bool_true;
3085 }
3086 
3087 /* Remove all divs that are unknown or defined in terms of unknown divs.
3088  */
isl_basic_map_remove_unknown_divs(__isl_take isl_basic_map * bmap)3089 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3090 	__isl_take isl_basic_map *bmap)
3091 {
3092 	int i;
3093 
3094 	if (!bmap)
3095 		return NULL;
3096 
3097 	for (i = bmap->n_div - 1; i >= 0; --i) {
3098 		if (isl_basic_map_div_is_known(bmap, i))
3099 			continue;
3100 		bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3101 		if (!bmap)
3102 			return NULL;
3103 		i = bmap->n_div;
3104 	}
3105 
3106 	return bmap;
3107 }
3108 
3109 /* Remove all divs that are unknown or defined in terms of unknown divs.
3110  */
isl_basic_set_remove_unknown_divs(__isl_take isl_basic_set * bset)3111 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3112 	__isl_take isl_basic_set *bset)
3113 {
3114 	return isl_basic_map_remove_unknown_divs(bset);
3115 }
3116 
isl_map_remove_unknown_divs(__isl_take isl_map * map)3117 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3118 {
3119 	int i;
3120 
3121 	if (!map)
3122 		return NULL;
3123 	if (map->n == 0)
3124 		return map;
3125 
3126 	map = isl_map_cow(map);
3127 	if (!map)
3128 		return NULL;
3129 
3130 	for (i = 0; i < map->n; ++i) {
3131 		map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3132 		if (!map->p[i])
3133 			goto error;
3134 	}
3135 	return map;
3136 error:
3137 	isl_map_free(map);
3138 	return NULL;
3139 }
3140 
isl_set_remove_unknown_divs(__isl_take isl_set * set)3141 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3142 {
3143 	return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3144 }
3145 
isl_basic_set_remove_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3146 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3147 	__isl_take isl_basic_set *bset,
3148 	enum isl_dim_type type, unsigned first, unsigned n)
3149 {
3150 	isl_basic_map *bmap = bset_to_bmap(bset);
3151 	bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3152 	return bset_from_bmap(bmap);
3153 }
3154 
isl_map_remove_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3155 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3156 	enum isl_dim_type type, unsigned first, unsigned n)
3157 {
3158 	int i;
3159 
3160 	if (n == 0)
3161 		return map;
3162 
3163 	map = isl_map_cow(map);
3164 	if (isl_map_check_range(map, type, first, n) < 0)
3165 		return isl_map_free(map);
3166 
3167 	for (i = 0; i < map->n; ++i) {
3168 		map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3169 			isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3170 		if (!map->p[i])
3171 			goto error;
3172 	}
3173 	map = isl_map_drop(map, type, first, n);
3174 	return map;
3175 error:
3176 	isl_map_free(map);
3177 	return NULL;
3178 }
3179 
isl_set_remove_dims(__isl_take isl_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3180 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3181 	enum isl_dim_type type, unsigned first, unsigned n)
3182 {
3183 	return set_from_map(isl_map_remove_dims(set_to_map(bset),
3184 						type, first, n));
3185 }
3186 
3187 /* Project out n inputs starting at first using Fourier-Motzkin */
isl_map_remove_inputs(struct isl_map * map,unsigned first,unsigned n)3188 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
3189 	unsigned first, unsigned n)
3190 {
3191 	return isl_map_remove_dims(map, isl_dim_in, first, n);
3192 }
3193 
dump_term(struct isl_basic_map * bmap,isl_int c,int pos,FILE * out)3194 static void dump_term(struct isl_basic_map *bmap,
3195 			isl_int c, int pos, FILE *out)
3196 {
3197 	const char *name;
3198 	unsigned in = isl_basic_map_dim(bmap, isl_dim_in);
3199 	unsigned dim = in + isl_basic_map_dim(bmap, isl_dim_out);
3200 	unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
3201 	if (!pos)
3202 		isl_int_print(out, c, 0);
3203 	else {
3204 		if (!isl_int_is_one(c))
3205 			isl_int_print(out, c, 0);
3206 		if (pos < 1 + nparam) {
3207 			name = isl_space_get_dim_name(bmap->dim,
3208 						isl_dim_param, pos - 1);
3209 			if (name)
3210 				fprintf(out, "%s", name);
3211 			else
3212 				fprintf(out, "p%d", pos - 1);
3213 		} else if (pos < 1 + nparam + in)
3214 			fprintf(out, "i%d", pos - 1 - nparam);
3215 		else if (pos < 1 + nparam + dim)
3216 			fprintf(out, "o%d", pos - 1 - nparam - in);
3217 		else
3218 			fprintf(out, "e%d", pos - 1 - nparam - dim);
3219 	}
3220 }
3221 
dump_constraint_sign(struct isl_basic_map * bmap,isl_int * c,int sign,FILE * out)3222 static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
3223 				int sign, FILE *out)
3224 {
3225 	int i;
3226 	int first;
3227 	unsigned len = 1 + isl_basic_map_total_dim(bmap);
3228 	isl_int v;
3229 
3230 	isl_int_init(v);
3231 	for (i = 0, first = 1; i < len; ++i) {
3232 		if (isl_int_sgn(c[i]) * sign <= 0)
3233 			continue;
3234 		if (!first)
3235 			fprintf(out, " + ");
3236 		first = 0;
3237 		isl_int_abs(v, c[i]);
3238 		dump_term(bmap, v, i, out);
3239 	}
3240 	isl_int_clear(v);
3241 	if (first)
3242 		fprintf(out, "0");
3243 }
3244 
dump_constraint(struct isl_basic_map * bmap,isl_int * c,const char * op,FILE * out,int indent)3245 static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
3246 				const char *op, FILE *out, int indent)
3247 {
3248 	int i;
3249 
3250 	fprintf(out, "%*s", indent, "");
3251 
3252 	dump_constraint_sign(bmap, c, 1, out);
3253 	fprintf(out, " %s ", op);
3254 	dump_constraint_sign(bmap, c, -1, out);
3255 
3256 	fprintf(out, "\n");
3257 
3258 	for (i = bmap->n_div; i < bmap->extra; ++i) {
3259 		if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
3260 			continue;
3261 		fprintf(out, "%*s", indent, "");
3262 		fprintf(out, "ERROR: unused div coefficient not zero\n");
3263 		abort();
3264 	}
3265 }
3266 
dump_constraints(struct isl_basic_map * bmap,isl_int ** c,unsigned n,const char * op,FILE * out,int indent)3267 static void dump_constraints(struct isl_basic_map *bmap,
3268 				isl_int **c, unsigned n,
3269 				const char *op, FILE *out, int indent)
3270 {
3271 	int i;
3272 
3273 	for (i = 0; i < n; ++i)
3274 		dump_constraint(bmap, c[i], op, out, indent);
3275 }
3276 
dump_affine(struct isl_basic_map * bmap,isl_int * exp,FILE * out)3277 static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
3278 {
3279 	int j;
3280 	int first = 1;
3281 	unsigned total = isl_basic_map_total_dim(bmap);
3282 
3283 	for (j = 0; j < 1 + total; ++j) {
3284 		if (isl_int_is_zero(exp[j]))
3285 			continue;
3286 		if (!first && isl_int_is_pos(exp[j]))
3287 			fprintf(out, "+");
3288 		dump_term(bmap, exp[j], j, out);
3289 		first = 0;
3290 	}
3291 }
3292 
dump(struct isl_basic_map * bmap,FILE * out,int indent)3293 static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
3294 {
3295 	int i;
3296 
3297 	dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
3298 	dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
3299 
3300 	for (i = 0; i < bmap->n_div; ++i) {
3301 		fprintf(out, "%*s", indent, "");
3302 		fprintf(out, "e%d = [(", i);
3303 		dump_affine(bmap, bmap->div[i]+1, out);
3304 		fprintf(out, ")/");
3305 		isl_int_print(out, bmap->div[i][0], 0);
3306 		fprintf(out, "]\n");
3307 	}
3308 }
3309 
isl_basic_set_print_internal(struct isl_basic_set * bset,FILE * out,int indent)3310 void isl_basic_set_print_internal(struct isl_basic_set *bset,
3311 	FILE *out, int indent)
3312 {
3313 	if (!bset) {
3314 		fprintf(out, "null basic set\n");
3315 		return;
3316 	}
3317 
3318 	fprintf(out, "%*s", indent, "");
3319 	fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3320 			bset->ref, bset->dim->nparam, bset->dim->n_out,
3321 			bset->extra, bset->flags);
3322 	dump(bset_to_bmap(bset), out, indent);
3323 }
3324 
isl_basic_map_print_internal(struct isl_basic_map * bmap,FILE * out,int indent)3325 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
3326 	FILE *out, int indent)
3327 {
3328 	if (!bmap) {
3329 		fprintf(out, "null basic map\n");
3330 		return;
3331 	}
3332 
3333 	fprintf(out, "%*s", indent, "");
3334 	fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3335 			"flags: %x, n_name: %d\n",
3336 		bmap->ref,
3337 		bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3338 		bmap->extra, bmap->flags, bmap->dim->n_id);
3339 	dump(bmap, out, indent);
3340 }
3341 
isl_inequality_negate(struct isl_basic_map * bmap,unsigned pos)3342 int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
3343 {
3344 	unsigned total;
3345 	if (!bmap)
3346 		return -1;
3347 	total = isl_basic_map_total_dim(bmap);
3348 	isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
3349 	isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3350 	isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3351 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
3352 	return 0;
3353 }
3354 
isl_set_alloc_space(__isl_take isl_space * space,int n,unsigned flags)3355 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3356 	unsigned flags)
3357 {
3358 	if (!space)
3359 		return NULL;
3360 	if (isl_space_dim(space, isl_dim_in) != 0)
3361 		isl_die(isl_space_get_ctx(space), isl_error_invalid,
3362 			"set cannot have input dimensions", goto error);
3363 	return isl_map_alloc_space(space, n, flags);
3364 error:
3365 	isl_space_free(space);
3366 	return NULL;
3367 }
3368 
3369 /* Make sure "map" has room for at least "n" more basic maps.
3370  */
isl_map_grow(__isl_take isl_map * map,int n)3371 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3372 {
3373 	int i;
3374 	struct isl_map *grown = NULL;
3375 
3376 	if (!map)
3377 		return NULL;
3378 	isl_assert(map->ctx, n >= 0, goto error);
3379 	if (map->n + n <= map->size)
3380 		return map;
3381 	grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3382 	if (!grown)
3383 		goto error;
3384 	for (i = 0; i < map->n; ++i) {
3385 		grown->p[i] = isl_basic_map_copy(map->p[i]);
3386 		if (!grown->p[i])
3387 			goto error;
3388 		grown->n++;
3389 	}
3390 	isl_map_free(map);
3391 	return grown;
3392 error:
3393 	isl_map_free(grown);
3394 	isl_map_free(map);
3395 	return NULL;
3396 }
3397 
3398 /* Make sure "set" has room for at least "n" more basic sets.
3399  */
isl_set_grow(struct isl_set * set,int n)3400 struct isl_set *isl_set_grow(struct isl_set *set, int n)
3401 {
3402 	return set_from_map(isl_map_grow(set_to_map(set), n));
3403 }
3404 
isl_set_from_basic_set(__isl_take isl_basic_set * bset)3405 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3406 {
3407 	return isl_map_from_basic_map(bset);
3408 }
3409 
isl_map_from_basic_map(__isl_take isl_basic_map * bmap)3410 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3411 {
3412 	struct isl_map *map;
3413 
3414 	if (!bmap)
3415 		return NULL;
3416 
3417 	map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3418 	return isl_map_add_basic_map(map, bmap);
3419 }
3420 
isl_set_add_basic_set(__isl_take isl_set * set,__isl_take isl_basic_set * bset)3421 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3422 						__isl_take isl_basic_set *bset)
3423 {
3424 	return set_from_map(isl_map_add_basic_map(set_to_map(set),
3425 						bset_to_bmap(bset)));
3426 }
3427 
isl_set_free(__isl_take isl_set * set)3428 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3429 {
3430 	return isl_map_free(set);
3431 }
3432 
isl_set_print_internal(struct isl_set * set,FILE * out,int indent)3433 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3434 {
3435 	int i;
3436 
3437 	if (!set) {
3438 		fprintf(out, "null set\n");
3439 		return;
3440 	}
3441 
3442 	fprintf(out, "%*s", indent, "");
3443 	fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3444 			set->ref, set->n, set->dim->nparam, set->dim->n_out,
3445 			set->flags);
3446 	for (i = 0; i < set->n; ++i) {
3447 		fprintf(out, "%*s", indent, "");
3448 		fprintf(out, "basic set %d:\n", i);
3449 		isl_basic_set_print_internal(set->p[i], out, indent+4);
3450 	}
3451 }
3452 
isl_map_print_internal(struct isl_map * map,FILE * out,int indent)3453 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3454 {
3455 	int i;
3456 
3457 	if (!map) {
3458 		fprintf(out, "null map\n");
3459 		return;
3460 	}
3461 
3462 	fprintf(out, "%*s", indent, "");
3463 	fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3464 		     "flags: %x, n_name: %d\n",
3465 			map->ref, map->n, map->dim->nparam, map->dim->n_in,
3466 			map->dim->n_out, map->flags, map->dim->n_id);
3467 	for (i = 0; i < map->n; ++i) {
3468 		fprintf(out, "%*s", indent, "");
3469 		fprintf(out, "basic map %d:\n", i);
3470 		isl_basic_map_print_internal(map->p[i], out, indent+4);
3471 	}
3472 }
3473 
isl_basic_map_intersect_domain(__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset)3474 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3475 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3476 {
3477 	struct isl_basic_map *bmap_domain;
3478 
3479 	if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3480 		goto error;
3481 
3482 	if (isl_space_dim(bset->dim, isl_dim_set) != 0)
3483 		isl_assert(bset->ctx,
3484 		    isl_basic_map_compatible_domain(bmap, bset), goto error);
3485 
3486 	bmap = isl_basic_map_cow(bmap);
3487 	if (!bmap)
3488 		goto error;
3489 	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3490 			bset->n_div, bset->n_eq, bset->n_ineq);
3491 	bmap_domain = isl_basic_map_from_domain(bset);
3492 	bmap = add_constraints(bmap, bmap_domain, 0, 0);
3493 
3494 	bmap = isl_basic_map_simplify(bmap);
3495 	return isl_basic_map_finalize(bmap);
3496 error:
3497 	isl_basic_map_free(bmap);
3498 	isl_basic_set_free(bset);
3499 	return NULL;
3500 }
3501 
3502 /* Check that the space of "bset" is the same as that of the range of "bmap".
3503  */
isl_basic_map_check_compatible_range(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)3504 static isl_stat isl_basic_map_check_compatible_range(
3505 	__isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3506 {
3507 	isl_bool ok;
3508 
3509 	ok = isl_basic_map_compatible_range(bmap, bset);
3510 	if (ok < 0)
3511 		return isl_stat_error;
3512 	if (!ok)
3513 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3514 			"incompatible spaces", return isl_stat_error);
3515 
3516 	return isl_stat_ok;
3517 }
3518 
isl_basic_map_intersect_range(__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset)3519 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3520 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3521 {
3522 	struct isl_basic_map *bmap_range;
3523 
3524 	if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3525 		goto error;
3526 
3527 	if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
3528 	    isl_basic_map_check_compatible_range(bmap, bset) < 0)
3529 		goto error;
3530 
3531 	if (isl_basic_set_plain_is_universe(bset)) {
3532 		isl_basic_set_free(bset);
3533 		return bmap;
3534 	}
3535 
3536 	bmap = isl_basic_map_cow(bmap);
3537 	if (!bmap)
3538 		goto error;
3539 	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3540 			bset->n_div, bset->n_eq, bset->n_ineq);
3541 	bmap_range = bset_to_bmap(bset);
3542 	bmap = add_constraints(bmap, bmap_range, 0, 0);
3543 
3544 	bmap = isl_basic_map_simplify(bmap);
3545 	return isl_basic_map_finalize(bmap);
3546 error:
3547 	isl_basic_map_free(bmap);
3548 	isl_basic_set_free(bset);
3549 	return NULL;
3550 }
3551 
isl_basic_map_contains(__isl_keep isl_basic_map * bmap,__isl_keep isl_vec * vec)3552 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3553 	__isl_keep isl_vec *vec)
3554 {
3555 	int i;
3556 	unsigned total;
3557 	isl_int s;
3558 
3559 	if (!bmap || !vec)
3560 		return isl_bool_error;
3561 
3562 	total = 1 + isl_basic_map_total_dim(bmap);
3563 	if (total != vec->size)
3564 		return isl_bool_false;
3565 
3566 	isl_int_init(s);
3567 
3568 	for (i = 0; i < bmap->n_eq; ++i) {
3569 		isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3570 		if (!isl_int_is_zero(s)) {
3571 			isl_int_clear(s);
3572 			return isl_bool_false;
3573 		}
3574 	}
3575 
3576 	for (i = 0; i < bmap->n_ineq; ++i) {
3577 		isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3578 		if (isl_int_is_neg(s)) {
3579 			isl_int_clear(s);
3580 			return isl_bool_false;
3581 		}
3582 	}
3583 
3584 	isl_int_clear(s);
3585 
3586 	return isl_bool_true;
3587 }
3588 
isl_basic_set_contains(__isl_keep isl_basic_set * bset,__isl_keep isl_vec * vec)3589 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3590 	__isl_keep isl_vec *vec)
3591 {
3592 	return isl_basic_map_contains(bset_to_bmap(bset), vec);
3593 }
3594 
isl_basic_map_intersect(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)3595 __isl_give isl_basic_map *isl_basic_map_intersect(
3596 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3597 {
3598 	struct isl_vec *sample = NULL;
3599 
3600 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3601 		goto error;
3602 	if (isl_space_dim(bmap1->dim, isl_dim_all) ==
3603 				isl_space_dim(bmap1->dim, isl_dim_param) &&
3604 	    isl_space_dim(bmap2->dim, isl_dim_all) !=
3605 				isl_space_dim(bmap2->dim, isl_dim_param))
3606 		return isl_basic_map_intersect(bmap2, bmap1);
3607 
3608 	if (isl_space_dim(bmap2->dim, isl_dim_all) !=
3609 					isl_space_dim(bmap2->dim, isl_dim_param))
3610 		isl_assert(bmap1->ctx,
3611 			    isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3612 
3613 	if (isl_basic_map_plain_is_empty(bmap1)) {
3614 		isl_basic_map_free(bmap2);
3615 		return bmap1;
3616 	}
3617 	if (isl_basic_map_plain_is_empty(bmap2)) {
3618 		isl_basic_map_free(bmap1);
3619 		return bmap2;
3620 	}
3621 
3622 	if (bmap1->sample &&
3623 	    isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3624 	    isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3625 		sample = isl_vec_copy(bmap1->sample);
3626 	else if (bmap2->sample &&
3627 	    isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3628 	    isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3629 		sample = isl_vec_copy(bmap2->sample);
3630 
3631 	bmap1 = isl_basic_map_cow(bmap1);
3632 	if (!bmap1)
3633 		goto error;
3634 	bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3635 			bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3636 	bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3637 
3638 	if (!bmap1)
3639 		isl_vec_free(sample);
3640 	else if (sample) {
3641 		isl_vec_free(bmap1->sample);
3642 		bmap1->sample = sample;
3643 	}
3644 
3645 	bmap1 = isl_basic_map_simplify(bmap1);
3646 	return isl_basic_map_finalize(bmap1);
3647 error:
3648 	if (sample)
3649 		isl_vec_free(sample);
3650 	isl_basic_map_free(bmap1);
3651 	isl_basic_map_free(bmap2);
3652 	return NULL;
3653 }
3654 
isl_basic_set_intersect(struct isl_basic_set * bset1,struct isl_basic_set * bset2)3655 struct isl_basic_set *isl_basic_set_intersect(
3656 		struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3657 {
3658 	return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3659 							bset_to_bmap(bset2)));
3660 }
3661 
isl_basic_set_intersect_params(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)3662 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3663 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3664 {
3665 	return isl_basic_set_intersect(bset1, bset2);
3666 }
3667 
3668 /* Special case of isl_map_intersect, where both map1 and map2
3669  * are convex, without any divs and such that either map1 or map2
3670  * contains a single constraint.  This constraint is then simply
3671  * added to the other map.
3672  */
map_intersect_add_constraint(__isl_take isl_map * map1,__isl_take isl_map * map2)3673 static __isl_give isl_map *map_intersect_add_constraint(
3674 	__isl_take isl_map *map1, __isl_take isl_map *map2)
3675 {
3676 	isl_assert(map1->ctx, map1->n == 1, goto error);
3677 	isl_assert(map2->ctx, map1->n == 1, goto error);
3678 	isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3679 	isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3680 
3681 	if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3682 		return isl_map_intersect(map2, map1);
3683 
3684 	map1 = isl_map_cow(map1);
3685 	if (!map1)
3686 		goto error;
3687 	if (isl_map_plain_is_empty(map1)) {
3688 		isl_map_free(map2);
3689 		return map1;
3690 	}
3691 	map1->p[0] = isl_basic_map_cow(map1->p[0]);
3692 	if (map2->p[0]->n_eq == 1)
3693 		map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3694 	else
3695 		map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3696 							map2->p[0]->ineq[0]);
3697 
3698 	map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3699 	map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3700 	if (!map1->p[0])
3701 		goto error;
3702 
3703 	if (isl_basic_map_plain_is_empty(map1->p[0])) {
3704 		isl_basic_map_free(map1->p[0]);
3705 		map1->n = 0;
3706 	}
3707 
3708 	isl_map_free(map2);
3709 
3710 	map1 = isl_map_unmark_normalized(map1);
3711 	return map1;
3712 error:
3713 	isl_map_free(map1);
3714 	isl_map_free(map2);
3715 	return NULL;
3716 }
3717 
3718 /* map2 may be either a parameter domain or a map living in the same
3719  * space as map1.
3720  */
map_intersect_internal(__isl_take isl_map * map1,__isl_take isl_map * map2)3721 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3722 	__isl_take isl_map *map2)
3723 {
3724 	unsigned flags = 0;
3725 	isl_bool equal;
3726 	isl_map *result;
3727 	int i, j;
3728 
3729 	if (!map1 || !map2)
3730 		goto error;
3731 
3732 	if ((isl_map_plain_is_empty(map1) ||
3733 	     isl_map_plain_is_universe(map2)) &&
3734 	    isl_space_is_equal(map1->dim, map2->dim)) {
3735 		isl_map_free(map2);
3736 		return map1;
3737 	}
3738 	if ((isl_map_plain_is_empty(map2) ||
3739 	     isl_map_plain_is_universe(map1)) &&
3740 	    isl_space_is_equal(map1->dim, map2->dim)) {
3741 		isl_map_free(map1);
3742 		return map2;
3743 	}
3744 
3745 	if (map1->n == 1 && map2->n == 1 &&
3746 	    map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3747 	    isl_space_is_equal(map1->dim, map2->dim) &&
3748 	    (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3749 	     map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3750 		return map_intersect_add_constraint(map1, map2);
3751 
3752 	equal = isl_map_plain_is_equal(map1, map2);
3753 	if (equal < 0)
3754 		goto error;
3755 	if (equal) {
3756 		isl_map_free(map2);
3757 		return map1;
3758 	}
3759 
3760 	if (isl_space_dim(map2->dim, isl_dim_all) !=
3761 				isl_space_dim(map2->dim, isl_dim_param))
3762 		isl_assert(map1->ctx,
3763 			    isl_space_is_equal(map1->dim, map2->dim), goto error);
3764 
3765 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3766 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3767 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3768 
3769 	result = isl_map_alloc_space(isl_space_copy(map1->dim),
3770 				map1->n * map2->n, flags);
3771 	if (!result)
3772 		goto error;
3773 	for (i = 0; i < map1->n; ++i)
3774 		for (j = 0; j < map2->n; ++j) {
3775 			struct isl_basic_map *part;
3776 			part = isl_basic_map_intersect(
3777 				    isl_basic_map_copy(map1->p[i]),
3778 				    isl_basic_map_copy(map2->p[j]));
3779 			if (isl_basic_map_is_empty(part) < 0)
3780 				part = isl_basic_map_free(part);
3781 			result = isl_map_add_basic_map(result, part);
3782 			if (!result)
3783 				goto error;
3784 		}
3785 	isl_map_free(map1);
3786 	isl_map_free(map2);
3787 	return result;
3788 error:
3789 	isl_map_free(map1);
3790 	isl_map_free(map2);
3791 	return NULL;
3792 }
3793 
map_intersect(__isl_take isl_map * map1,__isl_take isl_map * map2)3794 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3795 	__isl_take isl_map *map2)
3796 {
3797 	if (!map1 || !map2)
3798 		goto error;
3799 	if (!isl_space_is_equal(map1->dim, map2->dim))
3800 		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3801 			"spaces don't match", goto error);
3802 	return map_intersect_internal(map1, map2);
3803 error:
3804 	isl_map_free(map1);
3805 	isl_map_free(map2);
3806 	return NULL;
3807 }
3808 
isl_map_intersect(__isl_take isl_map * map1,__isl_take isl_map * map2)3809 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3810 	__isl_take isl_map *map2)
3811 {
3812 	return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3813 }
3814 
isl_set_intersect(struct isl_set * set1,struct isl_set * set2)3815 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3816 {
3817 	return set_from_map(isl_map_intersect(set_to_map(set1),
3818 					      set_to_map(set2)));
3819 }
3820 
3821 /* map_intersect_internal accepts intersections
3822  * with parameter domains, so we can just call that function.
3823  */
map_intersect_params(__isl_take isl_map * map,__isl_take isl_set * params)3824 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3825 		__isl_take isl_set *params)
3826 {
3827 	return map_intersect_internal(map, params);
3828 }
3829 
isl_map_intersect_params(__isl_take isl_map * map1,__isl_take isl_map * map2)3830 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3831 	__isl_take isl_map *map2)
3832 {
3833 	return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3834 }
3835 
isl_set_intersect_params(__isl_take isl_set * set,__isl_take isl_set * params)3836 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3837 		__isl_take isl_set *params)
3838 {
3839 	return isl_map_intersect_params(set, params);
3840 }
3841 
isl_basic_map_reverse(__isl_take isl_basic_map * bmap)3842 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3843 {
3844 	isl_space *space;
3845 	unsigned pos, n1, n2;
3846 
3847 	if (!bmap)
3848 		return NULL;
3849 	bmap = isl_basic_map_cow(bmap);
3850 	if (!bmap)
3851 		return NULL;
3852 	space = isl_space_reverse(isl_space_copy(bmap->dim));
3853 	pos = isl_basic_map_offset(bmap, isl_dim_in);
3854 	n1 = isl_basic_map_dim(bmap, isl_dim_in);
3855 	n2 = isl_basic_map_dim(bmap, isl_dim_out);
3856 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3857 	return isl_basic_map_reset_space(bmap, space);
3858 }
3859 
basic_map_space_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)3860 static __isl_give isl_basic_map *basic_map_space_reset(
3861 	__isl_take isl_basic_map *bmap, enum isl_dim_type type)
3862 {
3863 	isl_space *space;
3864 
3865 	if (!bmap)
3866 		return NULL;
3867 	if (!isl_space_is_named_or_nested(bmap->dim, type))
3868 		return bmap;
3869 
3870 	space = isl_basic_map_get_space(bmap);
3871 	space = isl_space_reset(space, type);
3872 	bmap = isl_basic_map_reset_space(bmap, space);
3873 	return bmap;
3874 }
3875 
isl_basic_map_insert_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,unsigned n)3876 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3877 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
3878 	unsigned pos, unsigned n)
3879 {
3880 	isl_bool rational;
3881 	isl_space *res_space;
3882 	struct isl_basic_map *res;
3883 	struct isl_dim_map *dim_map;
3884 	unsigned total, off;
3885 	enum isl_dim_type t;
3886 
3887 	if (n == 0)
3888 		return basic_map_space_reset(bmap, type);
3889 
3890 	res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3891 					type, pos, n);
3892 	if (!res_space)
3893 		return isl_basic_map_free(bmap);
3894 
3895 	total = isl_basic_map_total_dim(bmap) + n;
3896 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
3897 	off = 0;
3898 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3899 		if (t != type) {
3900 			isl_dim_map_dim(dim_map, bmap->dim, t, off);
3901 		} else {
3902 			unsigned size = isl_basic_map_dim(bmap, t);
3903 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3904 						0, pos, off);
3905 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3906 						pos, size - pos, off + pos + n);
3907 		}
3908 		off += isl_space_dim(res_space, t);
3909 	}
3910 	isl_dim_map_div(dim_map, bmap, off);
3911 
3912 	res = isl_basic_map_alloc_space(res_space,
3913 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
3914 	rational = isl_basic_map_is_rational(bmap);
3915 	if (rational < 0)
3916 		res = isl_basic_map_free(res);
3917 	if (rational)
3918 		res = isl_basic_map_set_rational(res);
3919 	if (isl_basic_map_plain_is_empty(bmap)) {
3920 		isl_basic_map_free(bmap);
3921 		free(dim_map);
3922 		return isl_basic_map_set_to_empty(res);
3923 	}
3924 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3925 	return isl_basic_map_finalize(res);
3926 }
3927 
isl_basic_set_insert_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,unsigned n)3928 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3929 	__isl_take isl_basic_set *bset,
3930 	enum isl_dim_type type, unsigned pos, unsigned n)
3931 {
3932 	return isl_basic_map_insert_dims(bset, type, pos, n);
3933 }
3934 
isl_basic_map_add_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned n)3935 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3936 		enum isl_dim_type type, unsigned n)
3937 {
3938 	if (!bmap)
3939 		return NULL;
3940 	return isl_basic_map_insert_dims(bmap, type,
3941 					isl_basic_map_dim(bmap, type), n);
3942 }
3943 
isl_basic_set_add_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned n)3944 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3945 		enum isl_dim_type type, unsigned n)
3946 {
3947 	if (!bset)
3948 		return NULL;
3949 	isl_assert(bset->ctx, type != isl_dim_in, goto error);
3950 	return isl_basic_map_add_dims(bset, type, n);
3951 error:
3952 	isl_basic_set_free(bset);
3953 	return NULL;
3954 }
3955 
map_space_reset(__isl_take isl_map * map,enum isl_dim_type type)3956 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3957 	enum isl_dim_type type)
3958 {
3959 	isl_space *space;
3960 
3961 	if (!map || !isl_space_is_named_or_nested(map->dim, type))
3962 		return map;
3963 
3964 	space = isl_map_get_space(map);
3965 	space = isl_space_reset(space, type);
3966 	map = isl_map_reset_space(map, space);
3967 	return map;
3968 }
3969 
isl_map_insert_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,unsigned n)3970 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3971 		enum isl_dim_type type, unsigned pos, unsigned n)
3972 {
3973 	int i;
3974 
3975 	if (n == 0)
3976 		return map_space_reset(map, type);
3977 
3978 	map = isl_map_cow(map);
3979 	if (!map)
3980 		return NULL;
3981 
3982 	map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3983 	if (!map->dim)
3984 		goto error;
3985 
3986 	for (i = 0; i < map->n; ++i) {
3987 		map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3988 		if (!map->p[i])
3989 			goto error;
3990 	}
3991 
3992 	return map;
3993 error:
3994 	isl_map_free(map);
3995 	return NULL;
3996 }
3997 
isl_set_insert_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,unsigned n)3998 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3999 		enum isl_dim_type type, unsigned pos, unsigned n)
4000 {
4001 	return isl_map_insert_dims(set, type, pos, n);
4002 }
4003 
isl_map_add_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned n)4004 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
4005 		enum isl_dim_type type, unsigned n)
4006 {
4007 	if (!map)
4008 		return NULL;
4009 	return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
4010 }
4011 
isl_set_add_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned n)4012 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
4013 		enum isl_dim_type type, unsigned n)
4014 {
4015 	if (!set)
4016 		return NULL;
4017 	isl_assert(set->ctx, type != isl_dim_in, goto error);
4018 	return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
4019 error:
4020 	isl_set_free(set);
4021 	return NULL;
4022 }
4023 
isl_basic_map_move_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type dst_type,unsigned dst_pos,enum isl_dim_type src_type,unsigned src_pos,unsigned n)4024 __isl_give isl_basic_map *isl_basic_map_move_dims(
4025 	__isl_take isl_basic_map *bmap,
4026 	enum isl_dim_type dst_type, unsigned dst_pos,
4027 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4028 {
4029 	struct isl_dim_map *dim_map;
4030 	struct isl_basic_map *res;
4031 	enum isl_dim_type t;
4032 	unsigned total, off;
4033 
4034 	if (!bmap)
4035 		return NULL;
4036 	if (n == 0) {
4037 		bmap = isl_basic_map_reset(bmap, src_type);
4038 		bmap = isl_basic_map_reset(bmap, dst_type);
4039 		return bmap;
4040 	}
4041 
4042 	if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
4043 		return isl_basic_map_free(bmap);
4044 
4045 	if (dst_type == src_type && dst_pos == src_pos)
4046 		return bmap;
4047 
4048 	isl_assert(bmap->ctx, dst_type != src_type, goto error);
4049 
4050 	if (pos(bmap->dim, dst_type) + dst_pos ==
4051 	    pos(bmap->dim, src_type) + src_pos +
4052 					    ((src_type < dst_type) ? n : 0)) {
4053 		bmap = isl_basic_map_cow(bmap);
4054 		if (!bmap)
4055 			return NULL;
4056 
4057 		bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4058 						src_type, src_pos, n);
4059 		if (!bmap->dim)
4060 			goto error;
4061 
4062 		bmap = isl_basic_map_finalize(bmap);
4063 
4064 		return bmap;
4065 	}
4066 
4067 	total = isl_basic_map_total_dim(bmap);
4068 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
4069 
4070 	off = 0;
4071 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4072 		unsigned size = isl_space_dim(bmap->dim, t);
4073 		if (t == dst_type) {
4074 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4075 					    0, dst_pos, off);
4076 			off += dst_pos;
4077 			isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
4078 					    src_pos, n, off);
4079 			off += n;
4080 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4081 					    dst_pos, size - dst_pos, off);
4082 			off += size - dst_pos;
4083 		} else if (t == src_type) {
4084 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4085 					    0, src_pos, off);
4086 			off += src_pos;
4087 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4088 					src_pos + n, size - src_pos - n, off);
4089 			off += size - src_pos - n;
4090 		} else {
4091 			isl_dim_map_dim(dim_map, bmap->dim, t, off);
4092 			off += size;
4093 		}
4094 	}
4095 	isl_dim_map_div(dim_map, bmap, off);
4096 
4097 	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4098 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
4099 	bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4100 	if (!bmap)
4101 		goto error;
4102 
4103 	bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4104 					src_type, src_pos, n);
4105 	if (!bmap->dim)
4106 		goto error;
4107 
4108 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
4109 	bmap = isl_basic_map_gauss(bmap, NULL);
4110 	bmap = isl_basic_map_finalize(bmap);
4111 
4112 	return bmap;
4113 error:
4114 	isl_basic_map_free(bmap);
4115 	return NULL;
4116 }
4117 
isl_basic_set_move_dims(__isl_take isl_basic_set * bset,enum isl_dim_type dst_type,unsigned dst_pos,enum isl_dim_type src_type,unsigned src_pos,unsigned n)4118 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4119 	enum isl_dim_type dst_type, unsigned dst_pos,
4120 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4121 {
4122 	isl_basic_map *bmap = bset_to_bmap(bset);
4123 	bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4124 					src_type, src_pos, n);
4125 	return bset_from_bmap(bmap);
4126 }
4127 
isl_set_move_dims(__isl_take isl_set * set,enum isl_dim_type dst_type,unsigned dst_pos,enum isl_dim_type src_type,unsigned src_pos,unsigned n)4128 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4129 	enum isl_dim_type dst_type, unsigned dst_pos,
4130 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4131 {
4132 	if (!set)
4133 		return NULL;
4134 	isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4135 	return set_from_map(isl_map_move_dims(set_to_map(set),
4136 				    dst_type, dst_pos, src_type, src_pos, n));
4137 error:
4138 	isl_set_free(set);
4139 	return NULL;
4140 }
4141 
isl_map_move_dims(__isl_take isl_map * map,enum isl_dim_type dst_type,unsigned dst_pos,enum isl_dim_type src_type,unsigned src_pos,unsigned n)4142 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4143 	enum isl_dim_type dst_type, unsigned dst_pos,
4144 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4145 {
4146 	int i;
4147 
4148 	if (n == 0) {
4149 		map = isl_map_reset(map, src_type);
4150 		map = isl_map_reset(map, dst_type);
4151 		return map;
4152 	}
4153 
4154 	if (isl_map_check_range(map, src_type, src_pos, n))
4155 		return isl_map_free(map);
4156 
4157 	if (dst_type == src_type && dst_pos == src_pos)
4158 		return map;
4159 
4160 	isl_assert(map->ctx, dst_type != src_type, goto error);
4161 
4162 	map = isl_map_cow(map);
4163 	if (!map)
4164 		return NULL;
4165 
4166 	map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
4167 	if (!map->dim)
4168 		goto error;
4169 
4170 	for (i = 0; i < map->n; ++i) {
4171 		map->p[i] = isl_basic_map_move_dims(map->p[i],
4172 						dst_type, dst_pos,
4173 						src_type, src_pos, n);
4174 		if (!map->p[i])
4175 			goto error;
4176 	}
4177 
4178 	return map;
4179 error:
4180 	isl_map_free(map);
4181 	return NULL;
4182 }
4183 
4184 /* Move the specified dimensions to the last columns right before
4185  * the divs.  Don't change the dimension specification of bmap.
4186  * That's the responsibility of the caller.
4187  */
move_last(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4188 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4189 	enum isl_dim_type type, unsigned first, unsigned n)
4190 {
4191 	struct isl_dim_map *dim_map;
4192 	struct isl_basic_map *res;
4193 	enum isl_dim_type t;
4194 	unsigned total, off;
4195 
4196 	if (!bmap)
4197 		return NULL;
4198 	if (pos(bmap->dim, type) + first + n ==
4199 				1 + isl_space_dim(bmap->dim, isl_dim_all))
4200 		return bmap;
4201 
4202 	total = isl_basic_map_total_dim(bmap);
4203 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
4204 
4205 	off = 0;
4206 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4207 		unsigned size = isl_space_dim(bmap->dim, t);
4208 		if (t == type) {
4209 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4210 					    0, first, off);
4211 			off += first;
4212 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4213 					    first, n, total - bmap->n_div - n);
4214 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4215 					    first + n, size - (first + n), off);
4216 			off += size - (first + n);
4217 		} else {
4218 			isl_dim_map_dim(dim_map, bmap->dim, t, off);
4219 			off += size;
4220 		}
4221 	}
4222 	isl_dim_map_div(dim_map, bmap, off + n);
4223 
4224 	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4225 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
4226 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4227 	return res;
4228 }
4229 
4230 /* Insert "n" rows in the divs of "bmap".
4231  *
4232  * The number of columns is not changed, which means that the last
4233  * dimensions of "bmap" are being reintepreted as the new divs.
4234  * The space of "bmap" is not adjusted, however, which means
4235  * that "bmap" is left in an inconsistent state.  Removing "n" dimensions
4236  * from the space of "bmap" is the responsibility of the caller.
4237  */
insert_div_rows(__isl_take isl_basic_map * bmap,int n)4238 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4239 	int n)
4240 {
4241 	int i;
4242 	size_t row_size;
4243 	isl_int **new_div;
4244 	isl_int *old;
4245 
4246 	bmap = isl_basic_map_cow(bmap);
4247 	if (!bmap)
4248 		return NULL;
4249 
4250 	row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
4251 	old = bmap->block2.data;
4252 	bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4253 					(bmap->extra + n) * (1 + row_size));
4254 	if (!bmap->block2.data)
4255 		return isl_basic_map_free(bmap);
4256 	new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4257 	if (!new_div)
4258 		return isl_basic_map_free(bmap);
4259 	for (i = 0; i < n; ++i) {
4260 		new_div[i] = bmap->block2.data +
4261 				(bmap->extra + i) * (1 + row_size);
4262 		isl_seq_clr(new_div[i], 1 + row_size);
4263 	}
4264 	for (i = 0; i < bmap->extra; ++i)
4265 		new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4266 	free(bmap->div);
4267 	bmap->div = new_div;
4268 	bmap->n_div += n;
4269 	bmap->extra += n;
4270 
4271 	return bmap;
4272 }
4273 
4274 /* Drop constraints from "bmap" that only involve the variables
4275  * of "type" in the range [first, first + n] that are not related
4276  * to any of the variables outside that interval.
4277  * These constraints cannot influence the values for the variables
4278  * outside the interval, except in case they cause "bmap" to be empty.
4279  * Only drop the constraints if "bmap" is known to be non-empty.
4280  */
drop_irrelevant_constraints(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4281 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4282 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
4283 	unsigned first, unsigned n)
4284 {
4285 	int i;
4286 	int *groups;
4287 	unsigned dim, n_div;
4288 	isl_bool non_empty;
4289 
4290 	non_empty = isl_basic_map_plain_is_non_empty(bmap);
4291 	if (non_empty < 0)
4292 		return isl_basic_map_free(bmap);
4293 	if (!non_empty)
4294 		return bmap;
4295 
4296 	dim = isl_basic_map_dim(bmap, isl_dim_all);
4297 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
4298 	groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4299 	if (!groups)
4300 		return isl_basic_map_free(bmap);
4301 	first += isl_basic_map_offset(bmap, type) - 1;
4302 	for (i = 0; i < first; ++i)
4303 		groups[i] = -1;
4304 	for (i = first + n; i < dim - n_div; ++i)
4305 		groups[i] = -1;
4306 
4307 	bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4308 
4309 	return bmap;
4310 }
4311 
4312 /* Turn the n dimensions of type type, starting at first
4313  * into existentially quantified variables.
4314  *
4315  * If a subset of the projected out variables are unrelated
4316  * to any of the variables that remain, then the constraints
4317  * involving this subset are simply dropped first.
4318  */
isl_basic_map_project_out(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4319 __isl_give isl_basic_map *isl_basic_map_project_out(
4320 		__isl_take isl_basic_map *bmap,
4321 		enum isl_dim_type type, unsigned first, unsigned n)
4322 {
4323 	isl_bool empty;
4324 
4325 	if (n == 0)
4326 		return basic_map_space_reset(bmap, type);
4327 	if (type == isl_dim_div)
4328 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4329 			"cannot project out existentially quantified variables",
4330 			return isl_basic_map_free(bmap));
4331 
4332 	empty = isl_basic_map_plain_is_empty(bmap);
4333 	if (empty < 0)
4334 		return isl_basic_map_free(bmap);
4335 	if (empty)
4336 		bmap = isl_basic_map_set_to_empty(bmap);
4337 
4338 	bmap = drop_irrelevant_constraints(bmap, type, first, n);
4339 	if (!bmap)
4340 		return NULL;
4341 
4342 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4343 		return isl_basic_map_remove_dims(bmap, type, first, n);
4344 
4345 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4346 		return isl_basic_map_free(bmap);
4347 
4348 	bmap = move_last(bmap, type, first, n);
4349 	bmap = isl_basic_map_cow(bmap);
4350 	bmap = insert_div_rows(bmap, n);
4351 	if (!bmap)
4352 		return NULL;
4353 
4354 	bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
4355 	if (!bmap->dim)
4356 		goto error;
4357 	bmap = isl_basic_map_simplify(bmap);
4358 	bmap = isl_basic_map_drop_redundant_divs(bmap);
4359 	return isl_basic_map_finalize(bmap);
4360 error:
4361 	isl_basic_map_free(bmap);
4362 	return NULL;
4363 }
4364 
4365 /* Turn the n dimensions of type type, starting at first
4366  * into existentially quantified variables.
4367  */
isl_basic_set_project_out(struct isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)4368 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
4369 		enum isl_dim_type type, unsigned first, unsigned n)
4370 {
4371 	return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4372 							type, first, n));
4373 }
4374 
4375 /* Turn the n dimensions of type type, starting at first
4376  * into existentially quantified variables.
4377  */
isl_map_project_out(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)4378 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4379 		enum isl_dim_type type, unsigned first, unsigned n)
4380 {
4381 	int i;
4382 
4383 	if (n == 0)
4384 		return map_space_reset(map, type);
4385 
4386 	if (isl_map_check_range(map, type, first, n) < 0)
4387 		return isl_map_free(map);
4388 
4389 	map = isl_map_cow(map);
4390 	if (!map)
4391 		return NULL;
4392 
4393 	map->dim = isl_space_drop_dims(map->dim, type, first, n);
4394 	if (!map->dim)
4395 		goto error;
4396 
4397 	for (i = 0; i < map->n; ++i) {
4398 		map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4399 		if (!map->p[i])
4400 			goto error;
4401 	}
4402 
4403 	return map;
4404 error:
4405 	isl_map_free(map);
4406 	return NULL;
4407 }
4408 
4409 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4410  * into existentially quantified variables.
4411  */
isl_map_project_onto(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)4412 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4413 	enum isl_dim_type type, unsigned first, unsigned n)
4414 {
4415 	unsigned dim;
4416 
4417 	if (isl_map_check_range(map, type, first, n) < 0)
4418 		return isl_map_free(map);
4419 	dim = isl_map_dim(map, type);
4420 	map = isl_map_project_out(map, type, first + n, dim - (first + n));
4421 	map = isl_map_project_out(map, type, 0, first);
4422 	return map;
4423 }
4424 
4425 /* Turn the n dimensions of type type, starting at first
4426  * into existentially quantified variables.
4427  */
isl_set_project_out(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)4428 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4429 		enum isl_dim_type type, unsigned first, unsigned n)
4430 {
4431 	return set_from_map(isl_map_project_out(set_to_map(set),
4432 						type, first, n));
4433 }
4434 
4435 /* Return a map that projects the elements in "set" onto their
4436  * "n" set dimensions starting at "first".
4437  * "type" should be equal to isl_dim_set.
4438  */
isl_set_project_onto_map(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)4439 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4440 	enum isl_dim_type type, unsigned first, unsigned n)
4441 {
4442 	int i;
4443 	int dim;
4444 	isl_map *map;
4445 
4446 	if (!set)
4447 		return NULL;
4448 	if (type != isl_dim_set)
4449 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
4450 			"only set dimensions can be projected out", goto error);
4451 	dim = isl_set_dim(set, isl_dim_set);
4452 	if (first + n > dim || first + n < first)
4453 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
4454 			"index out of bounds", goto error);
4455 
4456 	map = isl_map_from_domain(set);
4457 	map = isl_map_add_dims(map, isl_dim_out, n);
4458 	for (i = 0; i < n; ++i)
4459 		map = isl_map_equate(map, isl_dim_in, first + i,
4460 					isl_dim_out, i);
4461 	return map;
4462 error:
4463 	isl_set_free(set);
4464 	return NULL;
4465 }
4466 
add_divs(struct isl_basic_map * bmap,unsigned n)4467 static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
4468 {
4469 	int i, j;
4470 
4471 	for (i = 0; i < n; ++i) {
4472 		j = isl_basic_map_alloc_div(bmap);
4473 		if (j < 0)
4474 			goto error;
4475 		isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4476 	}
4477 	return bmap;
4478 error:
4479 	isl_basic_map_free(bmap);
4480 	return NULL;
4481 }
4482 
isl_basic_map_apply_range(struct isl_basic_map * bmap1,struct isl_basic_map * bmap2)4483 struct isl_basic_map *isl_basic_map_apply_range(
4484 		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4485 {
4486 	isl_space *dim_result = NULL;
4487 	struct isl_basic_map *bmap;
4488 	unsigned n_in, n_out, n, nparam, total, pos;
4489 	struct isl_dim_map *dim_map1, *dim_map2;
4490 
4491 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4492 		goto error;
4493 	if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4494 				    bmap2->dim, isl_dim_in))
4495 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4496 			"spaces don't match", goto error);
4497 
4498 	dim_result = isl_space_join(isl_space_copy(bmap1->dim),
4499 				  isl_space_copy(bmap2->dim));
4500 
4501 	n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4502 	n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4503 	n = isl_basic_map_dim(bmap1, isl_dim_out);
4504 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4505 
4506 	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4507 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4508 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4509 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4510 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4511 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4512 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4513 	isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4514 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4515 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4516 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4517 
4518 	bmap = isl_basic_map_alloc_space(dim_result,
4519 			bmap1->n_div + bmap2->n_div + n,
4520 			bmap1->n_eq + bmap2->n_eq,
4521 			bmap1->n_ineq + bmap2->n_ineq);
4522 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4523 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4524 	bmap = add_divs(bmap, n);
4525 	bmap = isl_basic_map_simplify(bmap);
4526 	bmap = isl_basic_map_drop_redundant_divs(bmap);
4527 	return isl_basic_map_finalize(bmap);
4528 error:
4529 	isl_basic_map_free(bmap1);
4530 	isl_basic_map_free(bmap2);
4531 	return NULL;
4532 }
4533 
isl_basic_set_apply(struct isl_basic_set * bset,struct isl_basic_map * bmap)4534 struct isl_basic_set *isl_basic_set_apply(
4535 		struct isl_basic_set *bset, struct isl_basic_map *bmap)
4536 {
4537 	if (!bset || !bmap)
4538 		goto error;
4539 
4540 	isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4541 		    goto error);
4542 
4543 	return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4544 							bmap));
4545 error:
4546 	isl_basic_set_free(bset);
4547 	isl_basic_map_free(bmap);
4548 	return NULL;
4549 }
4550 
isl_basic_map_apply_domain(struct isl_basic_map * bmap1,struct isl_basic_map * bmap2)4551 struct isl_basic_map *isl_basic_map_apply_domain(
4552 		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4553 {
4554 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4555 		goto error;
4556 	if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4557 					bmap2->dim, isl_dim_in))
4558 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4559 			"spaces don't match", goto error);
4560 
4561 	bmap1 = isl_basic_map_reverse(bmap1);
4562 	bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4563 	return isl_basic_map_reverse(bmap1);
4564 error:
4565 	isl_basic_map_free(bmap1);
4566 	isl_basic_map_free(bmap2);
4567 	return NULL;
4568 }
4569 
4570 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4571  * A \cap B -> f(A) + f(B)
4572  */
isl_basic_map_sum(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4573 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4574 	__isl_take isl_basic_map *bmap2)
4575 {
4576 	unsigned n_in, n_out, nparam, total, pos;
4577 	struct isl_basic_map *bmap = NULL;
4578 	struct isl_dim_map *dim_map1, *dim_map2;
4579 	int i;
4580 
4581 	if (!bmap1 || !bmap2)
4582 		goto error;
4583 
4584 	isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4585 		goto error);
4586 
4587 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4588 	n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4589 	n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4590 
4591 	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4592 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4593 	dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4594 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4595 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4596 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4597 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4598 	isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4599 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4600 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4601 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4602 
4603 	bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4604 			bmap1->n_div + bmap2->n_div + 2 * n_out,
4605 			bmap1->n_eq + bmap2->n_eq + n_out,
4606 			bmap1->n_ineq + bmap2->n_ineq);
4607 	for (i = 0; i < n_out; ++i) {
4608 		int j = isl_basic_map_alloc_equality(bmap);
4609 		if (j < 0)
4610 			goto error;
4611 		isl_seq_clr(bmap->eq[j], 1+total);
4612 		isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4613 		isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4614 		isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4615 	}
4616 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4617 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4618 	bmap = add_divs(bmap, 2 * n_out);
4619 
4620 	bmap = isl_basic_map_simplify(bmap);
4621 	return isl_basic_map_finalize(bmap);
4622 error:
4623 	isl_basic_map_free(bmap);
4624 	isl_basic_map_free(bmap1);
4625 	isl_basic_map_free(bmap2);
4626 	return NULL;
4627 }
4628 
4629 /* Given two maps A -> f(A) and B -> g(B), construct a map
4630  * A \cap B -> f(A) + f(B)
4631  */
isl_map_sum(__isl_take isl_map * map1,__isl_take isl_map * map2)4632 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4633 	__isl_take isl_map *map2)
4634 {
4635 	struct isl_map *result;
4636 	int i, j;
4637 
4638 	if (!map1 || !map2)
4639 		goto error;
4640 
4641 	isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4642 
4643 	result = isl_map_alloc_space(isl_space_copy(map1->dim),
4644 				map1->n * map2->n, 0);
4645 	if (!result)
4646 		goto error;
4647 	for (i = 0; i < map1->n; ++i)
4648 		for (j = 0; j < map2->n; ++j) {
4649 			struct isl_basic_map *part;
4650 			part = isl_basic_map_sum(
4651 				    isl_basic_map_copy(map1->p[i]),
4652 				    isl_basic_map_copy(map2->p[j]));
4653 			if (isl_basic_map_is_empty(part))
4654 				isl_basic_map_free(part);
4655 			else
4656 				result = isl_map_add_basic_map(result, part);
4657 			if (!result)
4658 				goto error;
4659 		}
4660 	isl_map_free(map1);
4661 	isl_map_free(map2);
4662 	return result;
4663 error:
4664 	isl_map_free(map1);
4665 	isl_map_free(map2);
4666 	return NULL;
4667 }
4668 
isl_set_sum(__isl_take isl_set * set1,__isl_take isl_set * set2)4669 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4670 	__isl_take isl_set *set2)
4671 {
4672 	return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4673 }
4674 
4675 /* Given a basic map A -> f(A), construct A -> -f(A).
4676  */
isl_basic_map_neg(__isl_take isl_basic_map * bmap)4677 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4678 {
4679 	int i, j;
4680 	unsigned off, n;
4681 
4682 	bmap = isl_basic_map_cow(bmap);
4683 	if (!bmap)
4684 		return NULL;
4685 
4686 	n = isl_basic_map_dim(bmap, isl_dim_out);
4687 	off = isl_basic_map_offset(bmap, isl_dim_out);
4688 	for (i = 0; i < bmap->n_eq; ++i)
4689 		for (j = 0; j < n; ++j)
4690 			isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4691 	for (i = 0; i < bmap->n_ineq; ++i)
4692 		for (j = 0; j < n; ++j)
4693 			isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4694 	for (i = 0; i < bmap->n_div; ++i)
4695 		for (j = 0; j < n; ++j)
4696 			isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4697 	bmap = isl_basic_map_gauss(bmap, NULL);
4698 	return isl_basic_map_finalize(bmap);
4699 }
4700 
isl_basic_set_neg(__isl_take isl_basic_set * bset)4701 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4702 {
4703 	return isl_basic_map_neg(bset);
4704 }
4705 
4706 /* Given a map A -> f(A), construct A -> -f(A).
4707  */
isl_map_neg(__isl_take isl_map * map)4708 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4709 {
4710 	int i;
4711 
4712 	map = isl_map_cow(map);
4713 	if (!map)
4714 		return NULL;
4715 
4716 	for (i = 0; i < map->n; ++i) {
4717 		map->p[i] = isl_basic_map_neg(map->p[i]);
4718 		if (!map->p[i])
4719 			goto error;
4720 	}
4721 
4722 	return map;
4723 error:
4724 	isl_map_free(map);
4725 	return NULL;
4726 }
4727 
isl_set_neg(__isl_take isl_set * set)4728 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4729 {
4730 	return set_from_map(isl_map_neg(set_to_map(set)));
4731 }
4732 
4733 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4734  * A -> floor(f(A)/d).
4735  */
isl_basic_map_floordiv(__isl_take isl_basic_map * bmap,isl_int d)4736 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4737 		isl_int d)
4738 {
4739 	unsigned n_in, n_out, nparam, total, pos;
4740 	struct isl_basic_map *result = NULL;
4741 	struct isl_dim_map *dim_map;
4742 	int i;
4743 
4744 	if (!bmap)
4745 		return NULL;
4746 
4747 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4748 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4749 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
4750 
4751 	total = nparam + n_in + n_out + bmap->n_div + n_out;
4752 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
4753 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4754 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4755 	isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4756 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4757 
4758 	result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4759 			bmap->n_div + n_out,
4760 			bmap->n_eq, bmap->n_ineq + 2 * n_out);
4761 	result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4762 	result = add_divs(result, n_out);
4763 	for (i = 0; i < n_out; ++i) {
4764 		int j;
4765 		j = isl_basic_map_alloc_inequality(result);
4766 		if (j < 0)
4767 			goto error;
4768 		isl_seq_clr(result->ineq[j], 1+total);
4769 		isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4770 		isl_int_set_si(result->ineq[j][1+pos+i], 1);
4771 		j = isl_basic_map_alloc_inequality(result);
4772 		if (j < 0)
4773 			goto error;
4774 		isl_seq_clr(result->ineq[j], 1+total);
4775 		isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4776 		isl_int_set_si(result->ineq[j][1+pos+i], -1);
4777 		isl_int_sub_ui(result->ineq[j][0], d, 1);
4778 	}
4779 
4780 	result = isl_basic_map_simplify(result);
4781 	return isl_basic_map_finalize(result);
4782 error:
4783 	isl_basic_map_free(result);
4784 	return NULL;
4785 }
4786 
4787 /* Given a map A -> f(A) and an integer d, construct a map
4788  * A -> floor(f(A)/d).
4789  */
isl_map_floordiv(__isl_take isl_map * map,isl_int d)4790 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4791 {
4792 	int i;
4793 
4794 	map = isl_map_cow(map);
4795 	if (!map)
4796 		return NULL;
4797 
4798 	ISL_F_CLR(map, ISL_MAP_DISJOINT);
4799 	for (i = 0; i < map->n; ++i) {
4800 		map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4801 		if (!map->p[i])
4802 			goto error;
4803 	}
4804 	map = isl_map_unmark_normalized(map);
4805 
4806 	return map;
4807 error:
4808 	isl_map_free(map);
4809 	return NULL;
4810 }
4811 
4812 /* Given a map A -> f(A) and an integer d, construct a map
4813  * A -> floor(f(A)/d).
4814  */
isl_map_floordiv_val(__isl_take isl_map * map,__isl_take isl_val * d)4815 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4816 	__isl_take isl_val *d)
4817 {
4818 	if (!map || !d)
4819 		goto error;
4820 	if (!isl_val_is_int(d))
4821 		isl_die(isl_val_get_ctx(d), isl_error_invalid,
4822 			"expecting integer denominator", goto error);
4823 	map = isl_map_floordiv(map, d->n);
4824 	isl_val_free(d);
4825 	return map;
4826 error:
4827 	isl_map_free(map);
4828 	isl_val_free(d);
4829 	return NULL;
4830 }
4831 
var_equal(__isl_take isl_basic_map * bmap,unsigned pos)4832 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
4833 	unsigned pos)
4834 {
4835 	int i;
4836 	unsigned nparam;
4837 	unsigned n_in;
4838 
4839 	i = isl_basic_map_alloc_equality(bmap);
4840 	if (i < 0)
4841 		goto error;
4842 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4843 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4844 	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4845 	isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4846 	isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4847 	return isl_basic_map_finalize(bmap);
4848 error:
4849 	isl_basic_map_free(bmap);
4850 	return NULL;
4851 }
4852 
4853 /* Add a constraint to "bmap" expressing i_pos < o_pos
4854  */
var_less(__isl_take isl_basic_map * bmap,unsigned pos)4855 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
4856 	unsigned pos)
4857 {
4858 	int i;
4859 	unsigned nparam;
4860 	unsigned n_in;
4861 
4862 	i = isl_basic_map_alloc_inequality(bmap);
4863 	if (i < 0)
4864 		goto error;
4865 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4866 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4867 	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4868 	isl_int_set_si(bmap->ineq[i][0], -1);
4869 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4870 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4871 	return isl_basic_map_finalize(bmap);
4872 error:
4873 	isl_basic_map_free(bmap);
4874 	return NULL;
4875 }
4876 
4877 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4878  */
var_less_or_equal(__isl_take isl_basic_map * bmap,unsigned pos)4879 static __isl_give isl_basic_map *var_less_or_equal(
4880 	__isl_take isl_basic_map *bmap, unsigned pos)
4881 {
4882 	int i;
4883 	unsigned nparam;
4884 	unsigned n_in;
4885 
4886 	i = isl_basic_map_alloc_inequality(bmap);
4887 	if (i < 0)
4888 		goto error;
4889 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4890 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4891 	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4892 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4893 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4894 	return isl_basic_map_finalize(bmap);
4895 error:
4896 	isl_basic_map_free(bmap);
4897 	return NULL;
4898 }
4899 
4900 /* Add a constraint to "bmap" expressing i_pos > o_pos
4901  */
var_more(__isl_take isl_basic_map * bmap,unsigned pos)4902 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
4903 	unsigned pos)
4904 {
4905 	int i;
4906 	unsigned nparam;
4907 	unsigned n_in;
4908 
4909 	i = isl_basic_map_alloc_inequality(bmap);
4910 	if (i < 0)
4911 		goto error;
4912 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4913 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4914 	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4915 	isl_int_set_si(bmap->ineq[i][0], -1);
4916 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4917 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4918 	return isl_basic_map_finalize(bmap);
4919 error:
4920 	isl_basic_map_free(bmap);
4921 	return NULL;
4922 }
4923 
4924 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4925  */
var_more_or_equal(__isl_take isl_basic_map * bmap,unsigned pos)4926 static __isl_give isl_basic_map *var_more_or_equal(
4927 	__isl_take isl_basic_map *bmap, unsigned pos)
4928 {
4929 	int i;
4930 	unsigned nparam;
4931 	unsigned n_in;
4932 
4933 	i = isl_basic_map_alloc_inequality(bmap);
4934 	if (i < 0)
4935 		goto error;
4936 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4937 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4938 	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4939 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4940 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4941 	return isl_basic_map_finalize(bmap);
4942 error:
4943 	isl_basic_map_free(bmap);
4944 	return NULL;
4945 }
4946 
isl_basic_map_equal(__isl_take isl_space * dim,unsigned n_equal)4947 __isl_give isl_basic_map *isl_basic_map_equal(
4948 	__isl_take isl_space *dim, unsigned n_equal)
4949 {
4950 	int i;
4951 	struct isl_basic_map *bmap;
4952 	bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
4953 	if (!bmap)
4954 		return NULL;
4955 	for (i = 0; i < n_equal && bmap; ++i)
4956 		bmap = var_equal(bmap, i);
4957 	return isl_basic_map_finalize(bmap);
4958 }
4959 
4960 /* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
4961  */
isl_basic_map_less_at(__isl_take isl_space * dim,unsigned pos)4962 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
4963 	unsigned pos)
4964 {
4965 	int i;
4966 	struct isl_basic_map *bmap;
4967 	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4968 	if (!bmap)
4969 		return NULL;
4970 	for (i = 0; i < pos && bmap; ++i)
4971 		bmap = var_equal(bmap, i);
4972 	if (bmap)
4973 		bmap = var_less(bmap, pos);
4974 	return isl_basic_map_finalize(bmap);
4975 }
4976 
4977 /* Return a relation on "dim" expressing i_[0..pos] <<= o_[0..pos]
4978  */
isl_basic_map_less_or_equal_at(__isl_take isl_space * dim,unsigned pos)4979 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4980 	__isl_take isl_space *dim, unsigned pos)
4981 {
4982 	int i;
4983 	isl_basic_map *bmap;
4984 
4985 	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4986 	for (i = 0; i < pos; ++i)
4987 		bmap = var_equal(bmap, i);
4988 	bmap = var_less_or_equal(bmap, pos);
4989 	return isl_basic_map_finalize(bmap);
4990 }
4991 
4992 /* Return a relation on "dim" expressing i_pos > o_pos
4993  */
isl_basic_map_more_at(__isl_take isl_space * dim,unsigned pos)4994 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
4995 	unsigned pos)
4996 {
4997 	int i;
4998 	struct isl_basic_map *bmap;
4999 	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
5000 	if (!bmap)
5001 		return NULL;
5002 	for (i = 0; i < pos && bmap; ++i)
5003 		bmap = var_equal(bmap, i);
5004 	if (bmap)
5005 		bmap = var_more(bmap, pos);
5006 	return isl_basic_map_finalize(bmap);
5007 }
5008 
5009 /* Return a relation on "dim" expressing i_[0..pos] >>= o_[0..pos]
5010  */
isl_basic_map_more_or_equal_at(__isl_take isl_space * dim,unsigned pos)5011 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
5012 	__isl_take isl_space *dim, unsigned pos)
5013 {
5014 	int i;
5015 	isl_basic_map *bmap;
5016 
5017 	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
5018 	for (i = 0; i < pos; ++i)
5019 		bmap = var_equal(bmap, i);
5020 	bmap = var_more_or_equal(bmap, pos);
5021 	return isl_basic_map_finalize(bmap);
5022 }
5023 
map_lex_lte_first(__isl_take isl_space * dims,unsigned n,int equal)5024 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
5025 	unsigned n, int equal)
5026 {
5027 	struct isl_map *map;
5028 	int i;
5029 
5030 	if (n == 0 && equal)
5031 		return isl_map_universe(dims);
5032 
5033 	map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
5034 
5035 	for (i = 0; i + 1 < n; ++i)
5036 		map = isl_map_add_basic_map(map,
5037 				  isl_basic_map_less_at(isl_space_copy(dims), i));
5038 	if (n > 0) {
5039 		if (equal)
5040 			map = isl_map_add_basic_map(map,
5041 			      isl_basic_map_less_or_equal_at(dims, n - 1));
5042 		else
5043 			map = isl_map_add_basic_map(map,
5044 			      isl_basic_map_less_at(dims, n - 1));
5045 	} else
5046 		isl_space_free(dims);
5047 
5048 	return map;
5049 }
5050 
map_lex_lte(__isl_take isl_space * dims,int equal)5051 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
5052 {
5053 	if (!dims)
5054 		return NULL;
5055 	return map_lex_lte_first(dims, dims->n_out, equal);
5056 }
5057 
isl_map_lex_lt_first(__isl_take isl_space * dim,unsigned n)5058 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
5059 {
5060 	return map_lex_lte_first(dim, n, 0);
5061 }
5062 
isl_map_lex_le_first(__isl_take isl_space * dim,unsigned n)5063 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
5064 {
5065 	return map_lex_lte_first(dim, n, 1);
5066 }
5067 
isl_map_lex_lt(__isl_take isl_space * set_dim)5068 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
5069 {
5070 	return map_lex_lte(isl_space_map_from_set(set_dim), 0);
5071 }
5072 
isl_map_lex_le(__isl_take isl_space * set_dim)5073 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
5074 {
5075 	return map_lex_lte(isl_space_map_from_set(set_dim), 1);
5076 }
5077 
map_lex_gte_first(__isl_take isl_space * dims,unsigned n,int equal)5078 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
5079 	unsigned n, int equal)
5080 {
5081 	struct isl_map *map;
5082 	int i;
5083 
5084 	if (n == 0 && equal)
5085 		return isl_map_universe(dims);
5086 
5087 	map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
5088 
5089 	for (i = 0; i + 1 < n; ++i)
5090 		map = isl_map_add_basic_map(map,
5091 				  isl_basic_map_more_at(isl_space_copy(dims), i));
5092 	if (n > 0) {
5093 		if (equal)
5094 			map = isl_map_add_basic_map(map,
5095 			      isl_basic_map_more_or_equal_at(dims, n - 1));
5096 		else
5097 			map = isl_map_add_basic_map(map,
5098 			      isl_basic_map_more_at(dims, n - 1));
5099 	} else
5100 		isl_space_free(dims);
5101 
5102 	return map;
5103 }
5104 
map_lex_gte(__isl_take isl_space * dims,int equal)5105 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
5106 {
5107 	if (!dims)
5108 		return NULL;
5109 	return map_lex_gte_first(dims, dims->n_out, equal);
5110 }
5111 
isl_map_lex_gt_first(__isl_take isl_space * dim,unsigned n)5112 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
5113 {
5114 	return map_lex_gte_first(dim, n, 0);
5115 }
5116 
isl_map_lex_ge_first(__isl_take isl_space * dim,unsigned n)5117 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
5118 {
5119 	return map_lex_gte_first(dim, n, 1);
5120 }
5121 
isl_map_lex_gt(__isl_take isl_space * set_dim)5122 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
5123 {
5124 	return map_lex_gte(isl_space_map_from_set(set_dim), 0);
5125 }
5126 
isl_map_lex_ge(__isl_take isl_space * set_dim)5127 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
5128 {
5129 	return map_lex_gte(isl_space_map_from_set(set_dim), 1);
5130 }
5131 
isl_set_lex_le_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5132 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5133 	__isl_take isl_set *set2)
5134 {
5135 	isl_map *map;
5136 	map = isl_map_lex_le(isl_set_get_space(set1));
5137 	map = isl_map_intersect_domain(map, set1);
5138 	map = isl_map_intersect_range(map, set2);
5139 	return map;
5140 }
5141 
isl_set_lex_lt_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5142 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5143 	__isl_take isl_set *set2)
5144 {
5145 	isl_map *map;
5146 	map = isl_map_lex_lt(isl_set_get_space(set1));
5147 	map = isl_map_intersect_domain(map, set1);
5148 	map = isl_map_intersect_range(map, set2);
5149 	return map;
5150 }
5151 
isl_set_lex_ge_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5152 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5153 	__isl_take isl_set *set2)
5154 {
5155 	isl_map *map;
5156 	map = isl_map_lex_ge(isl_set_get_space(set1));
5157 	map = isl_map_intersect_domain(map, set1);
5158 	map = isl_map_intersect_range(map, set2);
5159 	return map;
5160 }
5161 
isl_set_lex_gt_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5162 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5163 	__isl_take isl_set *set2)
5164 {
5165 	isl_map *map;
5166 	map = isl_map_lex_gt(isl_set_get_space(set1));
5167 	map = isl_map_intersect_domain(map, set1);
5168 	map = isl_map_intersect_range(map, set2);
5169 	return map;
5170 }
5171 
isl_map_lex_le_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5172 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5173 	__isl_take isl_map *map2)
5174 {
5175 	isl_map *map;
5176 	map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5177 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5178 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5179 	return map;
5180 }
5181 
isl_map_lex_lt_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5182 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5183 	__isl_take isl_map *map2)
5184 {
5185 	isl_map *map;
5186 	map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5187 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5188 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5189 	return map;
5190 }
5191 
isl_map_lex_ge_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5192 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5193 	__isl_take isl_map *map2)
5194 {
5195 	isl_map *map;
5196 	map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5197 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5198 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5199 	return map;
5200 }
5201 
isl_map_lex_gt_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5202 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5203 	__isl_take isl_map *map2)
5204 {
5205 	isl_map *map;
5206 	map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5207 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5208 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5209 	return map;
5210 }
5211 
5212 /* For a div d = floor(f/m), add the constraint
5213  *
5214  *		f - m d >= 0
5215  */
add_upper_div_constraint(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * div)5216 static isl_stat add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
5217 	unsigned pos, isl_int *div)
5218 {
5219 	int i;
5220 	unsigned total = isl_basic_map_total_dim(bmap);
5221 
5222 	i = isl_basic_map_alloc_inequality(bmap);
5223 	if (i < 0)
5224 		return isl_stat_error;
5225 	isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
5226 	isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
5227 
5228 	return isl_stat_ok;
5229 }
5230 
5231 /* For a div d = floor(f/m), add the constraint
5232  *
5233  *		-(f-(m-1)) + m d >= 0
5234  */
add_lower_div_constraint(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * div)5235 static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
5236 	unsigned pos, isl_int *div)
5237 {
5238 	int i;
5239 	unsigned total = isl_basic_map_total_dim(bmap);
5240 
5241 	i = isl_basic_map_alloc_inequality(bmap);
5242 	if (i < 0)
5243 		return isl_stat_error;
5244 	isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
5245 	isl_int_set(bmap->ineq[i][1 + pos], div[0]);
5246 	isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5247 	isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5248 
5249 	return isl_stat_ok;
5250 }
5251 
5252 /* For a div d = floor(f/m), add the constraints
5253  *
5254  *		f - m d >= 0
5255  *		-(f-(m-1)) + m d >= 0
5256  *
5257  * Note that the second constraint is the negation of
5258  *
5259  *		f - m d >= m
5260  */
isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * div)5261 int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
5262 	unsigned pos, isl_int *div)
5263 {
5264 	if (add_upper_div_constraint(bmap, pos, div) < 0)
5265 		return -1;
5266 	if (add_lower_div_constraint(bmap, pos, div) < 0)
5267 		return -1;
5268 	return 0;
5269 }
5270 
isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set * bset,unsigned pos,isl_int * div)5271 int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
5272 	unsigned pos, isl_int *div)
5273 {
5274 	return isl_basic_map_add_div_constraints_var(bset_to_bmap(bset),
5275 							pos, div);
5276 }
5277 
isl_basic_map_add_div_constraints(struct isl_basic_map * bmap,unsigned div)5278 int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
5279 {
5280 	unsigned total = isl_basic_map_total_dim(bmap);
5281 	unsigned div_pos = total - bmap->n_div + div;
5282 
5283 	return isl_basic_map_add_div_constraints_var(bmap, div_pos,
5284 							bmap->div[div]);
5285 }
5286 
5287 /* For each known div d = floor(f/m), add the constraints
5288  *
5289  *		f - m d >= 0
5290  *		-(f-(m-1)) + m d >= 0
5291  *
5292  * Remove duplicate constraints in case of some these div constraints
5293  * already appear in "bmap".
5294  */
isl_basic_map_add_known_div_constraints(__isl_take isl_basic_map * bmap)5295 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5296 	__isl_take isl_basic_map *bmap)
5297 {
5298 	unsigned n_div;
5299 
5300 	if (!bmap)
5301 		return NULL;
5302 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
5303 	if (n_div == 0)
5304 		return bmap;
5305 
5306 	bmap = add_known_div_constraints(bmap);
5307 	bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5308 	bmap = isl_basic_map_finalize(bmap);
5309 	return bmap;
5310 }
5311 
5312 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5313  *
5314  * In particular, if this div is of the form d = floor(f/m),
5315  * then add the constraint
5316  *
5317  *		f - m d >= 0
5318  *
5319  * if sign < 0 or the constraint
5320  *
5321  *		-(f-(m-1)) + m d >= 0
5322  *
5323  * if sign > 0.
5324  */
isl_basic_map_add_div_constraint(__isl_keep isl_basic_map * bmap,unsigned div,int sign)5325 int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
5326 	unsigned div, int sign)
5327 {
5328 	unsigned total;
5329 	unsigned div_pos;
5330 
5331 	if (!bmap)
5332 		return -1;
5333 
5334 	total = isl_basic_map_total_dim(bmap);
5335 	div_pos = total - bmap->n_div + div;
5336 
5337 	if (sign < 0)
5338 		return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
5339 	else
5340 		return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
5341 }
5342 
isl_basic_map_underlying_set(__isl_take isl_basic_map * bmap)5343 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5344 	__isl_take isl_basic_map *bmap)
5345 {
5346 	if (!bmap)
5347 		goto error;
5348 	if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5349 	    bmap->n_div == 0 &&
5350 	    !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5351 	    !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5352 		return bset_from_bmap(bmap);
5353 	bmap = isl_basic_map_cow(bmap);
5354 	if (!bmap)
5355 		goto error;
5356 	bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
5357 	if (!bmap->dim)
5358 		goto error;
5359 	bmap->extra -= bmap->n_div;
5360 	bmap->n_div = 0;
5361 	bmap = isl_basic_map_finalize(bmap);
5362 	return bset_from_bmap(bmap);
5363 error:
5364 	isl_basic_map_free(bmap);
5365 	return NULL;
5366 }
5367 
isl_basic_set_underlying_set(__isl_take isl_basic_set * bset)5368 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5369 		__isl_take isl_basic_set *bset)
5370 {
5371 	return isl_basic_map_underlying_set(bset_to_bmap(bset));
5372 }
5373 
5374 /* Replace each element in "list" by the result of applying
5375  * isl_basic_map_underlying_set to the element.
5376  */
isl_basic_map_list_underlying_set(__isl_take isl_basic_map_list * list)5377 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5378 	__isl_take isl_basic_map_list *list)
5379 {
5380 	int i, n;
5381 
5382 	if (!list)
5383 		return NULL;
5384 
5385 	n = isl_basic_map_list_n_basic_map(list);
5386 	for (i = 0; i < n; ++i) {
5387 		isl_basic_map *bmap;
5388 		isl_basic_set *bset;
5389 
5390 		bmap = isl_basic_map_list_get_basic_map(list, i);
5391 		bset = isl_basic_set_underlying_set(bmap);
5392 		list = isl_basic_set_list_set_basic_set(list, i, bset);
5393 	}
5394 
5395 	return list;
5396 }
5397 
isl_basic_map_overlying_set(__isl_take isl_basic_set * bset,__isl_take isl_basic_map * like)5398 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5399 	__isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5400 {
5401 	struct isl_basic_map *bmap;
5402 	struct isl_ctx *ctx;
5403 	unsigned total;
5404 	int i;
5405 
5406 	if (!bset || !like)
5407 		goto error;
5408 	ctx = bset->ctx;
5409 	isl_assert(ctx, bset->n_div == 0, goto error);
5410 	isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
5411 	isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
5412 			goto error);
5413 	if (like->n_div == 0) {
5414 		isl_space *space = isl_basic_map_get_space(like);
5415 		isl_basic_map_free(like);
5416 		return isl_basic_map_reset_space(bset, space);
5417 	}
5418 	bset = isl_basic_set_cow(bset);
5419 	if (!bset)
5420 		goto error;
5421 	total = bset->dim->n_out + bset->extra;
5422 	bmap = bset_to_bmap(bset);
5423 	isl_space_free(bmap->dim);
5424 	bmap->dim = isl_space_copy(like->dim);
5425 	if (!bmap->dim)
5426 		goto error;
5427 	bmap->n_div = like->n_div;
5428 	bmap->extra += like->n_div;
5429 	if (bmap->extra) {
5430 		unsigned ltotal;
5431 		isl_int **div;
5432 		ltotal = total - bmap->extra + like->extra;
5433 		if (ltotal > total)
5434 			ltotal = total;
5435 		bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5436 					bmap->extra * (1 + 1 + total));
5437 		if (isl_blk_is_error(bmap->block2))
5438 			goto error;
5439 		div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5440 		if (!div)
5441 			goto error;
5442 		bmap->div = div;
5443 		for (i = 0; i < bmap->extra; ++i)
5444 			bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5445 		for (i = 0; i < like->n_div; ++i) {
5446 			isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5447 			isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5448 		}
5449 		bmap = isl_basic_map_add_known_div_constraints(bmap);
5450 	}
5451 	isl_basic_map_free(like);
5452 	bmap = isl_basic_map_simplify(bmap);
5453 	bmap = isl_basic_map_finalize(bmap);
5454 	return bmap;
5455 error:
5456 	isl_basic_map_free(like);
5457 	isl_basic_set_free(bset);
5458 	return NULL;
5459 }
5460 
isl_basic_set_from_underlying_set(struct isl_basic_set * bset,struct isl_basic_set * like)5461 struct isl_basic_set *isl_basic_set_from_underlying_set(
5462 	struct isl_basic_set *bset, struct isl_basic_set *like)
5463 {
5464 	return bset_from_bmap(isl_basic_map_overlying_set(bset,
5465 							bset_to_bmap(like)));
5466 }
5467 
isl_map_underlying_set(__isl_take isl_map * map)5468 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5469 {
5470 	int i;
5471 
5472 	map = isl_map_cow(map);
5473 	if (!map)
5474 		return NULL;
5475 	map->dim = isl_space_cow(map->dim);
5476 	if (!map->dim)
5477 		goto error;
5478 
5479 	for (i = 1; i < map->n; ++i)
5480 		isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5481 				goto error);
5482 	for (i = 0; i < map->n; ++i) {
5483 		map->p[i] = bset_to_bmap(
5484 				isl_basic_map_underlying_set(map->p[i]));
5485 		if (!map->p[i])
5486 			goto error;
5487 	}
5488 	if (map->n == 0)
5489 		map->dim = isl_space_underlying(map->dim, 0);
5490 	else {
5491 		isl_space_free(map->dim);
5492 		map->dim = isl_space_copy(map->p[0]->dim);
5493 	}
5494 	if (!map->dim)
5495 		goto error;
5496 	return set_from_map(map);
5497 error:
5498 	isl_map_free(map);
5499 	return NULL;
5500 }
5501 
5502 /* Replace the space of "bmap" by "space".
5503  *
5504  * If the space of "bmap" is identical to "space" (including the identifiers
5505  * of the input and output dimensions), then simply return the original input.
5506  */
isl_basic_map_reset_space(__isl_take isl_basic_map * bmap,__isl_take isl_space * space)5507 __isl_give isl_basic_map *isl_basic_map_reset_space(
5508 	__isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5509 {
5510 	isl_bool equal;
5511 	isl_space *bmap_space;
5512 
5513 	bmap_space = isl_basic_map_peek_space(bmap);
5514 	equal = isl_space_is_equal(bmap_space, space);
5515 	if (equal >= 0 && equal)
5516 		equal = isl_space_has_equal_ids(bmap_space, space);
5517 	if (equal < 0)
5518 		goto error;
5519 	if (equal) {
5520 		isl_space_free(space);
5521 		return bmap;
5522 	}
5523 	bmap = isl_basic_map_cow(bmap);
5524 	if (!bmap || !space)
5525 		goto error;
5526 
5527 	isl_space_free(bmap->dim);
5528 	bmap->dim = space;
5529 
5530 	bmap = isl_basic_map_finalize(bmap);
5531 
5532 	return bmap;
5533 error:
5534 	isl_basic_map_free(bmap);
5535 	isl_space_free(space);
5536 	return NULL;
5537 }
5538 
isl_basic_set_reset_space(__isl_take isl_basic_set * bset,__isl_take isl_space * dim)5539 __isl_give isl_basic_set *isl_basic_set_reset_space(
5540 	__isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5541 {
5542 	return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5543 							dim));
5544 }
5545 
5546 /* Check that the total dimensions of "map" and "space" are the same.
5547  */
check_map_space_equal_total_dim(__isl_keep isl_map * map,__isl_keep isl_space * space)5548 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5549 	__isl_keep isl_space *space)
5550 {
5551 	unsigned dim1, dim2;
5552 
5553 	if (!map || !space)
5554 		return isl_stat_error;
5555 	dim1 = isl_map_dim(map, isl_dim_all);
5556 	dim2 = isl_space_dim(space, isl_dim_all);
5557 	if (dim1 == dim2)
5558 		return isl_stat_ok;
5559 	isl_die(isl_map_get_ctx(map), isl_error_invalid,
5560 		"total dimensions do not match", return isl_stat_error);
5561 }
5562 
isl_map_reset_space(__isl_take isl_map * map,__isl_take isl_space * dim)5563 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5564 	__isl_take isl_space *dim)
5565 {
5566 	int i;
5567 
5568 	map = isl_map_cow(map);
5569 	if (!map || !dim)
5570 		goto error;
5571 
5572 	for (i = 0; i < map->n; ++i) {
5573 		map->p[i] = isl_basic_map_reset_space(map->p[i],
5574 						    isl_space_copy(dim));
5575 		if (!map->p[i])
5576 			goto error;
5577 	}
5578 	isl_space_free(map->dim);
5579 	map->dim = dim;
5580 
5581 	return map;
5582 error:
5583 	isl_map_free(map);
5584 	isl_space_free(dim);
5585 	return NULL;
5586 }
5587 
5588 /* Replace the space of "map" by "space", without modifying
5589  * the dimension of "map".
5590  *
5591  * If the space of "map" is identical to "space" (including the identifiers
5592  * of the input and output dimensions), then simply return the original input.
5593  */
isl_map_reset_equal_dim_space(__isl_take isl_map * map,__isl_take isl_space * space)5594 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5595 	__isl_take isl_space *space)
5596 {
5597 	isl_bool equal;
5598 	isl_space *map_space;
5599 
5600 	map_space = isl_map_peek_space(map);
5601 	equal = isl_space_is_equal(map_space, space);
5602 	if (equal >= 0 && equal)
5603 		equal = isl_space_has_equal_ids(map_space, space);
5604 	if (equal < 0)
5605 		goto error;
5606 	if (equal) {
5607 		isl_space_free(space);
5608 		return map;
5609 	}
5610 	if (check_map_space_equal_total_dim(map, space) < 0)
5611 		goto error;
5612 	return isl_map_reset_space(map, space);
5613 error:
5614 	isl_map_free(map);
5615 	isl_space_free(space);
5616 	return NULL;
5617 }
5618 
isl_set_reset_space(__isl_take isl_set * set,__isl_take isl_space * dim)5619 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5620 	__isl_take isl_space *dim)
5621 {
5622 	return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5623 }
5624 
5625 /* Compute the parameter domain of the given basic set.
5626  */
isl_basic_set_params(__isl_take isl_basic_set * bset)5627 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5628 {
5629 	isl_bool is_params;
5630 	isl_space *space;
5631 	unsigned n;
5632 
5633 	is_params = isl_basic_set_is_params(bset);
5634 	if (is_params < 0)
5635 		return isl_basic_set_free(bset);
5636 	if (is_params)
5637 		return bset;
5638 
5639 	n = isl_basic_set_dim(bset, isl_dim_set);
5640 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5641 	space = isl_basic_set_get_space(bset);
5642 	space = isl_space_params(space);
5643 	bset = isl_basic_set_reset_space(bset, space);
5644 	return bset;
5645 }
5646 
5647 /* Construct a zero-dimensional basic set with the given parameter domain.
5648  */
isl_basic_set_from_params(__isl_take isl_basic_set * bset)5649 __isl_give isl_basic_set *isl_basic_set_from_params(
5650 	__isl_take isl_basic_set *bset)
5651 {
5652 	isl_space *space;
5653 	space = isl_basic_set_get_space(bset);
5654 	space = isl_space_set_from_params(space);
5655 	bset = isl_basic_set_reset_space(bset, space);
5656 	return bset;
5657 }
5658 
5659 /* Compute the parameter domain of the given set.
5660  */
isl_set_params(__isl_take isl_set * set)5661 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5662 {
5663 	isl_space *space;
5664 	unsigned n;
5665 
5666 	if (isl_set_is_params(set))
5667 		return set;
5668 
5669 	n = isl_set_dim(set, isl_dim_set);
5670 	set = isl_set_project_out(set, isl_dim_set, 0, n);
5671 	space = isl_set_get_space(set);
5672 	space = isl_space_params(space);
5673 	set = isl_set_reset_space(set, space);
5674 	return set;
5675 }
5676 
5677 /* Construct a zero-dimensional set with the given parameter domain.
5678  */
isl_set_from_params(__isl_take isl_set * set)5679 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5680 {
5681 	isl_space *space;
5682 	space = isl_set_get_space(set);
5683 	space = isl_space_set_from_params(space);
5684 	set = isl_set_reset_space(set, space);
5685 	return set;
5686 }
5687 
5688 /* Compute the parameter domain of the given map.
5689  */
isl_map_params(__isl_take isl_map * map)5690 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5691 {
5692 	isl_space *space;
5693 	unsigned n;
5694 
5695 	n = isl_map_dim(map, isl_dim_in);
5696 	map = isl_map_project_out(map, isl_dim_in, 0, n);
5697 	n = isl_map_dim(map, isl_dim_out);
5698 	map = isl_map_project_out(map, isl_dim_out, 0, n);
5699 	space = isl_map_get_space(map);
5700 	space = isl_space_params(space);
5701 	map = isl_map_reset_space(map, space);
5702 	return map;
5703 }
5704 
isl_basic_map_domain(struct isl_basic_map * bmap)5705 struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
5706 {
5707 	isl_space *space;
5708 	unsigned n_out;
5709 
5710 	if (!bmap)
5711 		return NULL;
5712 	space = isl_space_domain(isl_basic_map_get_space(bmap));
5713 
5714 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
5715 	bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5716 
5717 	return isl_basic_map_reset_space(bmap, space);
5718 }
5719 
isl_basic_map_may_be_set(__isl_keep isl_basic_map * bmap)5720 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5721 {
5722 	if (!bmap)
5723 		return isl_bool_error;
5724 	return isl_space_may_be_set(bmap->dim);
5725 }
5726 
5727 /* Is this basic map actually a set?
5728  * Users should never call this function.  Outside of isl,
5729  * the type should indicate whether something is a set or a map.
5730  */
isl_basic_map_is_set(__isl_keep isl_basic_map * bmap)5731 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5732 {
5733 	if (!bmap)
5734 		return isl_bool_error;
5735 	return isl_space_is_set(bmap->dim);
5736 }
5737 
isl_basic_map_range(struct isl_basic_map * bmap)5738 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5739 {
5740 	isl_bool is_set;
5741 
5742 	is_set = isl_basic_map_is_set(bmap);
5743 	if (is_set < 0)
5744 		goto error;
5745 	if (is_set)
5746 		return bmap;
5747 	return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5748 error:
5749 	isl_basic_map_free(bmap);
5750 	return NULL;
5751 }
5752 
isl_basic_map_domain_map(__isl_take isl_basic_map * bmap)5753 __isl_give isl_basic_map *isl_basic_map_domain_map(
5754 	__isl_take isl_basic_map *bmap)
5755 {
5756 	int i;
5757 	isl_space *dim;
5758 	isl_basic_map *domain;
5759 	int nparam, n_in, n_out;
5760 
5761 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5762 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5763 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
5764 
5765 	dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
5766 	domain = isl_basic_map_universe(dim);
5767 
5768 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5769 	bmap = isl_basic_map_apply_range(bmap, domain);
5770 	bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5771 
5772 	for (i = 0; i < n_in; ++i)
5773 		bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5774 						    isl_dim_out, i);
5775 
5776 	bmap = isl_basic_map_gauss(bmap, NULL);
5777 	return isl_basic_map_finalize(bmap);
5778 }
5779 
isl_basic_map_range_map(__isl_take isl_basic_map * bmap)5780 __isl_give isl_basic_map *isl_basic_map_range_map(
5781 	__isl_take isl_basic_map *bmap)
5782 {
5783 	int i;
5784 	isl_space *dim;
5785 	isl_basic_map *range;
5786 	int nparam, n_in, n_out;
5787 
5788 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5789 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5790 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
5791 
5792 	dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
5793 	range = isl_basic_map_universe(dim);
5794 
5795 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5796 	bmap = isl_basic_map_apply_range(bmap, range);
5797 	bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5798 
5799 	for (i = 0; i < n_out; ++i)
5800 		bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5801 						    isl_dim_out, i);
5802 
5803 	bmap = isl_basic_map_gauss(bmap, NULL);
5804 	return isl_basic_map_finalize(bmap);
5805 }
5806 
isl_map_may_be_set(__isl_keep isl_map * map)5807 int isl_map_may_be_set(__isl_keep isl_map *map)
5808 {
5809 	if (!map)
5810 		return -1;
5811 	return isl_space_may_be_set(map->dim);
5812 }
5813 
5814 /* Is this map actually a set?
5815  * Users should never call this function.  Outside of isl,
5816  * the type should indicate whether something is a set or a map.
5817  */
isl_map_is_set(__isl_keep isl_map * map)5818 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5819 {
5820 	if (!map)
5821 		return isl_bool_error;
5822 	return isl_space_is_set(map->dim);
5823 }
5824 
isl_map_range(__isl_take isl_map * map)5825 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
5826 {
5827 	int i;
5828 	isl_bool is_set;
5829 	struct isl_set *set;
5830 
5831 	is_set = isl_map_is_set(map);
5832 	if (is_set < 0)
5833 		goto error;
5834 	if (is_set)
5835 		return set_from_map(map);
5836 
5837 	map = isl_map_cow(map);
5838 	if (!map)
5839 		goto error;
5840 
5841 	set = set_from_map(map);
5842 	set->dim = isl_space_range(set->dim);
5843 	if (!set->dim)
5844 		goto error;
5845 	for (i = 0; i < map->n; ++i) {
5846 		set->p[i] = isl_basic_map_range(map->p[i]);
5847 		if (!set->p[i])
5848 			goto error;
5849 	}
5850 	ISL_F_CLR(set, ISL_MAP_DISJOINT);
5851 	ISL_F_CLR(set, ISL_SET_NORMALIZED);
5852 	return set;
5853 error:
5854 	isl_map_free(map);
5855 	return NULL;
5856 }
5857 
isl_map_domain_map(__isl_take isl_map * map)5858 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5859 {
5860 	int i;
5861 
5862 	map = isl_map_cow(map);
5863 	if (!map)
5864 		return NULL;
5865 
5866 	map->dim = isl_space_domain_map(map->dim);
5867 	if (!map->dim)
5868 		goto error;
5869 	for (i = 0; i < map->n; ++i) {
5870 		map->p[i] = isl_basic_map_domain_map(map->p[i]);
5871 		if (!map->p[i])
5872 			goto error;
5873 	}
5874 	ISL_F_CLR(map, ISL_MAP_DISJOINT);
5875 	map = isl_map_unmark_normalized(map);
5876 	return map;
5877 error:
5878 	isl_map_free(map);
5879 	return NULL;
5880 }
5881 
isl_map_range_map(__isl_take isl_map * map)5882 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5883 {
5884 	int i;
5885 	isl_space *range_dim;
5886 
5887 	map = isl_map_cow(map);
5888 	if (!map)
5889 		return NULL;
5890 
5891 	range_dim = isl_space_range(isl_map_get_space(map));
5892 	range_dim = isl_space_from_range(range_dim);
5893 	map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5894 	map->dim = isl_space_join(map->dim, range_dim);
5895 	if (!map->dim)
5896 		goto error;
5897 	for (i = 0; i < map->n; ++i) {
5898 		map->p[i] = isl_basic_map_range_map(map->p[i]);
5899 		if (!map->p[i])
5900 			goto error;
5901 	}
5902 	ISL_F_CLR(map, ISL_MAP_DISJOINT);
5903 	map = isl_map_unmark_normalized(map);
5904 	return map;
5905 error:
5906 	isl_map_free(map);
5907 	return NULL;
5908 }
5909 
5910 /* Given a wrapped map of the form A[B -> C],
5911  * return the map A[B -> C] -> B.
5912  */
isl_set_wrapped_domain_map(__isl_take isl_set * set)5913 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5914 {
5915 	isl_id *id;
5916 	isl_map *map;
5917 
5918 	if (!set)
5919 		return NULL;
5920 	if (!isl_set_has_tuple_id(set))
5921 		return isl_map_domain_map(isl_set_unwrap(set));
5922 
5923 	id = isl_set_get_tuple_id(set);
5924 	map = isl_map_domain_map(isl_set_unwrap(set));
5925 	map = isl_map_set_tuple_id(map, isl_dim_in, id);
5926 
5927 	return map;
5928 }
5929 
isl_basic_map_from_domain(__isl_take isl_basic_set * bset)5930 __isl_give isl_basic_map *isl_basic_map_from_domain(
5931 	__isl_take isl_basic_set *bset)
5932 {
5933 	return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5934 }
5935 
isl_basic_map_from_range(__isl_take isl_basic_set * bset)5936 __isl_give isl_basic_map *isl_basic_map_from_range(
5937 	__isl_take isl_basic_set *bset)
5938 {
5939 	isl_space *space;
5940 	space = isl_basic_set_get_space(bset);
5941 	space = isl_space_from_range(space);
5942 	bset = isl_basic_set_reset_space(bset, space);
5943 	return bset_to_bmap(bset);
5944 }
5945 
5946 /* Create a relation with the given set as range.
5947  * The domain of the created relation is a zero-dimensional
5948  * flat anonymous space.
5949  */
isl_map_from_range(__isl_take isl_set * set)5950 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5951 {
5952 	isl_space *space;
5953 	space = isl_set_get_space(set);
5954 	space = isl_space_from_range(space);
5955 	set = isl_set_reset_space(set, space);
5956 	return set_to_map(set);
5957 }
5958 
5959 /* Create a relation with the given set as domain.
5960  * The range of the created relation is a zero-dimensional
5961  * flat anonymous space.
5962  */
isl_map_from_domain(__isl_take isl_set * set)5963 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5964 {
5965 	return isl_map_reverse(isl_map_from_range(set));
5966 }
5967 
isl_basic_map_from_domain_and_range(__isl_take isl_basic_set * domain,__isl_take isl_basic_set * range)5968 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5969 	__isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5970 {
5971 	return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5972 }
5973 
isl_map_from_domain_and_range(__isl_take isl_set * domain,__isl_take isl_set * range)5974 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5975 	__isl_take isl_set *range)
5976 {
5977 	return isl_map_apply_range(isl_map_reverse(domain), range);
5978 }
5979 
5980 /* Return a newly allocated isl_map with given space and flags and
5981  * room for "n" basic maps.
5982  * Make sure that all cached information is cleared.
5983  */
isl_map_alloc_space(__isl_take isl_space * space,int n,unsigned flags)5984 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5985 	unsigned flags)
5986 {
5987 	struct isl_map *map;
5988 
5989 	if (!space)
5990 		return NULL;
5991 	if (n < 0)
5992 		isl_die(space->ctx, isl_error_internal,
5993 			"negative number of basic maps", goto error);
5994 	map = isl_calloc(space->ctx, struct isl_map,
5995 			sizeof(struct isl_map) +
5996 			(n - 1) * sizeof(struct isl_basic_map *));
5997 	if (!map)
5998 		goto error;
5999 
6000 	map->ctx = space->ctx;
6001 	isl_ctx_ref(map->ctx);
6002 	map->ref = 1;
6003 	map->size = n;
6004 	map->n = 0;
6005 	map->dim = space;
6006 	map->flags = flags;
6007 	return map;
6008 error:
6009 	isl_space_free(space);
6010 	return NULL;
6011 }
6012 
isl_basic_map_empty(__isl_take isl_space * space)6013 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
6014 {
6015 	struct isl_basic_map *bmap;
6016 	bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
6017 	bmap = isl_basic_map_set_to_empty(bmap);
6018 	return bmap;
6019 }
6020 
isl_basic_set_empty(__isl_take isl_space * space)6021 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
6022 {
6023 	struct isl_basic_set *bset;
6024 	bset = isl_basic_set_alloc_space(space, 0, 1, 0);
6025 	bset = isl_basic_set_set_to_empty(bset);
6026 	return bset;
6027 }
6028 
isl_basic_map_universe(__isl_take isl_space * space)6029 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6030 {
6031 	struct isl_basic_map *bmap;
6032 	bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6033 	bmap = isl_basic_map_finalize(bmap);
6034 	return bmap;
6035 }
6036 
isl_basic_set_universe(__isl_take isl_space * space)6037 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6038 {
6039 	struct isl_basic_set *bset;
6040 	bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6041 	bset = isl_basic_set_finalize(bset);
6042 	return bset;
6043 }
6044 
isl_basic_map_nat_universe(__isl_take isl_space * dim)6045 __isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
6046 {
6047 	int i;
6048 	unsigned total = isl_space_dim(dim, isl_dim_all);
6049 	isl_basic_map *bmap;
6050 
6051 	bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
6052 	for (i = 0; i < total; ++i) {
6053 		int k = isl_basic_map_alloc_inequality(bmap);
6054 		if (k < 0)
6055 			goto error;
6056 		isl_seq_clr(bmap->ineq[k], 1 + total);
6057 		isl_int_set_si(bmap->ineq[k][1 + i], 1);
6058 	}
6059 	return bmap;
6060 error:
6061 	isl_basic_map_free(bmap);
6062 	return NULL;
6063 }
6064 
isl_basic_set_nat_universe(__isl_take isl_space * dim)6065 __isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
6066 {
6067 	return isl_basic_map_nat_universe(dim);
6068 }
6069 
isl_map_nat_universe(__isl_take isl_space * dim)6070 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
6071 {
6072 	return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
6073 }
6074 
isl_set_nat_universe(__isl_take isl_space * dim)6075 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
6076 {
6077 	return isl_map_nat_universe(dim);
6078 }
6079 
isl_map_empty(__isl_take isl_space * space)6080 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6081 {
6082 	return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6083 }
6084 
isl_set_empty(__isl_take isl_space * space)6085 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6086 {
6087 	return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6088 }
6089 
isl_map_universe(__isl_take isl_space * space)6090 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6091 {
6092 	struct isl_map *map;
6093 	if (!space)
6094 		return NULL;
6095 	map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6096 	map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6097 	return map;
6098 }
6099 
isl_set_universe(__isl_take isl_space * space)6100 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6101 {
6102 	struct isl_set *set;
6103 	if (!space)
6104 		return NULL;
6105 	set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6106 	set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6107 	return set;
6108 }
6109 
isl_map_dup(struct isl_map * map)6110 struct isl_map *isl_map_dup(struct isl_map *map)
6111 {
6112 	int i;
6113 	struct isl_map *dup;
6114 
6115 	if (!map)
6116 		return NULL;
6117 	dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6118 	for (i = 0; i < map->n; ++i)
6119 		dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6120 	return dup;
6121 }
6122 
isl_map_add_basic_map(__isl_take isl_map * map,__isl_take isl_basic_map * bmap)6123 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6124 						__isl_take isl_basic_map *bmap)
6125 {
6126 	if (!bmap || !map)
6127 		goto error;
6128 	if (isl_basic_map_plain_is_empty(bmap)) {
6129 		isl_basic_map_free(bmap);
6130 		return map;
6131 	}
6132 	isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
6133 	isl_assert(map->ctx, map->n < map->size, goto error);
6134 	map->p[map->n] = bmap;
6135 	map->n++;
6136 	map = isl_map_unmark_normalized(map);
6137 	return map;
6138 error:
6139 	if (map)
6140 		isl_map_free(map);
6141 	if (bmap)
6142 		isl_basic_map_free(bmap);
6143 	return NULL;
6144 }
6145 
isl_map_free(__isl_take isl_map * map)6146 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6147 {
6148 	int i;
6149 
6150 	if (!map)
6151 		return NULL;
6152 
6153 	if (--map->ref > 0)
6154 		return NULL;
6155 
6156 	clear_caches(map);
6157 	isl_ctx_deref(map->ctx);
6158 	for (i = 0; i < map->n; ++i)
6159 		isl_basic_map_free(map->p[i]);
6160 	isl_space_free(map->dim);
6161 	free(map);
6162 
6163 	return NULL;
6164 }
6165 
isl_basic_map_fix_pos_si(struct isl_basic_map * bmap,unsigned pos,int value)6166 static struct isl_basic_map *isl_basic_map_fix_pos_si(
6167 	struct isl_basic_map *bmap, unsigned pos, int value)
6168 {
6169 	int j;
6170 
6171 	bmap = isl_basic_map_cow(bmap);
6172 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6173 	j = isl_basic_map_alloc_equality(bmap);
6174 	if (j < 0)
6175 		goto error;
6176 	isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6177 	isl_int_set_si(bmap->eq[j][pos], -1);
6178 	isl_int_set_si(bmap->eq[j][0], value);
6179 	bmap = isl_basic_map_simplify(bmap);
6180 	return isl_basic_map_finalize(bmap);
6181 error:
6182 	isl_basic_map_free(bmap);
6183 	return NULL;
6184 }
6185 
isl_basic_map_fix_pos(__isl_take isl_basic_map * bmap,unsigned pos,isl_int value)6186 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6187 	__isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6188 {
6189 	int j;
6190 
6191 	bmap = isl_basic_map_cow(bmap);
6192 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6193 	j = isl_basic_map_alloc_equality(bmap);
6194 	if (j < 0)
6195 		goto error;
6196 	isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6197 	isl_int_set_si(bmap->eq[j][pos], -1);
6198 	isl_int_set(bmap->eq[j][0], value);
6199 	bmap = isl_basic_map_simplify(bmap);
6200 	return isl_basic_map_finalize(bmap);
6201 error:
6202 	isl_basic_map_free(bmap);
6203 	return NULL;
6204 }
6205 
isl_basic_map_fix_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6206 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6207 		enum isl_dim_type type, unsigned pos, int value)
6208 {
6209 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6210 		return isl_basic_map_free(bmap);
6211 	return isl_basic_map_fix_pos_si(bmap,
6212 		isl_basic_map_offset(bmap, type) + pos, value);
6213 }
6214 
isl_basic_map_fix(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int value)6215 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6216 		enum isl_dim_type type, unsigned pos, isl_int value)
6217 {
6218 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6219 		return isl_basic_map_free(bmap);
6220 	return isl_basic_map_fix_pos(bmap,
6221 		isl_basic_map_offset(bmap, type) + pos, value);
6222 }
6223 
6224 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6225  * to be equal to "v".
6226  */
isl_basic_map_fix_val(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6227 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6228 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6229 {
6230 	if (!bmap || !v)
6231 		goto error;
6232 	if (!isl_val_is_int(v))
6233 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6234 			"expecting integer value", goto error);
6235 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6236 		goto error;
6237 	pos += isl_basic_map_offset(bmap, type);
6238 	bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6239 	isl_val_free(v);
6240 	return bmap;
6241 error:
6242 	isl_basic_map_free(bmap);
6243 	isl_val_free(v);
6244 	return NULL;
6245 }
6246 
6247 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6248  * to be equal to "v".
6249  */
isl_basic_set_fix_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6250 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6251 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6252 {
6253 	return isl_basic_map_fix_val(bset, type, pos, v);
6254 }
6255 
isl_basic_set_fix_si(struct isl_basic_set * bset,enum isl_dim_type type,unsigned pos,int value)6256 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
6257 		enum isl_dim_type type, unsigned pos, int value)
6258 {
6259 	return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6260 						    type, pos, value));
6261 }
6262 
isl_basic_set_fix(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value)6263 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6264 		enum isl_dim_type type, unsigned pos, isl_int value)
6265 {
6266 	return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6267 						    type, pos, value));
6268 }
6269 
isl_basic_map_fix_input_si(struct isl_basic_map * bmap,unsigned input,int value)6270 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
6271 		unsigned input, int value)
6272 {
6273 	return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
6274 }
6275 
isl_basic_set_fix_dim_si(struct isl_basic_set * bset,unsigned dim,int value)6276 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
6277 		unsigned dim, int value)
6278 {
6279 	return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6280 					isl_dim_set, dim, value));
6281 }
6282 
6283 /* Remove the basic map at position "i" from "map" if this basic map
6284  * is (obviously) empty.
6285  */
remove_if_empty(__isl_take isl_map * map,int i)6286 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6287 {
6288 	isl_bool empty;
6289 
6290 	if (!map)
6291 		return NULL;
6292 
6293 	empty = isl_basic_map_plain_is_empty(map->p[i]);
6294 	if (empty < 0)
6295 		return isl_map_free(map);
6296 	if (!empty)
6297 		return map;
6298 
6299 	isl_basic_map_free(map->p[i]);
6300 	map->n--;
6301 	if (i != map->n) {
6302 		map->p[i] = map->p[map->n];
6303 		map = isl_map_unmark_normalized(map);
6304 
6305 	}
6306 
6307 	return map;
6308 }
6309 
6310 /* Perform "fn" on each basic map of "map", where we may not be holding
6311  * the only reference to "map".
6312  * In particular, "fn" should be a semantics preserving operation
6313  * that we want to apply to all copies of "map".  We therefore need
6314  * to be careful not to modify "map" in a way that breaks "map"
6315  * in case anything goes wrong.
6316  */
isl_map_inline_foreach_basic_map(__isl_take isl_map * map,__isl_give isl_basic_map * (* fn)(__isl_take isl_basic_map * bmap))6317 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6318 	__isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6319 {
6320 	struct isl_basic_map *bmap;
6321 	int i;
6322 
6323 	if (!map)
6324 		return NULL;
6325 
6326 	for (i = map->n - 1; i >= 0; --i) {
6327 		bmap = isl_basic_map_copy(map->p[i]);
6328 		bmap = fn(bmap);
6329 		if (!bmap)
6330 			goto error;
6331 		isl_basic_map_free(map->p[i]);
6332 		map->p[i] = bmap;
6333 		map = remove_if_empty(map, i);
6334 		if (!map)
6335 			return NULL;
6336 	}
6337 
6338 	return map;
6339 error:
6340 	isl_map_free(map);
6341 	return NULL;
6342 }
6343 
isl_map_fix_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6344 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6345 		enum isl_dim_type type, unsigned pos, int value)
6346 {
6347 	int i;
6348 
6349 	map = isl_map_cow(map);
6350 	if (!map)
6351 		return NULL;
6352 
6353 	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6354 	for (i = map->n - 1; i >= 0; --i) {
6355 		map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6356 		map = remove_if_empty(map, i);
6357 		if (!map)
6358 			return NULL;
6359 	}
6360 	map = isl_map_unmark_normalized(map);
6361 	return map;
6362 error:
6363 	isl_map_free(map);
6364 	return NULL;
6365 }
6366 
isl_set_fix_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6367 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6368 		enum isl_dim_type type, unsigned pos, int value)
6369 {
6370 	return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6371 }
6372 
isl_map_fix(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6373 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6374 		enum isl_dim_type type, unsigned pos, isl_int value)
6375 {
6376 	int i;
6377 
6378 	map = isl_map_cow(map);
6379 	if (!map)
6380 		return NULL;
6381 
6382 	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6383 	for (i = 0; i < map->n; ++i) {
6384 		map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6385 		if (!map->p[i])
6386 			goto error;
6387 	}
6388 	map = isl_map_unmark_normalized(map);
6389 	return map;
6390 error:
6391 	isl_map_free(map);
6392 	return NULL;
6393 }
6394 
isl_set_fix(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6395 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6396 		enum isl_dim_type type, unsigned pos, isl_int value)
6397 {
6398 	return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6399 }
6400 
6401 /* Fix the value of the variable at position "pos" of type "type" of "map"
6402  * to be equal to "v".
6403  */
isl_map_fix_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6404 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6405 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6406 {
6407 	int i;
6408 
6409 	map = isl_map_cow(map);
6410 	if (!map || !v)
6411 		goto error;
6412 
6413 	if (!isl_val_is_int(v))
6414 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
6415 			"expecting integer value", goto error);
6416 	if (pos >= isl_map_dim(map, type))
6417 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
6418 			"index out of bounds", goto error);
6419 	for (i = map->n - 1; i >= 0; --i) {
6420 		map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6421 							isl_val_copy(v));
6422 		map = remove_if_empty(map, i);
6423 		if (!map)
6424 			goto error;
6425 	}
6426 	map = isl_map_unmark_normalized(map);
6427 	isl_val_free(v);
6428 	return map;
6429 error:
6430 	isl_map_free(map);
6431 	isl_val_free(v);
6432 	return NULL;
6433 }
6434 
6435 /* Fix the value of the variable at position "pos" of type "type" of "set"
6436  * to be equal to "v".
6437  */
isl_set_fix_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6438 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6439 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6440 {
6441 	return isl_map_fix_val(set, type, pos, v);
6442 }
6443 
isl_map_fix_input_si(struct isl_map * map,unsigned input,int value)6444 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
6445 		unsigned input, int value)
6446 {
6447 	return isl_map_fix_si(map, isl_dim_in, input, value);
6448 }
6449 
isl_set_fix_dim_si(struct isl_set * set,unsigned dim,int value)6450 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
6451 {
6452 	return set_from_map(isl_map_fix_si(set_to_map(set),
6453 						isl_dim_set, dim, value));
6454 }
6455 
basic_map_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value,int upper)6456 static __isl_give isl_basic_map *basic_map_bound_si(
6457 	__isl_take isl_basic_map *bmap,
6458 	enum isl_dim_type type, unsigned pos, int value, int upper)
6459 {
6460 	int j;
6461 
6462 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6463 		return isl_basic_map_free(bmap);
6464 	pos += isl_basic_map_offset(bmap, type);
6465 	bmap = isl_basic_map_cow(bmap);
6466 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6467 	j = isl_basic_map_alloc_inequality(bmap);
6468 	if (j < 0)
6469 		goto error;
6470 	isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6471 	if (upper) {
6472 		isl_int_set_si(bmap->ineq[j][pos], -1);
6473 		isl_int_set_si(bmap->ineq[j][0], value);
6474 	} else {
6475 		isl_int_set_si(bmap->ineq[j][pos], 1);
6476 		isl_int_set_si(bmap->ineq[j][0], -value);
6477 	}
6478 	bmap = isl_basic_map_simplify(bmap);
6479 	return isl_basic_map_finalize(bmap);
6480 error:
6481 	isl_basic_map_free(bmap);
6482 	return NULL;
6483 }
6484 
isl_basic_map_lower_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6485 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6486 	__isl_take isl_basic_map *bmap,
6487 	enum isl_dim_type type, unsigned pos, int value)
6488 {
6489 	return basic_map_bound_si(bmap, type, pos, value, 0);
6490 }
6491 
6492 /* Constrain the values of the given dimension to be no greater than "value".
6493  */
isl_basic_map_upper_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6494 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6495 	__isl_take isl_basic_map *bmap,
6496 	enum isl_dim_type type, unsigned pos, int value)
6497 {
6498 	return basic_map_bound_si(bmap, type, pos, value, 1);
6499 }
6500 
map_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value,int upper)6501 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6502 	enum isl_dim_type type, unsigned pos, int value, int upper)
6503 {
6504 	int i;
6505 
6506 	map = isl_map_cow(map);
6507 	if (!map)
6508 		return NULL;
6509 
6510 	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6511 	for (i = 0; i < map->n; ++i) {
6512 		map->p[i] = basic_map_bound_si(map->p[i],
6513 						 type, pos, value, upper);
6514 		if (!map->p[i])
6515 			goto error;
6516 	}
6517 	map = isl_map_unmark_normalized(map);
6518 	return map;
6519 error:
6520 	isl_map_free(map);
6521 	return NULL;
6522 }
6523 
isl_map_lower_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6524 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6525 	enum isl_dim_type type, unsigned pos, int value)
6526 {
6527 	return map_bound_si(map, type, pos, value, 0);
6528 }
6529 
isl_map_upper_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6530 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6531 	enum isl_dim_type type, unsigned pos, int value)
6532 {
6533 	return map_bound_si(map, type, pos, value, 1);
6534 }
6535 
isl_set_lower_bound_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6536 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6537 		enum isl_dim_type type, unsigned pos, int value)
6538 {
6539 	return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6540 							type, pos, value));
6541 }
6542 
isl_set_upper_bound_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6543 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6544 	enum isl_dim_type type, unsigned pos, int value)
6545 {
6546 	return isl_map_upper_bound_si(set, type, pos, value);
6547 }
6548 
6549 /* Bound the given variable of "bmap" from below (or above is "upper"
6550  * is set) to "value".
6551  */
basic_map_bound(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6552 static __isl_give isl_basic_map *basic_map_bound(
6553 	__isl_take isl_basic_map *bmap,
6554 	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6555 {
6556 	int j;
6557 
6558 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6559 		return isl_basic_map_free(bmap);
6560 	pos += isl_basic_map_offset(bmap, type);
6561 	bmap = isl_basic_map_cow(bmap);
6562 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6563 	j = isl_basic_map_alloc_inequality(bmap);
6564 	if (j < 0)
6565 		goto error;
6566 	isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6567 	if (upper) {
6568 		isl_int_set_si(bmap->ineq[j][pos], -1);
6569 		isl_int_set(bmap->ineq[j][0], value);
6570 	} else {
6571 		isl_int_set_si(bmap->ineq[j][pos], 1);
6572 		isl_int_neg(bmap->ineq[j][0], value);
6573 	}
6574 	bmap = isl_basic_map_simplify(bmap);
6575 	return isl_basic_map_finalize(bmap);
6576 error:
6577 	isl_basic_map_free(bmap);
6578 	return NULL;
6579 }
6580 
6581 /* Bound the given variable of "map" from below (or above is "upper"
6582  * is set) to "value".
6583  */
map_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6584 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6585 	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6586 {
6587 	int i;
6588 
6589 	map = isl_map_cow(map);
6590 	if (!map)
6591 		return NULL;
6592 
6593 	if (pos >= isl_map_dim(map, type))
6594 		isl_die(map->ctx, isl_error_invalid,
6595 			"index out of bounds", goto error);
6596 	for (i = map->n - 1; i >= 0; --i) {
6597 		map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6598 		map = remove_if_empty(map, i);
6599 		if (!map)
6600 			return NULL;
6601 	}
6602 	map = isl_map_unmark_normalized(map);
6603 	return map;
6604 error:
6605 	isl_map_free(map);
6606 	return NULL;
6607 }
6608 
isl_map_lower_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6609 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6610 	enum isl_dim_type type, unsigned pos, isl_int value)
6611 {
6612 	return map_bound(map, type, pos, value, 0);
6613 }
6614 
isl_map_upper_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6615 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6616 	enum isl_dim_type type, unsigned pos, isl_int value)
6617 {
6618 	return map_bound(map, type, pos, value, 1);
6619 }
6620 
isl_set_lower_bound(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6621 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6622 	enum isl_dim_type type, unsigned pos, isl_int value)
6623 {
6624 	return isl_map_lower_bound(set, type, pos, value);
6625 }
6626 
isl_set_upper_bound(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6627 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6628 	enum isl_dim_type type, unsigned pos, isl_int value)
6629 {
6630 	return isl_map_upper_bound(set, type, pos, value);
6631 }
6632 
6633 /* Force the values of the variable at position "pos" of type "type" of "set"
6634  * to be no smaller than "value".
6635  */
isl_set_lower_bound_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6636 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6637 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6638 {
6639 	if (!value)
6640 		goto error;
6641 	if (!isl_val_is_int(value))
6642 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
6643 			"expecting integer value", goto error);
6644 	set = isl_set_lower_bound(set, type, pos, value->n);
6645 	isl_val_free(value);
6646 	return set;
6647 error:
6648 	isl_val_free(value);
6649 	isl_set_free(set);
6650 	return NULL;
6651 }
6652 
6653 /* Force the values of the variable at position "pos" of type "type" of "set"
6654  * to be no greater than "value".
6655  */
isl_set_upper_bound_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6656 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6657 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6658 {
6659 	if (!value)
6660 		goto error;
6661 	if (!isl_val_is_int(value))
6662 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
6663 			"expecting integer value", goto error);
6664 	set = isl_set_upper_bound(set, type, pos, value->n);
6665 	isl_val_free(value);
6666 	return set;
6667 error:
6668 	isl_val_free(value);
6669 	isl_set_free(set);
6670 	return NULL;
6671 }
6672 
6673 /* Bound the given variable of "bset" from below (or above is "upper"
6674  * is set) to "value".
6675  */
isl_basic_set_bound(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6676 static __isl_give isl_basic_set *isl_basic_set_bound(
6677 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6678 	isl_int value, int upper)
6679 {
6680 	return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
6681 						type, pos, value, upper));
6682 }
6683 
6684 /* Bound the given variable of "bset" from below (or above is "upper"
6685  * is set) to "value".
6686  */
isl_basic_set_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value,int upper)6687 static __isl_give isl_basic_set *isl_basic_set_bound_val(
6688 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6689 	__isl_take isl_val *value, int upper)
6690 {
6691 	if (!value)
6692 		goto error;
6693 	if (!isl_val_is_int(value))
6694 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
6695 			"expecting integer value", goto error);
6696 	bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
6697 	isl_val_free(value);
6698 	return bset;
6699 error:
6700 	isl_val_free(value);
6701 	isl_basic_set_free(bset);
6702 	return NULL;
6703 }
6704 
6705 /* Bound the given variable of "bset" from below to "value".
6706  */
isl_basic_set_lower_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6707 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
6708 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6709 	__isl_take isl_val *value)
6710 {
6711 	return isl_basic_set_bound_val(bset, type, pos, value, 0);
6712 }
6713 
6714 /* Bound the given variable of "bset" from above to "value".
6715  */
isl_basic_set_upper_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6716 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
6717 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6718 	__isl_take isl_val *value)
6719 {
6720 	return isl_basic_set_bound_val(bset, type, pos, value, 1);
6721 }
6722 
isl_map_reverse(__isl_take isl_map * map)6723 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
6724 {
6725 	int i;
6726 
6727 	map = isl_map_cow(map);
6728 	if (!map)
6729 		return NULL;
6730 
6731 	map->dim = isl_space_reverse(map->dim);
6732 	if (!map->dim)
6733 		goto error;
6734 	for (i = 0; i < map->n; ++i) {
6735 		map->p[i] = isl_basic_map_reverse(map->p[i]);
6736 		if (!map->p[i])
6737 			goto error;
6738 	}
6739 	map = isl_map_unmark_normalized(map);
6740 	return map;
6741 error:
6742 	isl_map_free(map);
6743 	return NULL;
6744 }
6745 
6746 #undef TYPE
6747 #define TYPE	isl_pw_multi_aff
6748 #undef SUFFIX
6749 #define SUFFIX	_pw_multi_aff
6750 #undef EMPTY
6751 #define EMPTY	isl_pw_multi_aff_empty
6752 #undef ADD
6753 #define ADD	isl_pw_multi_aff_union_add
6754 #include "isl_map_lexopt_templ.c"
6755 
6756 /* Given a map "map", compute the lexicographically minimal
6757  * (or maximal) image element for each domain element in dom,
6758  * in the form of an isl_pw_multi_aff.
6759  * If "empty" is not NULL, then set *empty to those elements in dom that
6760  * do not have an image element.
6761  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6762  * should be computed over the domain of "map".  "empty" is also NULL
6763  * in this case.
6764  *
6765  * We first compute the lexicographically minimal or maximal element
6766  * in the first basic map.  This results in a partial solution "res"
6767  * and a subset "todo" of dom that still need to be handled.
6768  * We then consider each of the remaining maps in "map" and successively
6769  * update both "res" and "todo".
6770  * If "empty" is NULL, then the todo sets are not needed and therefore
6771  * also not computed.
6772  */
isl_map_partial_lexopt_aligned_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty,unsigned flags)6773 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6774 	__isl_take isl_map *map, __isl_take isl_set *dom,
6775 	__isl_give isl_set **empty, unsigned flags)
6776 {
6777 	int i;
6778 	int full;
6779 	isl_pw_multi_aff *res;
6780 	isl_set *todo;
6781 
6782 	full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6783 	if (!map || (!full && !dom))
6784 		goto error;
6785 
6786 	if (isl_map_plain_is_empty(map)) {
6787 		if (empty)
6788 			*empty = dom;
6789 		else
6790 			isl_set_free(dom);
6791 		return isl_pw_multi_aff_from_map(map);
6792 	}
6793 
6794 	res = basic_map_partial_lexopt_pw_multi_aff(
6795 					    isl_basic_map_copy(map->p[0]),
6796 					    isl_set_copy(dom), empty, flags);
6797 
6798 	if (empty)
6799 		todo = *empty;
6800 	for (i = 1; i < map->n; ++i) {
6801 		isl_pw_multi_aff *res_i;
6802 
6803 		res_i = basic_map_partial_lexopt_pw_multi_aff(
6804 					    isl_basic_map_copy(map->p[i]),
6805 					    isl_set_copy(dom), empty, flags);
6806 
6807 		if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6808 			res = isl_pw_multi_aff_union_lexmax(res, res_i);
6809 		else
6810 			res = isl_pw_multi_aff_union_lexmin(res, res_i);
6811 
6812 		if (empty)
6813 			todo = isl_set_intersect(todo, *empty);
6814 	}
6815 
6816 	isl_set_free(dom);
6817 	isl_map_free(map);
6818 
6819 	if (empty)
6820 		*empty = todo;
6821 
6822 	return res;
6823 error:
6824 	if (empty)
6825 		*empty = NULL;
6826 	isl_set_free(dom);
6827 	isl_map_free(map);
6828 	return NULL;
6829 }
6830 
6831 #undef TYPE
6832 #define TYPE	isl_map
6833 #undef SUFFIX
6834 #define SUFFIX
6835 #undef EMPTY
6836 #define EMPTY	isl_map_empty
6837 #undef ADD
6838 #define ADD	isl_map_union_disjoint
6839 #include "isl_map_lexopt_templ.c"
6840 
6841 /* Given a map "map", compute the lexicographically minimal
6842  * (or maximal) image element for each domain element in "dom",
6843  * in the form of an isl_map.
6844  * If "empty" is not NULL, then set *empty to those elements in "dom" that
6845  * do not have an image element.
6846  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6847  * should be computed over the domain of "map".  "empty" is also NULL
6848  * in this case.
6849  *
6850  * If the input consists of more than one disjunct, then first
6851  * compute the desired result in the form of an isl_pw_multi_aff and
6852  * then convert that into an isl_map.
6853  *
6854  * This function used to have an explicit implementation in terms
6855  * of isl_maps, but it would continually intersect the domains of
6856  * partial results with the complement of the domain of the next
6857  * partial solution, potentially leading to an explosion in the number
6858  * of disjuncts if there are several disjuncts in the input.
6859  * An even earlier implementation of this function would look for
6860  * better results in the domain of the partial result and for extra
6861  * results in the complement of this domain, which would lead to
6862  * even more splintering.
6863  */
isl_map_partial_lexopt_aligned(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty,unsigned flags)6864 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6865 	__isl_take isl_map *map, __isl_take isl_set *dom,
6866 	__isl_give isl_set **empty, unsigned flags)
6867 {
6868 	int full;
6869 	struct isl_map *res;
6870 	isl_pw_multi_aff *pma;
6871 
6872 	full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6873 	if (!map || (!full && !dom))
6874 		goto error;
6875 
6876 	if (isl_map_plain_is_empty(map)) {
6877 		if (empty)
6878 			*empty = dom;
6879 		else
6880 			isl_set_free(dom);
6881 		return map;
6882 	}
6883 
6884 	if (map->n == 1) {
6885 		res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6886 						dom, empty, flags);
6887 		isl_map_free(map);
6888 		return res;
6889 	}
6890 
6891 	pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6892 							flags);
6893 	return isl_map_from_pw_multi_aff(pma);
6894 error:
6895 	if (empty)
6896 		*empty = NULL;
6897 	isl_set_free(dom);
6898 	isl_map_free(map);
6899 	return NULL;
6900 }
6901 
isl_map_partial_lexmax(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)6902 __isl_give isl_map *isl_map_partial_lexmax(
6903 		__isl_take isl_map *map, __isl_take isl_set *dom,
6904 		__isl_give isl_set **empty)
6905 {
6906 	return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6907 }
6908 
isl_map_partial_lexmin(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)6909 __isl_give isl_map *isl_map_partial_lexmin(
6910 		__isl_take isl_map *map, __isl_take isl_set *dom,
6911 		__isl_give isl_set **empty)
6912 {
6913 	return isl_map_partial_lexopt(map, dom, empty, 0);
6914 }
6915 
isl_set_partial_lexmin(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)6916 __isl_give isl_set *isl_set_partial_lexmin(
6917 		__isl_take isl_set *set, __isl_take isl_set *dom,
6918 		__isl_give isl_set **empty)
6919 {
6920 	return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6921 						    dom, empty));
6922 }
6923 
isl_set_partial_lexmax(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)6924 __isl_give isl_set *isl_set_partial_lexmax(
6925 		__isl_take isl_set *set, __isl_take isl_set *dom,
6926 		__isl_give isl_set **empty)
6927 {
6928 	return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6929 						    dom, empty));
6930 }
6931 
6932 /* Compute the lexicographic minimum (or maximum if "flags" includes
6933  * ISL_OPT_MAX) of "bset" over its parametric domain.
6934  */
isl_basic_set_lexopt(__isl_take isl_basic_set * bset,unsigned flags)6935 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6936 	unsigned flags)
6937 {
6938 	return isl_basic_map_lexopt(bset, flags);
6939 }
6940 
isl_basic_map_lexmax(__isl_take isl_basic_map * bmap)6941 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6942 {
6943 	return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6944 }
6945 
isl_basic_set_lexmin(__isl_take isl_basic_set * bset)6946 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6947 {
6948 	return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6949 }
6950 
isl_basic_set_lexmax(__isl_take isl_basic_set * bset)6951 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6952 {
6953 	return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6954 }
6955 
6956 /* Compute the lexicographic minimum of "bset" over its parametric domain
6957  * for the purpose of quantifier elimination.
6958  * That is, find an explicit representation for all the existentially
6959  * quantified variables in "bset" by computing their lexicographic
6960  * minimum.
6961  */
isl_basic_set_lexmin_compute_divs(__isl_take isl_basic_set * bset)6962 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6963 	__isl_take isl_basic_set *bset)
6964 {
6965 	return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6966 }
6967 
6968 /* Given a basic map with one output dimension, compute the minimum or
6969  * maximum of that dimension as an isl_pw_aff.
6970  *
6971  * Compute the optimum as a lexicographic optimum over the single
6972  * output dimension and extract the single isl_pw_aff from the result.
6973  */
basic_map_dim_opt(__isl_keep isl_basic_map * bmap,int max)6974 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6975 	int max)
6976 {
6977 	isl_pw_multi_aff *pma;
6978 	isl_pw_aff *pwaff;
6979 
6980 	bmap = isl_basic_map_copy(bmap);
6981 	pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
6982 	pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
6983 	isl_pw_multi_aff_free(pma);
6984 
6985 	return pwaff;
6986 }
6987 
6988 /* Compute the minimum or maximum of the given output dimension
6989  * as a function of the parameters and the input dimensions,
6990  * but independently of the other output dimensions.
6991  *
6992  * We first project out the other output dimension and then compute
6993  * the "lexicographic" maximum in each basic map, combining the results
6994  * using isl_pw_aff_union_max.
6995  */
map_dim_opt(__isl_take isl_map * map,int pos,int max)6996 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6997 	int max)
6998 {
6999 	int i;
7000 	isl_pw_aff *pwaff;
7001 	unsigned n_out;
7002 
7003 	n_out = isl_map_dim(map, isl_dim_out);
7004 	map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7005 	map = isl_map_project_out(map, isl_dim_out, 0, pos);
7006 	if (!map)
7007 		return NULL;
7008 
7009 	if (map->n == 0) {
7010 		isl_space *dim = isl_map_get_space(map);
7011 		isl_map_free(map);
7012 		return isl_pw_aff_empty(dim);
7013 	}
7014 
7015 	pwaff = basic_map_dim_opt(map->p[0], max);
7016 	for (i = 1; i < map->n; ++i) {
7017 		isl_pw_aff *pwaff_i;
7018 
7019 		pwaff_i = basic_map_dim_opt(map->p[i], max);
7020 		pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7021 	}
7022 
7023 	isl_map_free(map);
7024 
7025 	return pwaff;
7026 }
7027 
7028 /* Compute the minimum of the given output dimension as a function of the
7029  * parameters and input dimensions, but independently of
7030  * the other output dimensions.
7031  */
isl_map_dim_min(__isl_take isl_map * map,int pos)7032 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7033 {
7034 	return map_dim_opt(map, pos, 0);
7035 }
7036 
7037 /* Compute the maximum of the given output dimension as a function of the
7038  * parameters and input dimensions, but independently of
7039  * the other output dimensions.
7040  */
isl_map_dim_max(__isl_take isl_map * map,int pos)7041 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7042 {
7043 	return map_dim_opt(map, pos, 1);
7044 }
7045 
7046 /* Compute the minimum or maximum of the given set dimension
7047  * as a function of the parameters,
7048  * but independently of the other set dimensions.
7049  */
set_dim_opt(__isl_take isl_set * set,int pos,int max)7050 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7051 	int max)
7052 {
7053 	return map_dim_opt(set, pos, max);
7054 }
7055 
7056 /* Compute the maximum of the given set dimension as a function of the
7057  * parameters, but independently of the other set dimensions.
7058  */
isl_set_dim_max(__isl_take isl_set * set,int pos)7059 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7060 {
7061 	return set_dim_opt(set, pos, 1);
7062 }
7063 
7064 /* Compute the minimum of the given set dimension as a function of the
7065  * parameters, but independently of the other set dimensions.
7066  */
isl_set_dim_min(__isl_take isl_set * set,int pos)7067 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7068 {
7069 	return set_dim_opt(set, pos, 0);
7070 }
7071 
7072 /* Apply a preimage specified by "mat" on the parameters of "bset".
7073  * bset is assumed to have only parameters and divs.
7074  */
basic_set_parameter_preimage(__isl_take isl_basic_set * bset,__isl_take isl_mat * mat)7075 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7076 	__isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7077 {
7078 	unsigned nparam;
7079 
7080 	if (!bset || !mat)
7081 		goto error;
7082 
7083 	bset->dim = isl_space_cow(bset->dim);
7084 	if (!bset->dim)
7085 		goto error;
7086 
7087 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7088 
7089 	isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7090 
7091 	bset->dim->nparam = 0;
7092 	bset->dim->n_out = nparam;
7093 	bset = isl_basic_set_preimage(bset, mat);
7094 	if (bset) {
7095 		bset->dim->nparam = bset->dim->n_out;
7096 		bset->dim->n_out = 0;
7097 	}
7098 	return bset;
7099 error:
7100 	isl_mat_free(mat);
7101 	isl_basic_set_free(bset);
7102 	return NULL;
7103 }
7104 
7105 /* Apply a preimage specified by "mat" on the parameters of "set".
7106  * set is assumed to have only parameters and divs.
7107  */
set_parameter_preimage(__isl_take isl_set * set,__isl_take isl_mat * mat)7108 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7109 	__isl_take isl_mat *mat)
7110 {
7111 	isl_space *space;
7112 	unsigned nparam;
7113 
7114 	if (!set || !mat)
7115 		goto error;
7116 
7117 	nparam = isl_set_dim(set, isl_dim_param);
7118 
7119 	if (mat->n_row != 1 + nparam)
7120 		isl_die(isl_set_get_ctx(set), isl_error_internal,
7121 			"unexpected number of rows", goto error);
7122 
7123 	space = isl_set_get_space(set);
7124 	space = isl_space_move_dims(space, isl_dim_set, 0,
7125 				    isl_dim_param, 0, nparam);
7126 	set = isl_set_reset_space(set, space);
7127 	set = isl_set_preimage(set, mat);
7128 	nparam = isl_set_dim(set, isl_dim_out);
7129 	space = isl_set_get_space(set);
7130 	space = isl_space_move_dims(space, isl_dim_param, 0,
7131 				    isl_dim_out, 0, nparam);
7132 	set = isl_set_reset_space(set, space);
7133 	return set;
7134 error:
7135 	isl_mat_free(mat);
7136 	isl_set_free(set);
7137 	return NULL;
7138 }
7139 
7140 /* Intersect the basic set "bset" with the affine space specified by the
7141  * equalities in "eq".
7142  */
basic_set_append_equalities(__isl_take isl_basic_set * bset,__isl_take isl_mat * eq)7143 static __isl_give isl_basic_set *basic_set_append_equalities(
7144 	__isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7145 {
7146 	int i, k;
7147 	unsigned len;
7148 
7149 	if (!bset || !eq)
7150 		goto error;
7151 
7152 	bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
7153 					eq->n_row, 0);
7154 	if (!bset)
7155 		goto error;
7156 
7157 	len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
7158 	for (i = 0; i < eq->n_row; ++i) {
7159 		k = isl_basic_set_alloc_equality(bset);
7160 		if (k < 0)
7161 			goto error;
7162 		isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7163 		isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7164 	}
7165 	isl_mat_free(eq);
7166 
7167 	bset = isl_basic_set_gauss(bset, NULL);
7168 	bset = isl_basic_set_finalize(bset);
7169 
7170 	return bset;
7171 error:
7172 	isl_mat_free(eq);
7173 	isl_basic_set_free(bset);
7174 	return NULL;
7175 }
7176 
7177 /* Intersect the set "set" with the affine space specified by the
7178  * equalities in "eq".
7179  */
set_append_equalities(struct isl_set * set,struct isl_mat * eq)7180 static struct isl_set *set_append_equalities(struct isl_set *set,
7181 	struct isl_mat *eq)
7182 {
7183 	int i;
7184 
7185 	if (!set || !eq)
7186 		goto error;
7187 
7188 	for (i = 0; i < set->n; ++i) {
7189 		set->p[i] = basic_set_append_equalities(set->p[i],
7190 					isl_mat_copy(eq));
7191 		if (!set->p[i])
7192 			goto error;
7193 	}
7194 	isl_mat_free(eq);
7195 	return set;
7196 error:
7197 	isl_mat_free(eq);
7198 	isl_set_free(set);
7199 	return NULL;
7200 }
7201 
7202 /* Given a basic set "bset" that only involves parameters and existentially
7203  * quantified variables, return the index of the first equality
7204  * that only involves parameters.  If there is no such equality then
7205  * return bset->n_eq.
7206  *
7207  * This function assumes that isl_basic_set_gauss has been called on "bset".
7208  */
first_parameter_equality(__isl_keep isl_basic_set * bset)7209 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7210 {
7211 	int i, j;
7212 	unsigned nparam, n_div;
7213 
7214 	if (!bset)
7215 		return -1;
7216 
7217 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7218 	n_div = isl_basic_set_dim(bset, isl_dim_div);
7219 
7220 	for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7221 		if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7222 			++i;
7223 	}
7224 
7225 	return i;
7226 }
7227 
7228 /* Compute an explicit representation for the existentially quantified
7229  * variables in "bset" by computing the "minimal value" of the set
7230  * variables.  Since there are no set variables, the computation of
7231  * the minimal value essentially computes an explicit representation
7232  * of the non-empty part(s) of "bset".
7233  *
7234  * The input only involves parameters and existentially quantified variables.
7235  * All equalities among parameters have been removed.
7236  *
7237  * Since the existentially quantified variables in the result are in general
7238  * going to be different from those in the input, we first replace
7239  * them by the minimal number of variables based on their equalities.
7240  * This should simplify the parametric integer programming.
7241  */
base_compute_divs(__isl_take isl_basic_set * bset)7242 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7243 {
7244 	isl_morph *morph1, *morph2;
7245 	isl_set *set;
7246 	unsigned n;
7247 
7248 	if (!bset)
7249 		return NULL;
7250 	if (bset->n_eq == 0)
7251 		return isl_basic_set_lexmin_compute_divs(bset);
7252 
7253 	morph1 = isl_basic_set_parameter_compression(bset);
7254 	bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7255 	bset = isl_basic_set_lift(bset);
7256 	morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7257 	bset = isl_morph_basic_set(morph2, bset);
7258 	n = isl_basic_set_dim(bset, isl_dim_set);
7259 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7260 
7261 	set = isl_basic_set_lexmin_compute_divs(bset);
7262 
7263 	set = isl_morph_set(isl_morph_inverse(morph1), set);
7264 
7265 	return set;
7266 }
7267 
7268 /* Project the given basic set onto its parameter domain, possibly introducing
7269  * new, explicit, existential variables in the constraints.
7270  * The input has parameters and (possibly implicit) existential variables.
7271  * The output has the same parameters, but only
7272  * explicit existentially quantified variables.
7273  *
7274  * The actual projection is performed by pip, but pip doesn't seem
7275  * to like equalities very much, so we first remove the equalities
7276  * among the parameters by performing a variable compression on
7277  * the parameters.  Afterward, an inverse transformation is performed
7278  * and the equalities among the parameters are inserted back in.
7279  *
7280  * The variable compression on the parameters may uncover additional
7281  * equalities that were only implicit before.  We therefore check
7282  * if there are any new parameter equalities in the result and
7283  * if so recurse.  The removal of parameter equalities is required
7284  * for the parameter compression performed by base_compute_divs.
7285  */
parameter_compute_divs(struct isl_basic_set * bset)7286 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
7287 {
7288 	int i;
7289 	struct isl_mat *eq;
7290 	struct isl_mat *T, *T2;
7291 	struct isl_set *set;
7292 	unsigned nparam;
7293 
7294 	bset = isl_basic_set_cow(bset);
7295 	if (!bset)
7296 		return NULL;
7297 
7298 	if (bset->n_eq == 0)
7299 		return base_compute_divs(bset);
7300 
7301 	bset = isl_basic_set_gauss(bset, NULL);
7302 	if (!bset)
7303 		return NULL;
7304 	if (isl_basic_set_plain_is_empty(bset))
7305 		return isl_set_from_basic_set(bset);
7306 
7307 	i = first_parameter_equality(bset);
7308 	if (i == bset->n_eq)
7309 		return base_compute_divs(bset);
7310 
7311 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7312 	eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7313 		0, 1 + nparam);
7314 	eq = isl_mat_cow(eq);
7315 	T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7316 	if (T && T->n_col == 0) {
7317 		isl_mat_free(T);
7318 		isl_mat_free(T2);
7319 		isl_mat_free(eq);
7320 		bset = isl_basic_set_set_to_empty(bset);
7321 		return isl_set_from_basic_set(bset);
7322 	}
7323 	bset = basic_set_parameter_preimage(bset, T);
7324 
7325 	i = first_parameter_equality(bset);
7326 	if (!bset)
7327 		set = NULL;
7328 	else if (i == bset->n_eq)
7329 		set = base_compute_divs(bset);
7330 	else
7331 		set = parameter_compute_divs(bset);
7332 	set = set_parameter_preimage(set, T2);
7333 	set = set_append_equalities(set, eq);
7334 	return set;
7335 }
7336 
7337 /* Insert the divs from "ls" before those of "bmap".
7338  *
7339  * The number of columns is not changed, which means that the last
7340  * dimensions of "bmap" are being reintepreted as the divs from "ls".
7341  * The caller is responsible for removing the same number of dimensions
7342  * from the space of "bmap".
7343  */
insert_divs_from_local_space(__isl_take isl_basic_map * bmap,__isl_keep isl_local_space * ls)7344 static __isl_give isl_basic_map *insert_divs_from_local_space(
7345 	__isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7346 {
7347 	int i;
7348 	int n_div;
7349 	int old_n_div;
7350 
7351 	n_div = isl_local_space_dim(ls, isl_dim_div);
7352 	if (n_div == 0)
7353 		return bmap;
7354 
7355 	old_n_div = bmap->n_div;
7356 	bmap = insert_div_rows(bmap, n_div);
7357 	if (!bmap)
7358 		return NULL;
7359 
7360 	for (i = 0; i < n_div; ++i) {
7361 		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7362 		isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7363 	}
7364 
7365 	return bmap;
7366 }
7367 
7368 /* Replace the space of "bmap" by the space and divs of "ls".
7369  *
7370  * If "ls" has any divs, then we simplify the result since we may
7371  * have discovered some additional equalities that could simplify
7372  * the div expressions.
7373  */
basic_replace_space_by_local_space(__isl_take isl_basic_map * bmap,__isl_take isl_local_space * ls)7374 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7375 	__isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7376 {
7377 	int n_div;
7378 
7379 	bmap = isl_basic_map_cow(bmap);
7380 	if (!bmap || !ls)
7381 		goto error;
7382 
7383 	n_div = isl_local_space_dim(ls, isl_dim_div);
7384 	bmap = insert_divs_from_local_space(bmap, ls);
7385 	if (!bmap)
7386 		goto error;
7387 
7388 	isl_space_free(bmap->dim);
7389 	bmap->dim = isl_local_space_get_space(ls);
7390 	if (!bmap->dim)
7391 		goto error;
7392 
7393 	isl_local_space_free(ls);
7394 	if (n_div > 0)
7395 		bmap = isl_basic_map_simplify(bmap);
7396 	bmap = isl_basic_map_finalize(bmap);
7397 	return bmap;
7398 error:
7399 	isl_basic_map_free(bmap);
7400 	isl_local_space_free(ls);
7401 	return NULL;
7402 }
7403 
7404 /* Replace the space of "map" by the space and divs of "ls".
7405  */
replace_space_by_local_space(__isl_take isl_map * map,__isl_take isl_local_space * ls)7406 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7407 	__isl_take isl_local_space *ls)
7408 {
7409 	int i;
7410 
7411 	map = isl_map_cow(map);
7412 	if (!map || !ls)
7413 		goto error;
7414 
7415 	for (i = 0; i < map->n; ++i) {
7416 		map->p[i] = basic_replace_space_by_local_space(map->p[i],
7417 						    isl_local_space_copy(ls));
7418 		if (!map->p[i])
7419 			goto error;
7420 	}
7421 	isl_space_free(map->dim);
7422 	map->dim = isl_local_space_get_space(ls);
7423 	if (!map->dim)
7424 		goto error;
7425 
7426 	isl_local_space_free(ls);
7427 	return map;
7428 error:
7429 	isl_local_space_free(ls);
7430 	isl_map_free(map);
7431 	return NULL;
7432 }
7433 
7434 /* Compute an explicit representation for the existentially
7435  * quantified variables for which do not know any explicit representation yet.
7436  *
7437  * We first sort the existentially quantified variables so that the
7438  * existentially quantified variables for which we already have an explicit
7439  * representation are placed before those for which we do not.
7440  * The input dimensions, the output dimensions and the existentially
7441  * quantified variables for which we already have an explicit
7442  * representation are then turned into parameters.
7443  * compute_divs returns a map with the same parameters and
7444  * no input or output dimensions and the dimension specification
7445  * is reset to that of the input, including the existentially quantified
7446  * variables for which we already had an explicit representation.
7447  */
compute_divs(struct isl_basic_map * bmap)7448 static struct isl_map *compute_divs(struct isl_basic_map *bmap)
7449 {
7450 	struct isl_basic_set *bset;
7451 	struct isl_set *set;
7452 	struct isl_map *map;
7453 	isl_space *dim;
7454 	isl_local_space *ls;
7455 	unsigned	 nparam;
7456 	unsigned	 n_in;
7457 	unsigned	 n_out;
7458 	int n_known;
7459 	int i;
7460 
7461 	bmap = isl_basic_map_sort_divs(bmap);
7462 	bmap = isl_basic_map_cow(bmap);
7463 	if (!bmap)
7464 		return NULL;
7465 
7466 	n_known = isl_basic_map_first_unknown_div(bmap);
7467 	if (n_known < 0)
7468 		return isl_map_from_basic_map(isl_basic_map_free(bmap));
7469 
7470 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
7471 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
7472 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
7473 	dim = isl_space_set_alloc(bmap->ctx,
7474 				    nparam + n_in + n_out + n_known, 0);
7475 	if (!dim)
7476 		goto error;
7477 
7478 	ls = isl_basic_map_get_local_space(bmap);
7479 	ls = isl_local_space_drop_dims(ls, isl_dim_div,
7480 					n_known, bmap->n_div - n_known);
7481 	if (n_known > 0) {
7482 		for (i = n_known; i < bmap->n_div; ++i)
7483 			swap_div(bmap, i - n_known, i);
7484 		bmap->n_div -= n_known;
7485 		bmap->extra -= n_known;
7486 	}
7487 	bmap = isl_basic_map_reset_space(bmap, dim);
7488 	bset = bset_from_bmap(bmap);
7489 
7490 	set = parameter_compute_divs(bset);
7491 	map = set_to_map(set);
7492 	map = replace_space_by_local_space(map, ls);
7493 
7494 	return map;
7495 error:
7496 	isl_basic_map_free(bmap);
7497 	return NULL;
7498 }
7499 
7500 /* Remove the explicit representation of local variable "div",
7501  * if there is any.
7502  */
isl_basic_map_mark_div_unknown(__isl_take isl_basic_map * bmap,int div)7503 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7504 	__isl_take isl_basic_map *bmap, int div)
7505 {
7506 	isl_bool unknown;
7507 
7508 	unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7509 	if (unknown < 0)
7510 		return isl_basic_map_free(bmap);
7511 	if (unknown)
7512 		return bmap;
7513 
7514 	bmap = isl_basic_map_cow(bmap);
7515 	if (!bmap)
7516 		return NULL;
7517 	isl_int_set_si(bmap->div[div][0], 0);
7518 	return bmap;
7519 }
7520 
7521 /* Is local variable "div" of "bmap" marked as not having an explicit
7522  * representation?
7523  * Note that even if "div" is not marked in this way and therefore
7524  * has an explicit representation, this representation may still
7525  * depend (indirectly) on other local variables that do not
7526  * have an explicit representation.
7527  */
isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map * bmap,int div)7528 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7529 	int div)
7530 {
7531 	if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7532 		return isl_bool_error;
7533 	return isl_int_is_zero(bmap->div[div][0]);
7534 }
7535 
7536 /* Return the position of the first local variable that does not
7537  * have an explicit representation.
7538  * Return the total number of local variables if they all have
7539  * an explicit representation.
7540  * Return -1 on error.
7541  */
isl_basic_map_first_unknown_div(__isl_keep isl_basic_map * bmap)7542 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7543 {
7544 	int i;
7545 
7546 	if (!bmap)
7547 		return -1;
7548 
7549 	for (i = 0; i < bmap->n_div; ++i) {
7550 		if (!isl_basic_map_div_is_known(bmap, i))
7551 			return i;
7552 	}
7553 	return bmap->n_div;
7554 }
7555 
7556 /* Return the position of the first local variable that does not
7557  * have an explicit representation.
7558  * Return the total number of local variables if they all have
7559  * an explicit representation.
7560  * Return -1 on error.
7561  */
isl_basic_set_first_unknown_div(__isl_keep isl_basic_set * bset)7562 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7563 {
7564 	return isl_basic_map_first_unknown_div(bset);
7565 }
7566 
7567 /* Does "bmap" have an explicit representation for all local variables?
7568  */
isl_basic_map_divs_known(__isl_keep isl_basic_map * bmap)7569 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7570 {
7571 	int first, n;
7572 
7573 	n = isl_basic_map_dim(bmap, isl_dim_div);
7574 	first = isl_basic_map_first_unknown_div(bmap);
7575 	if (first < 0)
7576 		return isl_bool_error;
7577 	return first == n;
7578 }
7579 
7580 /* Do all basic maps in "map" have an explicit representation
7581  * for all local variables?
7582  */
isl_map_divs_known(__isl_keep isl_map * map)7583 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7584 {
7585 	int i;
7586 
7587 	if (!map)
7588 		return isl_bool_error;
7589 
7590 	for (i = 0; i < map->n; ++i) {
7591 		int known = isl_basic_map_divs_known(map->p[i]);
7592 		if (known <= 0)
7593 			return known;
7594 	}
7595 
7596 	return isl_bool_true;
7597 }
7598 
7599 /* If bmap contains any unknown divs, then compute explicit
7600  * expressions for them.  However, this computation may be
7601  * quite expensive, so first try to remove divs that aren't
7602  * strictly needed.
7603  */
isl_basic_map_compute_divs(__isl_take isl_basic_map * bmap)7604 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7605 {
7606 	int known;
7607 	struct isl_map *map;
7608 
7609 	known = isl_basic_map_divs_known(bmap);
7610 	if (known < 0)
7611 		goto error;
7612 	if (known)
7613 		return isl_map_from_basic_map(bmap);
7614 
7615 	bmap = isl_basic_map_drop_redundant_divs(bmap);
7616 
7617 	known = isl_basic_map_divs_known(bmap);
7618 	if (known < 0)
7619 		goto error;
7620 	if (known)
7621 		return isl_map_from_basic_map(bmap);
7622 
7623 	map = compute_divs(bmap);
7624 	return map;
7625 error:
7626 	isl_basic_map_free(bmap);
7627 	return NULL;
7628 }
7629 
isl_map_compute_divs(__isl_take isl_map * map)7630 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7631 {
7632 	int i;
7633 	int known;
7634 	struct isl_map *res;
7635 
7636 	if (!map)
7637 		return NULL;
7638 	if (map->n == 0)
7639 		return map;
7640 
7641 	known = isl_map_divs_known(map);
7642 	if (known < 0) {
7643 		isl_map_free(map);
7644 		return NULL;
7645 	}
7646 	if (known)
7647 		return map;
7648 
7649 	res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7650 	for (i = 1 ; i < map->n; ++i) {
7651 		struct isl_map *r2;
7652 		r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7653 		if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7654 			res = isl_map_union_disjoint(res, r2);
7655 		else
7656 			res = isl_map_union(res, r2);
7657 	}
7658 	isl_map_free(map);
7659 
7660 	return res;
7661 }
7662 
isl_basic_set_compute_divs(__isl_take isl_basic_set * bset)7663 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
7664 {
7665 	return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7666 }
7667 
isl_set_compute_divs(struct isl_set * set)7668 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7669 {
7670 	return set_from_map(isl_map_compute_divs(set_to_map(set)));
7671 }
7672 
isl_map_domain(__isl_take isl_map * map)7673 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
7674 {
7675 	int i;
7676 	struct isl_set *set;
7677 
7678 	if (!map)
7679 		goto error;
7680 
7681 	map = isl_map_cow(map);
7682 	if (!map)
7683 		return NULL;
7684 
7685 	set = set_from_map(map);
7686 	set->dim = isl_space_domain(set->dim);
7687 	if (!set->dim)
7688 		goto error;
7689 	for (i = 0; i < map->n; ++i) {
7690 		set->p[i] = isl_basic_map_domain(map->p[i]);
7691 		if (!set->p[i])
7692 			goto error;
7693 	}
7694 	ISL_F_CLR(set, ISL_MAP_DISJOINT);
7695 	ISL_F_CLR(set, ISL_SET_NORMALIZED);
7696 	return set;
7697 error:
7698 	isl_map_free(map);
7699 	return NULL;
7700 }
7701 
7702 /* Return the union of "map1" and "map2", where we assume for now that
7703  * "map1" and "map2" are disjoint.  Note that the basic maps inside
7704  * "map1" or "map2" may not be disjoint from each other.
7705  * Also note that this function is also called from isl_map_union,
7706  * which takes care of handling the situation where "map1" and "map2"
7707  * may not be disjoint.
7708  *
7709  * If one of the inputs is empty, we can simply return the other input.
7710  * Similarly, if one of the inputs is universal, then it is equal to the union.
7711  */
map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)7712 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7713 	__isl_take isl_map *map2)
7714 {
7715 	int i;
7716 	unsigned flags = 0;
7717 	struct isl_map *map = NULL;
7718 	int is_universe;
7719 
7720 	if (!map1 || !map2)
7721 		goto error;
7722 
7723 	if (!isl_space_is_equal(map1->dim, map2->dim))
7724 		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7725 			"spaces don't match", goto error);
7726 
7727 	if (map1->n == 0) {
7728 		isl_map_free(map1);
7729 		return map2;
7730 	}
7731 	if (map2->n == 0) {
7732 		isl_map_free(map2);
7733 		return map1;
7734 	}
7735 
7736 	is_universe = isl_map_plain_is_universe(map1);
7737 	if (is_universe < 0)
7738 		goto error;
7739 	if (is_universe) {
7740 		isl_map_free(map2);
7741 		return map1;
7742 	}
7743 
7744 	is_universe = isl_map_plain_is_universe(map2);
7745 	if (is_universe < 0)
7746 		goto error;
7747 	if (is_universe) {
7748 		isl_map_free(map1);
7749 		return map2;
7750 	}
7751 
7752 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7753 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7754 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7755 
7756 	map = isl_map_alloc_space(isl_space_copy(map1->dim),
7757 				map1->n + map2->n, flags);
7758 	if (!map)
7759 		goto error;
7760 	for (i = 0; i < map1->n; ++i) {
7761 		map = isl_map_add_basic_map(map,
7762 				  isl_basic_map_copy(map1->p[i]));
7763 		if (!map)
7764 			goto error;
7765 	}
7766 	for (i = 0; i < map2->n; ++i) {
7767 		map = isl_map_add_basic_map(map,
7768 				  isl_basic_map_copy(map2->p[i]));
7769 		if (!map)
7770 			goto error;
7771 	}
7772 	isl_map_free(map1);
7773 	isl_map_free(map2);
7774 	return map;
7775 error:
7776 	isl_map_free(map);
7777 	isl_map_free(map1);
7778 	isl_map_free(map2);
7779 	return NULL;
7780 }
7781 
7782 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7783  * guaranteed to be disjoint by the caller.
7784  *
7785  * Note that this functions is called from within isl_map_make_disjoint,
7786  * so we have to be careful not to touch the constraints of the inputs
7787  * in any way.
7788  */
isl_map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)7789 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7790 	__isl_take isl_map *map2)
7791 {
7792 	return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7793 }
7794 
7795 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7796  * not be disjoint.  The parameters are assumed to have been aligned.
7797  *
7798  * We currently simply call map_union_disjoint, the internal operation
7799  * of which does not really depend on the inputs being disjoint.
7800  * If the result contains more than one basic map, then we clear
7801  * the disjoint flag since the result may contain basic maps from
7802  * both inputs and these are not guaranteed to be disjoint.
7803  *
7804  * As a special case, if "map1" and "map2" are obviously equal,
7805  * then we simply return "map1".
7806  */
map_union_aligned(__isl_take isl_map * map1,__isl_take isl_map * map2)7807 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7808 	__isl_take isl_map *map2)
7809 {
7810 	int equal;
7811 
7812 	if (!map1 || !map2)
7813 		goto error;
7814 
7815 	equal = isl_map_plain_is_equal(map1, map2);
7816 	if (equal < 0)
7817 		goto error;
7818 	if (equal) {
7819 		isl_map_free(map2);
7820 		return map1;
7821 	}
7822 
7823 	map1 = map_union_disjoint(map1, map2);
7824 	if (!map1)
7825 		return NULL;
7826 	if (map1->n > 1)
7827 		ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7828 	return map1;
7829 error:
7830 	isl_map_free(map1);
7831 	isl_map_free(map2);
7832 	return NULL;
7833 }
7834 
7835 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7836  * not be disjoint.
7837  */
isl_map_union(__isl_take isl_map * map1,__isl_take isl_map * map2)7838 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7839 	__isl_take isl_map *map2)
7840 {
7841 	return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7842 }
7843 
isl_set_union_disjoint(__isl_take isl_set * set1,__isl_take isl_set * set2)7844 __isl_give isl_set *isl_set_union_disjoint(
7845 	__isl_take isl_set *set1, __isl_take isl_set *set2)
7846 {
7847 	return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7848 						    set_to_map(set2)));
7849 }
7850 
isl_set_union(struct isl_set * set1,struct isl_set * set2)7851 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7852 {
7853 	return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7854 }
7855 
7856 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7857  * the results.
7858  *
7859  * "map" and "set" are assumed to be compatible and non-NULL.
7860  */
map_intersect_set(__isl_take isl_map * map,__isl_take isl_set * set,__isl_give isl_basic_map * fn (__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset))7861 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7862 	__isl_take isl_set *set,
7863 	__isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7864 		__isl_take isl_basic_set *bset))
7865 {
7866 	unsigned flags = 0;
7867 	struct isl_map *result;
7868 	int i, j;
7869 
7870 	if (isl_set_plain_is_universe(set)) {
7871 		isl_set_free(set);
7872 		return map;
7873 	}
7874 
7875 	if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7876 	    ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7877 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7878 
7879 	result = isl_map_alloc_space(isl_space_copy(map->dim),
7880 					map->n * set->n, flags);
7881 	for (i = 0; result && i < map->n; ++i)
7882 		for (j = 0; j < set->n; ++j) {
7883 			result = isl_map_add_basic_map(result,
7884 					fn(isl_basic_map_copy(map->p[i]),
7885 					    isl_basic_set_copy(set->p[j])));
7886 			if (!result)
7887 				break;
7888 		}
7889 
7890 	isl_map_free(map);
7891 	isl_set_free(set);
7892 	return result;
7893 }
7894 
map_intersect_range(__isl_take isl_map * map,__isl_take isl_set * set)7895 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7896 	__isl_take isl_set *set)
7897 {
7898 	isl_bool ok;
7899 
7900 	ok = isl_map_compatible_range(map, set);
7901 	if (ok < 0)
7902 		goto error;
7903 	if (!ok)
7904 		isl_die(set->ctx, isl_error_invalid,
7905 			"incompatible spaces", goto error);
7906 
7907 	return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7908 error:
7909 	isl_map_free(map);
7910 	isl_set_free(set);
7911 	return NULL;
7912 }
7913 
isl_map_intersect_range(__isl_take isl_map * map,__isl_take isl_set * set)7914 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7915 	__isl_take isl_set *set)
7916 {
7917 	return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7918 }
7919 
map_intersect_domain(__isl_take isl_map * map,__isl_take isl_set * set)7920 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7921 	__isl_take isl_set *set)
7922 {
7923 	isl_bool ok;
7924 
7925 	ok = isl_map_compatible_domain(map, set);
7926 	if (ok < 0)
7927 		goto error;
7928 	if (!ok)
7929 		isl_die(set->ctx, isl_error_invalid,
7930 			"incompatible spaces", goto error);
7931 
7932 	return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7933 error:
7934 	isl_map_free(map);
7935 	isl_set_free(set);
7936 	return NULL;
7937 }
7938 
isl_map_intersect_domain(__isl_take isl_map * map,__isl_take isl_set * set)7939 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7940 	__isl_take isl_set *set)
7941 {
7942 	return isl_map_align_params_map_map_and(map, set,
7943 						&map_intersect_domain);
7944 }
7945 
7946 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7947  * in the space B -> C, return the intersection.
7948  * The parameters are assumed to have been aligned.
7949  *
7950  * The map "factor" is first extended to a map living in the space
7951  * [A -> B] -> C and then a regular intersection is computed.
7952  */
map_intersect_domain_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)7953 static __isl_give isl_map *map_intersect_domain_factor_range(
7954 	__isl_take isl_map *map, __isl_take isl_map *factor)
7955 {
7956 	isl_space *space;
7957 	isl_map *ext_factor;
7958 
7959 	space = isl_space_domain_factor_domain(isl_map_get_space(map));
7960 	ext_factor = isl_map_universe(space);
7961 	ext_factor = isl_map_domain_product(ext_factor, factor);
7962 	return map_intersect(map, ext_factor);
7963 }
7964 
7965 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7966  * in the space B -> C, return the intersection.
7967  */
isl_map_intersect_domain_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)7968 __isl_give isl_map *isl_map_intersect_domain_factor_range(
7969 	__isl_take isl_map *map, __isl_take isl_map *factor)
7970 {
7971 	return isl_map_align_params_map_map_and(map, factor,
7972 					    &map_intersect_domain_factor_range);
7973 }
7974 
7975 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7976  * in the space A -> C, return the intersection.
7977  *
7978  * The map "factor" is first extended to a map living in the space
7979  * A -> [B -> C] and then a regular intersection is computed.
7980  */
map_intersect_range_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)7981 static __isl_give isl_map *map_intersect_range_factor_range(
7982 	__isl_take isl_map *map, __isl_take isl_map *factor)
7983 {
7984 	isl_space *space;
7985 	isl_map *ext_factor;
7986 
7987 	space = isl_space_range_factor_domain(isl_map_get_space(map));
7988 	ext_factor = isl_map_universe(space);
7989 	ext_factor = isl_map_range_product(ext_factor, factor);
7990 	return isl_map_intersect(map, ext_factor);
7991 }
7992 
7993 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7994  * in the space A -> C, return the intersection.
7995  */
isl_map_intersect_range_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)7996 __isl_give isl_map *isl_map_intersect_range_factor_range(
7997 	__isl_take isl_map *map, __isl_take isl_map *factor)
7998 {
7999 	return isl_map_align_params_map_map_and(map, factor,
8000 					    &map_intersect_range_factor_range);
8001 }
8002 
map_apply_domain(__isl_take isl_map * map1,__isl_take isl_map * map2)8003 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
8004 	__isl_take isl_map *map2)
8005 {
8006 	if (!map1 || !map2)
8007 		goto error;
8008 	map1 = isl_map_reverse(map1);
8009 	map1 = isl_map_apply_range(map1, map2);
8010 	return isl_map_reverse(map1);
8011 error:
8012 	isl_map_free(map1);
8013 	isl_map_free(map2);
8014 	return NULL;
8015 }
8016 
isl_map_apply_domain(__isl_take isl_map * map1,__isl_take isl_map * map2)8017 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8018 	__isl_take isl_map *map2)
8019 {
8020 	return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
8021 }
8022 
map_apply_range(__isl_take isl_map * map1,__isl_take isl_map * map2)8023 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
8024 	__isl_take isl_map *map2)
8025 {
8026 	isl_space *dim_result;
8027 	struct isl_map *result;
8028 	int i, j;
8029 
8030 	if (!map1 || !map2)
8031 		goto error;
8032 
8033 	dim_result = isl_space_join(isl_space_copy(map1->dim),
8034 				  isl_space_copy(map2->dim));
8035 
8036 	result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
8037 	if (!result)
8038 		goto error;
8039 	for (i = 0; i < map1->n; ++i)
8040 		for (j = 0; j < map2->n; ++j) {
8041 			result = isl_map_add_basic_map(result,
8042 			    isl_basic_map_apply_range(
8043 				isl_basic_map_copy(map1->p[i]),
8044 				isl_basic_map_copy(map2->p[j])));
8045 			if (!result)
8046 				goto error;
8047 		}
8048 	isl_map_free(map1);
8049 	isl_map_free(map2);
8050 	if (result && result->n <= 1)
8051 		ISL_F_SET(result, ISL_MAP_DISJOINT);
8052 	return result;
8053 error:
8054 	isl_map_free(map1);
8055 	isl_map_free(map2);
8056 	return NULL;
8057 }
8058 
isl_map_apply_range(__isl_take isl_map * map1,__isl_take isl_map * map2)8059 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8060 	__isl_take isl_map *map2)
8061 {
8062 	return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
8063 }
8064 
8065 /*
8066  * returns range - domain
8067  */
isl_basic_map_deltas(__isl_take isl_basic_map * bmap)8068 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8069 {
8070 	isl_space *target_space;
8071 	struct isl_basic_set *bset;
8072 	unsigned dim;
8073 	unsigned nparam;
8074 	int i;
8075 
8076 	if (!bmap)
8077 		goto error;
8078 	isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8079 						  bmap->dim, isl_dim_out),
8080 		   goto error);
8081 	target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8082 	dim = isl_basic_map_dim(bmap, isl_dim_in);
8083 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
8084 	bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8085 	bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8086 	bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8087 	for (i = 0; i < dim; ++i) {
8088 		int j = isl_basic_map_alloc_equality(bmap);
8089 		if (j < 0) {
8090 			bmap = isl_basic_map_free(bmap);
8091 			break;
8092 		}
8093 		isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
8094 		isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8095 		isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8096 		isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8097 	}
8098 	bset = isl_basic_map_domain(bmap);
8099 	bset = isl_basic_set_reset_space(bset, target_space);
8100 	return bset;
8101 error:
8102 	isl_basic_map_free(bmap);
8103 	return NULL;
8104 }
8105 
8106 /*
8107  * returns range - domain
8108  */
isl_map_deltas(__isl_take isl_map * map)8109 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8110 {
8111 	int i;
8112 	isl_space *dim;
8113 	struct isl_set *result;
8114 
8115 	if (!map)
8116 		return NULL;
8117 
8118 	isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
8119 						 map->dim, isl_dim_out),
8120 		   goto error);
8121 	dim = isl_map_get_space(map);
8122 	dim = isl_space_domain(dim);
8123 	result = isl_set_alloc_space(dim, map->n, 0);
8124 	if (!result)
8125 		goto error;
8126 	for (i = 0; i < map->n; ++i)
8127 		result = isl_set_add_basic_set(result,
8128 			  isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8129 	isl_map_free(map);
8130 	return result;
8131 error:
8132 	isl_map_free(map);
8133 	return NULL;
8134 }
8135 
8136 /*
8137  * returns [domain -> range] -> range - domain
8138  */
isl_basic_map_deltas_map(__isl_take isl_basic_map * bmap)8139 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8140 	__isl_take isl_basic_map *bmap)
8141 {
8142 	int i, k;
8143 	isl_space *dim;
8144 	isl_basic_map *domain;
8145 	int nparam, n;
8146 	unsigned total;
8147 
8148 	if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8149 					bmap->dim, isl_dim_out))
8150 		isl_die(bmap->ctx, isl_error_invalid,
8151 			"domain and range don't match", goto error);
8152 
8153 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
8154 	n = isl_basic_map_dim(bmap, isl_dim_in);
8155 
8156 	dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
8157 	domain = isl_basic_map_universe(dim);
8158 
8159 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8160 	bmap = isl_basic_map_apply_range(bmap, domain);
8161 	bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8162 
8163 	total = isl_basic_map_total_dim(bmap);
8164 
8165 	for (i = 0; i < n; ++i) {
8166 		k = isl_basic_map_alloc_equality(bmap);
8167 		if (k < 0)
8168 			goto error;
8169 		isl_seq_clr(bmap->eq[k], 1 + total);
8170 		isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8171 		isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8172 		isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8173 	}
8174 
8175 	bmap = isl_basic_map_gauss(bmap, NULL);
8176 	return isl_basic_map_finalize(bmap);
8177 error:
8178 	isl_basic_map_free(bmap);
8179 	return NULL;
8180 }
8181 
8182 /*
8183  * returns [domain -> range] -> range - domain
8184  */
isl_map_deltas_map(__isl_take isl_map * map)8185 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8186 {
8187 	int i;
8188 	isl_space *domain_dim;
8189 
8190 	if (!map)
8191 		return NULL;
8192 
8193 	if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
8194 					map->dim, isl_dim_out))
8195 		isl_die(map->ctx, isl_error_invalid,
8196 			"domain and range don't match", goto error);
8197 
8198 	map = isl_map_cow(map);
8199 	if (!map)
8200 		return NULL;
8201 
8202 	domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
8203 	map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
8204 	map->dim = isl_space_join(map->dim, domain_dim);
8205 	if (!map->dim)
8206 		goto error;
8207 	for (i = 0; i < map->n; ++i) {
8208 		map->p[i] = isl_basic_map_deltas_map(map->p[i]);
8209 		if (!map->p[i])
8210 			goto error;
8211 	}
8212 	map = isl_map_unmark_normalized(map);
8213 	return map;
8214 error:
8215 	isl_map_free(map);
8216 	return NULL;
8217 }
8218 
basic_map_identity(__isl_take isl_space * dims)8219 static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
8220 {
8221 	struct isl_basic_map *bmap;
8222 	unsigned nparam;
8223 	unsigned dim;
8224 	int i;
8225 
8226 	if (!dims)
8227 		return NULL;
8228 
8229 	nparam = dims->nparam;
8230 	dim = dims->n_out;
8231 	bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
8232 	if (!bmap)
8233 		goto error;
8234 
8235 	for (i = 0; i < dim; ++i) {
8236 		int j = isl_basic_map_alloc_equality(bmap);
8237 		if (j < 0)
8238 			goto error;
8239 		isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
8240 		isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8241 		isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
8242 	}
8243 	return isl_basic_map_finalize(bmap);
8244 error:
8245 	isl_basic_map_free(bmap);
8246 	return NULL;
8247 }
8248 
isl_basic_map_identity(__isl_take isl_space * dim)8249 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
8250 {
8251 	if (!dim)
8252 		return NULL;
8253 	if (dim->n_in != dim->n_out)
8254 		isl_die(dim->ctx, isl_error_invalid,
8255 			"number of input and output dimensions needs to be "
8256 			"the same", goto error);
8257 	return basic_map_identity(dim);
8258 error:
8259 	isl_space_free(dim);
8260 	return NULL;
8261 }
8262 
isl_map_identity(__isl_take isl_space * dim)8263 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
8264 {
8265 	return isl_map_from_basic_map(isl_basic_map_identity(dim));
8266 }
8267 
isl_set_identity(__isl_take isl_set * set)8268 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8269 {
8270 	isl_space *dim = isl_set_get_space(set);
8271 	isl_map *id;
8272 	id = isl_map_identity(isl_space_map_from_set(dim));
8273 	return isl_map_intersect_range(id, set);
8274 }
8275 
8276 /* Construct a basic set with all set dimensions having only non-negative
8277  * values.
8278  */
isl_basic_set_positive_orthant(__isl_take isl_space * space)8279 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8280 	__isl_take isl_space *space)
8281 {
8282 	int i;
8283 	unsigned nparam;
8284 	unsigned dim;
8285 	struct isl_basic_set *bset;
8286 
8287 	if (!space)
8288 		return NULL;
8289 	nparam = space->nparam;
8290 	dim = space->n_out;
8291 	bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8292 	if (!bset)
8293 		return NULL;
8294 	for (i = 0; i < dim; ++i) {
8295 		int k = isl_basic_set_alloc_inequality(bset);
8296 		if (k < 0)
8297 			goto error;
8298 		isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
8299 		isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8300 	}
8301 	return bset;
8302 error:
8303 	isl_basic_set_free(bset);
8304 	return NULL;
8305 }
8306 
8307 /* Construct the half-space x_pos >= 0.
8308  */
nonneg_halfspace(__isl_take isl_space * dim,int pos)8309 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
8310 	int pos)
8311 {
8312 	int k;
8313 	isl_basic_set *nonneg;
8314 
8315 	nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
8316 	k = isl_basic_set_alloc_inequality(nonneg);
8317 	if (k < 0)
8318 		goto error;
8319 	isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
8320 	isl_int_set_si(nonneg->ineq[k][pos], 1);
8321 
8322 	return isl_basic_set_finalize(nonneg);
8323 error:
8324 	isl_basic_set_free(nonneg);
8325 	return NULL;
8326 }
8327 
8328 /* Construct the half-space x_pos <= -1.
8329  */
neg_halfspace(__isl_take isl_space * dim,int pos)8330 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
8331 {
8332 	int k;
8333 	isl_basic_set *neg;
8334 
8335 	neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
8336 	k = isl_basic_set_alloc_inequality(neg);
8337 	if (k < 0)
8338 		goto error;
8339 	isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
8340 	isl_int_set_si(neg->ineq[k][0], -1);
8341 	isl_int_set_si(neg->ineq[k][pos], -1);
8342 
8343 	return isl_basic_set_finalize(neg);
8344 error:
8345 	isl_basic_set_free(neg);
8346 	return NULL;
8347 }
8348 
isl_set_split_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)8349 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8350 	enum isl_dim_type type, unsigned first, unsigned n)
8351 {
8352 	int i;
8353 	unsigned offset;
8354 	isl_basic_set *nonneg;
8355 	isl_basic_set *neg;
8356 
8357 	if (!set)
8358 		return NULL;
8359 	if (n == 0)
8360 		return set;
8361 
8362 	isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
8363 
8364 	offset = pos(set->dim, type);
8365 	for (i = 0; i < n; ++i) {
8366 		nonneg = nonneg_halfspace(isl_set_get_space(set),
8367 					  offset + first + i);
8368 		neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8369 
8370 		set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8371 	}
8372 
8373 	return set;
8374 error:
8375 	isl_set_free(set);
8376 	return NULL;
8377 }
8378 
foreach_orthant(__isl_take isl_set * set,int * signs,int first,int len,isl_stat (* fn)(__isl_take isl_set * orthant,int * signs,void * user),void * user)8379 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8380 	int len,
8381 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8382 	void *user)
8383 {
8384 	isl_set *half;
8385 
8386 	if (!set)
8387 		return isl_stat_error;
8388 	if (isl_set_plain_is_empty(set)) {
8389 		isl_set_free(set);
8390 		return isl_stat_ok;
8391 	}
8392 	if (first == len)
8393 		return fn(set, signs, user);
8394 
8395 	signs[first] = 1;
8396 	half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8397 							1 + first));
8398 	half = isl_set_intersect(half, isl_set_copy(set));
8399 	if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8400 		goto error;
8401 
8402 	signs[first] = -1;
8403 	half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8404 							1 + first));
8405 	half = isl_set_intersect(half, set);
8406 	return foreach_orthant(half, signs, first + 1, len, fn, user);
8407 error:
8408 	isl_set_free(set);
8409 	return isl_stat_error;
8410 }
8411 
8412 /* Call "fn" on the intersections of "set" with each of the orthants
8413  * (except for obviously empty intersections).  The orthant is identified
8414  * by the signs array, with each entry having value 1 or -1 according
8415  * to the sign of the corresponding variable.
8416  */
isl_set_foreach_orthant(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_set * orthant,int * signs,void * user),void * user)8417 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8418 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8419 	void *user)
8420 {
8421 	unsigned nparam;
8422 	unsigned nvar;
8423 	int *signs;
8424 	isl_stat r;
8425 
8426 	if (!set)
8427 		return isl_stat_error;
8428 	if (isl_set_plain_is_empty(set))
8429 		return isl_stat_ok;
8430 
8431 	nparam = isl_set_dim(set, isl_dim_param);
8432 	nvar = isl_set_dim(set, isl_dim_set);
8433 
8434 	signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8435 
8436 	r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8437 			    fn, user);
8438 
8439 	free(signs);
8440 
8441 	return r;
8442 }
8443 
isl_set_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)8444 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8445 {
8446 	return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8447 }
8448 
isl_basic_map_is_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8449 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8450 	__isl_keep isl_basic_map *bmap2)
8451 {
8452 	int is_subset;
8453 	struct isl_map *map1;
8454 	struct isl_map *map2;
8455 
8456 	if (!bmap1 || !bmap2)
8457 		return isl_bool_error;
8458 
8459 	map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8460 	map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8461 
8462 	is_subset = isl_map_is_subset(map1, map2);
8463 
8464 	isl_map_free(map1);
8465 	isl_map_free(map2);
8466 
8467 	return is_subset;
8468 }
8469 
isl_basic_set_is_subset(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8470 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8471 	__isl_keep isl_basic_set *bset2)
8472 {
8473 	return isl_basic_map_is_subset(bset1, bset2);
8474 }
8475 
isl_basic_map_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8476 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8477 	__isl_keep isl_basic_map *bmap2)
8478 {
8479 	isl_bool is_subset;
8480 
8481 	if (!bmap1 || !bmap2)
8482 		return isl_bool_error;
8483 	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8484 	if (is_subset != isl_bool_true)
8485 		return is_subset;
8486 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8487 	return is_subset;
8488 }
8489 
isl_basic_set_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8490 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8491 	__isl_keep isl_basic_set *bset2)
8492 {
8493 	return isl_basic_map_is_equal(
8494 		bset_to_bmap(bset1), bset_to_bmap(bset2));
8495 }
8496 
isl_map_is_empty(__isl_keep isl_map * map)8497 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8498 {
8499 	int i;
8500 	int is_empty;
8501 
8502 	if (!map)
8503 		return isl_bool_error;
8504 	for (i = 0; i < map->n; ++i) {
8505 		is_empty = isl_basic_map_is_empty(map->p[i]);
8506 		if (is_empty < 0)
8507 			return isl_bool_error;
8508 		if (!is_empty)
8509 			return isl_bool_false;
8510 	}
8511 	return isl_bool_true;
8512 }
8513 
isl_map_plain_is_empty(__isl_keep isl_map * map)8514 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8515 {
8516 	return map ? map->n == 0 : isl_bool_error;
8517 }
8518 
isl_set_plain_is_empty(__isl_keep isl_set * set)8519 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8520 {
8521 	return set ? set->n == 0 : isl_bool_error;
8522 }
8523 
isl_set_is_empty(__isl_keep isl_set * set)8524 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8525 {
8526 	return isl_map_is_empty(set_to_map(set));
8527 }
8528 
isl_map_has_equal_space(__isl_keep isl_map * map1,__isl_keep isl_map * map2)8529 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
8530 	__isl_keep isl_map *map2)
8531 {
8532 	if (!map1 || !map2)
8533 		return isl_bool_error;
8534 
8535 	return isl_space_is_equal(map1->dim, map2->dim);
8536 }
8537 
isl_set_has_equal_space(__isl_keep isl_set * set1,__isl_keep isl_set * set2)8538 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
8539 	__isl_keep isl_set *set2)
8540 {
8541 	if (!set1 || !set2)
8542 		return isl_bool_error;
8543 
8544 	return isl_space_is_equal(set1->dim, set2->dim);
8545 }
8546 
map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)8547 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8548 {
8549 	isl_bool is_subset;
8550 
8551 	if (!map1 || !map2)
8552 		return isl_bool_error;
8553 	is_subset = isl_map_is_subset(map1, map2);
8554 	if (is_subset != isl_bool_true)
8555 		return is_subset;
8556 	is_subset = isl_map_is_subset(map2, map1);
8557 	return is_subset;
8558 }
8559 
8560 /* Is "map1" equal to "map2"?
8561  *
8562  * First check if they are obviously equal.
8563  * If not, then perform a more detailed analysis.
8564  */
isl_map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)8565 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8566 {
8567 	isl_bool equal;
8568 
8569 	equal = isl_map_plain_is_equal(map1, map2);
8570 	if (equal < 0 || equal)
8571 		return equal;
8572 	return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8573 }
8574 
isl_basic_map_is_strict_subset(struct isl_basic_map * bmap1,struct isl_basic_map * bmap2)8575 isl_bool isl_basic_map_is_strict_subset(
8576 		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8577 {
8578 	isl_bool is_subset;
8579 
8580 	if (!bmap1 || !bmap2)
8581 		return isl_bool_error;
8582 	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8583 	if (is_subset != isl_bool_true)
8584 		return is_subset;
8585 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8586 	if (is_subset == isl_bool_error)
8587 		return is_subset;
8588 	return !is_subset;
8589 }
8590 
isl_map_is_strict_subset(__isl_keep isl_map * map1,__isl_keep isl_map * map2)8591 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8592 	__isl_keep isl_map *map2)
8593 {
8594 	isl_bool is_subset;
8595 
8596 	if (!map1 || !map2)
8597 		return isl_bool_error;
8598 	is_subset = isl_map_is_subset(map1, map2);
8599 	if (is_subset != isl_bool_true)
8600 		return is_subset;
8601 	is_subset = isl_map_is_subset(map2, map1);
8602 	if (is_subset == isl_bool_error)
8603 		return is_subset;
8604 	return !is_subset;
8605 }
8606 
isl_set_is_strict_subset(__isl_keep isl_set * set1,__isl_keep isl_set * set2)8607 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8608 	__isl_keep isl_set *set2)
8609 {
8610 	return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8611 }
8612 
8613 /* Is "bmap" obviously equal to the universe with the same space?
8614  *
8615  * That is, does it not have any constraints?
8616  */
isl_basic_map_plain_is_universe(__isl_keep isl_basic_map * bmap)8617 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8618 {
8619 	if (!bmap)
8620 		return isl_bool_error;
8621 	return bmap->n_eq == 0 && bmap->n_ineq == 0;
8622 }
8623 
8624 /* Is "bset" obviously equal to the universe with the same space?
8625  */
isl_basic_set_plain_is_universe(__isl_keep isl_basic_set * bset)8626 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8627 {
8628 	return isl_basic_map_plain_is_universe(bset);
8629 }
8630 
8631 /* If "c" does not involve any existentially quantified variables,
8632  * then set *univ to false and abort
8633  */
involves_divs(__isl_take isl_constraint * c,void * user)8634 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8635 {
8636 	isl_bool *univ = user;
8637 	unsigned n;
8638 
8639 	n = isl_constraint_dim(c, isl_dim_div);
8640 	*univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8641 	isl_constraint_free(c);
8642 	if (*univ < 0 || !*univ)
8643 		return isl_stat_error;
8644 	return isl_stat_ok;
8645 }
8646 
8647 /* Is "bmap" equal to the universe with the same space?
8648  *
8649  * First check if it is obviously equal to the universe.
8650  * If not and if there are any constraints not involving
8651  * existentially quantified variables, then it is certainly
8652  * not equal to the universe.
8653  * Otherwise, check if the universe is a subset of "bmap".
8654  */
isl_basic_map_is_universe(__isl_keep isl_basic_map * bmap)8655 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8656 {
8657 	isl_bool univ;
8658 	isl_basic_map *test;
8659 
8660 	univ = isl_basic_map_plain_is_universe(bmap);
8661 	if (univ < 0 || univ)
8662 		return univ;
8663 	if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8664 		return isl_bool_false;
8665 	univ = isl_bool_true;
8666 	if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8667 	    univ)
8668 		return isl_bool_error;
8669 	if (univ < 0 || !univ)
8670 		return univ;
8671 	test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8672 	univ = isl_basic_map_is_subset(test, bmap);
8673 	isl_basic_map_free(test);
8674 	return univ;
8675 }
8676 
8677 /* Is "bset" equal to the universe with the same space?
8678  */
isl_basic_set_is_universe(__isl_keep isl_basic_set * bset)8679 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8680 {
8681 	return isl_basic_map_is_universe(bset);
8682 }
8683 
isl_map_plain_is_universe(__isl_keep isl_map * map)8684 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8685 {
8686 	int i;
8687 
8688 	if (!map)
8689 		return isl_bool_error;
8690 
8691 	for (i = 0; i < map->n; ++i) {
8692 		isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8693 		if (r < 0 || r)
8694 			return r;
8695 	}
8696 
8697 	return isl_bool_false;
8698 }
8699 
isl_set_plain_is_universe(__isl_keep isl_set * set)8700 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8701 {
8702 	return isl_map_plain_is_universe(set_to_map(set));
8703 }
8704 
isl_basic_map_is_empty(__isl_keep isl_basic_map * bmap)8705 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8706 {
8707 	struct isl_basic_set *bset = NULL;
8708 	struct isl_vec *sample = NULL;
8709 	isl_bool empty, non_empty;
8710 
8711 	if (!bmap)
8712 		return isl_bool_error;
8713 
8714 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8715 		return isl_bool_true;
8716 
8717 	if (isl_basic_map_plain_is_universe(bmap))
8718 		return isl_bool_false;
8719 
8720 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8721 		struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8722 		copy = isl_basic_map_remove_redundancies(copy);
8723 		empty = isl_basic_map_plain_is_empty(copy);
8724 		isl_basic_map_free(copy);
8725 		return empty;
8726 	}
8727 
8728 	non_empty = isl_basic_map_plain_is_non_empty(bmap);
8729 	if (non_empty < 0)
8730 		return isl_bool_error;
8731 	if (non_empty)
8732 		return isl_bool_false;
8733 	isl_vec_free(bmap->sample);
8734 	bmap->sample = NULL;
8735 	bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8736 	if (!bset)
8737 		return isl_bool_error;
8738 	sample = isl_basic_set_sample_vec(bset);
8739 	if (!sample)
8740 		return isl_bool_error;
8741 	empty = sample->size == 0;
8742 	isl_vec_free(bmap->sample);
8743 	bmap->sample = sample;
8744 	if (empty)
8745 		ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8746 
8747 	return empty;
8748 }
8749 
isl_basic_map_plain_is_empty(__isl_keep isl_basic_map * bmap)8750 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8751 {
8752 	if (!bmap)
8753 		return isl_bool_error;
8754 	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8755 }
8756 
isl_basic_set_plain_is_empty(__isl_keep isl_basic_set * bset)8757 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8758 {
8759 	if (!bset)
8760 		return isl_bool_error;
8761 	return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8762 }
8763 
8764 /* Is "bmap" known to be non-empty?
8765  *
8766  * That is, is the cached sample still valid?
8767  */
isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map * bmap)8768 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8769 {
8770 	unsigned total;
8771 
8772 	if (!bmap)
8773 		return isl_bool_error;
8774 	if (!bmap->sample)
8775 		return isl_bool_false;
8776 	total = 1 + isl_basic_map_total_dim(bmap);
8777 	if (bmap->sample->size != total)
8778 		return isl_bool_false;
8779 	return isl_basic_map_contains(bmap, bmap->sample);
8780 }
8781 
isl_basic_set_is_empty(__isl_keep isl_basic_set * bset)8782 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8783 {
8784 	return isl_basic_map_is_empty(bset_to_bmap(bset));
8785 }
8786 
isl_basic_map_union(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)8787 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
8788 	__isl_take isl_basic_map *bmap2)
8789 {
8790 	struct isl_map *map;
8791 	if (!bmap1 || !bmap2)
8792 		goto error;
8793 
8794 	isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8795 
8796 	map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8797 	if (!map)
8798 		goto error;
8799 	map = isl_map_add_basic_map(map, bmap1);
8800 	map = isl_map_add_basic_map(map, bmap2);
8801 	return map;
8802 error:
8803 	isl_basic_map_free(bmap1);
8804 	isl_basic_map_free(bmap2);
8805 	return NULL;
8806 }
8807 
isl_basic_set_union(struct isl_basic_set * bset1,struct isl_basic_set * bset2)8808 struct isl_set *isl_basic_set_union(
8809 		struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8810 {
8811 	return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8812 						bset_to_bmap(bset2)));
8813 }
8814 
8815 /* Order divs such that any div only depends on previous divs */
isl_basic_map_order_divs(__isl_take isl_basic_map * bmap)8816 __isl_give isl_basic_map *isl_basic_map_order_divs(
8817 	__isl_take isl_basic_map *bmap)
8818 {
8819 	int i;
8820 	unsigned off;
8821 
8822 	if (!bmap)
8823 		return NULL;
8824 
8825 	off = isl_space_dim(bmap->dim, isl_dim_all);
8826 
8827 	for (i = 0; i < bmap->n_div; ++i) {
8828 		int pos;
8829 		if (isl_int_is_zero(bmap->div[i][0]))
8830 			continue;
8831 		pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8832 							    bmap->n_div-i);
8833 		if (pos == -1)
8834 			continue;
8835 		if (pos == 0)
8836 			isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8837 				"integer division depends on itself",
8838 				return isl_basic_map_free(bmap));
8839 		isl_basic_map_swap_div(bmap, i, i + pos);
8840 		--i;
8841 	}
8842 	return bmap;
8843 }
8844 
isl_basic_set_order_divs(struct isl_basic_set * bset)8845 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8846 {
8847 	return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8848 }
8849 
isl_map_order_divs(__isl_take isl_map * map)8850 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8851 {
8852 	int i;
8853 
8854 	if (!map)
8855 		return 0;
8856 
8857 	for (i = 0; i < map->n; ++i) {
8858 		map->p[i] = isl_basic_map_order_divs(map->p[i]);
8859 		if (!map->p[i])
8860 			goto error;
8861 	}
8862 
8863 	return map;
8864 error:
8865 	isl_map_free(map);
8866 	return NULL;
8867 }
8868 
8869 /* Sort the local variables of "bset".
8870  */
isl_basic_set_sort_divs(__isl_take isl_basic_set * bset)8871 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8872 	__isl_take isl_basic_set *bset)
8873 {
8874 	return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8875 }
8876 
8877 /* Apply the expansion computed by isl_merge_divs.
8878  * The expansion itself is given by "exp" while the resulting
8879  * list of divs is given by "div".
8880  *
8881  * Move the integer divisions of "bmap" into the right position
8882  * according to "exp" and then introduce the additional integer
8883  * divisions, adding div constraints.
8884  * The moving should be done first to avoid moving coefficients
8885  * in the definitions of the extra integer divisions.
8886  */
isl_basic_map_expand_divs(__isl_take isl_basic_map * bmap,__isl_take isl_mat * div,int * exp)8887 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8888 	__isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8889 {
8890 	int i, j;
8891 	int n_div;
8892 
8893 	bmap = isl_basic_map_cow(bmap);
8894 	if (!bmap || !div)
8895 		goto error;
8896 
8897 	if (div->n_row < bmap->n_div)
8898 		isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8899 			"not an expansion", goto error);
8900 
8901 	n_div = bmap->n_div;
8902 	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8903 					    div->n_row - n_div, 0,
8904 					    2 * (div->n_row - n_div));
8905 
8906 	for (i = n_div; i < div->n_row; ++i)
8907 		if (isl_basic_map_alloc_div(bmap) < 0)
8908 			goto error;
8909 
8910 	for (j = n_div - 1; j >= 0; --j) {
8911 		if (exp[j] == j)
8912 			break;
8913 		isl_basic_map_swap_div(bmap, j, exp[j]);
8914 	}
8915 	j = 0;
8916 	for (i = 0; i < div->n_row; ++i) {
8917 		if (j < n_div && exp[j] == i) {
8918 			j++;
8919 		} else {
8920 			isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8921 			if (isl_basic_map_div_is_marked_unknown(bmap, i))
8922 				continue;
8923 			if (isl_basic_map_add_div_constraints(bmap, i) < 0)
8924 				goto error;
8925 		}
8926 	}
8927 
8928 	isl_mat_free(div);
8929 	return bmap;
8930 error:
8931 	isl_basic_map_free(bmap);
8932 	isl_mat_free(div);
8933 	return NULL;
8934 }
8935 
8936 /* Apply the expansion computed by isl_merge_divs.
8937  * The expansion itself is given by "exp" while the resulting
8938  * list of divs is given by "div".
8939  */
isl_basic_set_expand_divs(__isl_take isl_basic_set * bset,__isl_take isl_mat * div,int * exp)8940 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8941 	__isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8942 {
8943 	return isl_basic_map_expand_divs(bset, div, exp);
8944 }
8945 
8946 /* Look for a div in dst that corresponds to the div "div" in src.
8947  * The divs before "div" in src and dst are assumed to be the same.
8948  *
8949  * Returns -1 if no corresponding div was found and the position
8950  * of the corresponding div in dst otherwise.
8951  */
find_div(__isl_keep isl_basic_map * dst,__isl_keep isl_basic_map * src,unsigned div)8952 static int find_div(__isl_keep isl_basic_map *dst,
8953 	__isl_keep isl_basic_map *src, unsigned div)
8954 {
8955 	int i;
8956 
8957 	unsigned total = isl_space_dim(src->dim, isl_dim_all);
8958 
8959 	isl_assert(dst->ctx, div <= dst->n_div, return -1);
8960 	for (i = div; i < dst->n_div; ++i)
8961 		if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8962 		    isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8963 						dst->n_div - div) == -1)
8964 			return i;
8965 	return -1;
8966 }
8967 
8968 /* Align the divs of "dst" to those of "src", adding divs from "src"
8969  * if needed.  That is, make sure that the first src->n_div divs
8970  * of the result are equal to those of src.
8971  *
8972  * The result is not finalized as by design it will have redundant
8973  * divs if any divs from "src" were copied.
8974  */
isl_basic_map_align_divs(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)8975 __isl_give isl_basic_map *isl_basic_map_align_divs(
8976 	__isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8977 {
8978 	int i;
8979 	int known, extended;
8980 	unsigned total;
8981 
8982 	if (!dst || !src)
8983 		return isl_basic_map_free(dst);
8984 
8985 	if (src->n_div == 0)
8986 		return dst;
8987 
8988 	known = isl_basic_map_divs_known(src);
8989 	if (known < 0)
8990 		return isl_basic_map_free(dst);
8991 	if (!known)
8992 		isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8993 			"some src divs are unknown",
8994 			return isl_basic_map_free(dst));
8995 
8996 	src = isl_basic_map_order_divs(src);
8997 
8998 	extended = 0;
8999 	total = isl_space_dim(src->dim, isl_dim_all);
9000 	for (i = 0; i < src->n_div; ++i) {
9001 		int j = find_div(dst, src, i);
9002 		if (j < 0) {
9003 			if (!extended) {
9004 				int extra = src->n_div - i;
9005 				dst = isl_basic_map_cow(dst);
9006 				if (!dst)
9007 					return NULL;
9008 				dst = isl_basic_map_extend_space(dst,
9009 						isl_space_copy(dst->dim),
9010 						extra, 0, 2 * extra);
9011 				extended = 1;
9012 			}
9013 			j = isl_basic_map_alloc_div(dst);
9014 			if (j < 0)
9015 				return isl_basic_map_free(dst);
9016 			isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
9017 			isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
9018 			if (isl_basic_map_add_div_constraints(dst, j) < 0)
9019 				return isl_basic_map_free(dst);
9020 		}
9021 		if (j != i)
9022 			isl_basic_map_swap_div(dst, i, j);
9023 	}
9024 	return dst;
9025 }
9026 
isl_map_align_divs_internal(__isl_take isl_map * map)9027 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9028 {
9029 	int i;
9030 
9031 	if (!map)
9032 		return NULL;
9033 	if (map->n == 0)
9034 		return map;
9035 	map = isl_map_compute_divs(map);
9036 	map = isl_map_cow(map);
9037 	if (!map)
9038 		return NULL;
9039 
9040 	for (i = 1; i < map->n; ++i)
9041 		map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9042 	for (i = 1; i < map->n; ++i) {
9043 		map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9044 		if (!map->p[i])
9045 			return isl_map_free(map);
9046 	}
9047 
9048 	map = isl_map_unmark_normalized(map);
9049 	return map;
9050 }
9051 
isl_map_align_divs(__isl_take isl_map * map)9052 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9053 {
9054 	return isl_map_align_divs_internal(map);
9055 }
9056 
isl_set_align_divs(struct isl_set * set)9057 struct isl_set *isl_set_align_divs(struct isl_set *set)
9058 {
9059 	return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9060 }
9061 
9062 /* Align the divs of the basic maps in "map" to those
9063  * of the basic maps in "list", as well as to the other basic maps in "map".
9064  * The elements in "list" are assumed to have known divs.
9065  */
isl_map_align_divs_to_basic_map_list(__isl_take isl_map * map,__isl_keep isl_basic_map_list * list)9066 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9067 	__isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9068 {
9069 	int i, n;
9070 
9071 	map = isl_map_compute_divs(map);
9072 	map = isl_map_cow(map);
9073 	if (!map || !list)
9074 		return isl_map_free(map);
9075 	if (map->n == 0)
9076 		return map;
9077 
9078 	n = isl_basic_map_list_n_basic_map(list);
9079 	for (i = 0; i < n; ++i) {
9080 		isl_basic_map *bmap;
9081 
9082 		bmap = isl_basic_map_list_get_basic_map(list, i);
9083 		map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9084 		isl_basic_map_free(bmap);
9085 	}
9086 	if (!map->p[0])
9087 		return isl_map_free(map);
9088 
9089 	return isl_map_align_divs_internal(map);
9090 }
9091 
9092 /* Align the divs of each element of "list" to those of "bmap".
9093  * Both "bmap" and the elements of "list" are assumed to have known divs.
9094  */
isl_basic_map_list_align_divs_to_basic_map(__isl_take isl_basic_map_list * list,__isl_keep isl_basic_map * bmap)9095 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9096 	__isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9097 {
9098 	int i, n;
9099 
9100 	if (!list || !bmap)
9101 		return isl_basic_map_list_free(list);
9102 
9103 	n = isl_basic_map_list_n_basic_map(list);
9104 	for (i = 0; i < n; ++i) {
9105 		isl_basic_map *bmap_i;
9106 
9107 		bmap_i = isl_basic_map_list_get_basic_map(list, i);
9108 		bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9109 		list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9110 	}
9111 
9112 	return list;
9113 }
9114 
set_apply(__isl_take isl_set * set,__isl_take isl_map * map)9115 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
9116 	__isl_take isl_map *map)
9117 {
9118 	isl_bool ok;
9119 
9120 	ok = isl_map_compatible_domain(map, set);
9121 	if (ok < 0)
9122 		goto error;
9123 	if (!ok)
9124 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
9125 			"incompatible spaces", goto error);
9126 	map = isl_map_intersect_domain(map, set);
9127 	set = isl_map_range(map);
9128 	return set;
9129 error:
9130 	isl_set_free(set);
9131 	isl_map_free(map);
9132 	return NULL;
9133 }
9134 
isl_set_apply(__isl_take isl_set * set,__isl_take isl_map * map)9135 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9136 	__isl_take isl_map *map)
9137 {
9138 	return isl_map_align_params_map_map_and(set, map, &set_apply);
9139 }
9140 
9141 /* There is no need to cow as removing empty parts doesn't change
9142  * the meaning of the set.
9143  */
isl_map_remove_empty_parts(__isl_take isl_map * map)9144 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9145 {
9146 	int i;
9147 
9148 	if (!map)
9149 		return NULL;
9150 
9151 	for (i = map->n - 1; i >= 0; --i)
9152 		map = remove_if_empty(map, i);
9153 
9154 	return map;
9155 }
9156 
isl_set_remove_empty_parts(struct isl_set * set)9157 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
9158 {
9159 	return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9160 }
9161 
9162 /* Create a binary relation that maps the shared initial "pos" dimensions
9163  * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9164  */
join_initial(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9165 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9166 	__isl_keep isl_basic_set *bset2, int pos)
9167 {
9168 	isl_basic_map *bmap1;
9169 	isl_basic_map *bmap2;
9170 
9171 	bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9172 	bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9173 	bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9174 					isl_dim_out, 0, pos);
9175 	bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9176 					isl_dim_out, 0, pos);
9177 	return isl_basic_map_range_product(bmap1, bmap2);
9178 }
9179 
9180 /* Given two basic sets bset1 and bset2, compute the maximal difference
9181  * between the values of dimension pos in bset1 and those in bset2
9182  * for any common value of the parameters and dimensions preceding pos.
9183  */
basic_set_maximal_difference_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos,isl_int * opt)9184 static enum isl_lp_result basic_set_maximal_difference_at(
9185 	__isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9186 	int pos, isl_int *opt)
9187 {
9188 	isl_basic_map *bmap1;
9189 	struct isl_ctx *ctx;
9190 	struct isl_vec *obj;
9191 	unsigned total;
9192 	unsigned nparam;
9193 	unsigned dim1;
9194 	enum isl_lp_result res;
9195 
9196 	if (!bset1 || !bset2)
9197 		return isl_lp_error;
9198 
9199 	nparam = isl_basic_set_n_param(bset1);
9200 	dim1 = isl_basic_set_n_dim(bset1);
9201 
9202 	bmap1 = join_initial(bset1, bset2, pos);
9203 	if (!bmap1)
9204 		return isl_lp_error;
9205 
9206 	total = isl_basic_map_total_dim(bmap1);
9207 	ctx = bmap1->ctx;
9208 	obj = isl_vec_alloc(ctx, 1 + total);
9209 	if (!obj)
9210 		goto error;
9211 	isl_seq_clr(obj->block.data, 1 + total);
9212 	isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9213 	isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9214 	res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9215 					opt, NULL, NULL);
9216 	isl_basic_map_free(bmap1);
9217 	isl_vec_free(obj);
9218 	return res;
9219 error:
9220 	isl_basic_map_free(bmap1);
9221 	return isl_lp_error;
9222 }
9223 
9224 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9225  * for any common value of the parameters and dimensions preceding pos
9226  * in both basic sets, the values of dimension pos in bset1 are
9227  * smaller or larger than those in bset2.
9228  *
9229  * Returns
9230  *	 1 if bset1 follows bset2
9231  *	-1 if bset1 precedes bset2
9232  *	 0 if bset1 and bset2 are incomparable
9233  *	-2 if some error occurred.
9234  */
isl_basic_set_compare_at(struct isl_basic_set * bset1,struct isl_basic_set * bset2,int pos)9235 int isl_basic_set_compare_at(struct isl_basic_set *bset1,
9236 	struct isl_basic_set *bset2, int pos)
9237 {
9238 	isl_int opt;
9239 	enum isl_lp_result res;
9240 	int cmp;
9241 
9242 	isl_int_init(opt);
9243 
9244 	res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9245 
9246 	if (res == isl_lp_empty)
9247 		cmp = 0;
9248 	else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9249 		  res == isl_lp_unbounded)
9250 		cmp = 1;
9251 	else if (res == isl_lp_ok && isl_int_is_neg(opt))
9252 		cmp = -1;
9253 	else
9254 		cmp = -2;
9255 
9256 	isl_int_clear(opt);
9257 	return cmp;
9258 }
9259 
9260 /* Given two basic sets bset1 and bset2, check whether
9261  * for any common value of the parameters and dimensions preceding pos
9262  * there is a value of dimension pos in bset1 that is larger
9263  * than a value of the same dimension in bset2.
9264  *
9265  * Return
9266  *	 1 if there exists such a pair
9267  *	 0 if there is no such pair, but there is a pair of equal values
9268  *	-1 otherwise
9269  *	-2 if some error occurred.
9270  */
isl_basic_set_follows_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9271 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9272 	__isl_keep isl_basic_set *bset2, int pos)
9273 {
9274 	isl_bool empty;
9275 	isl_basic_map *bmap;
9276 	unsigned dim1;
9277 
9278 	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9279 	bmap = join_initial(bset1, bset2, pos);
9280 	bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9281 					    isl_dim_out, dim1 - pos);
9282 	empty = isl_basic_map_is_empty(bmap);
9283 	if (empty < 0)
9284 		goto error;
9285 	if (empty) {
9286 		isl_basic_map_free(bmap);
9287 		return -1;
9288 	}
9289 	bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9290 					    isl_dim_out, dim1 - pos);
9291 	empty = isl_basic_map_is_empty(bmap);
9292 	if (empty < 0)
9293 		goto error;
9294 	isl_basic_map_free(bmap);
9295 	if (empty)
9296 		return 0;
9297 	return 1;
9298 error:
9299 	isl_basic_map_free(bmap);
9300 	return -2;
9301 }
9302 
9303 /* Given two sets set1 and set2, check whether
9304  * for any common value of the parameters and dimensions preceding pos
9305  * there is a value of dimension pos in set1 that is larger
9306  * than a value of the same dimension in set2.
9307  *
9308  * Return
9309  *	 1 if there exists such a pair
9310  *	 0 if there is no such pair, but there is a pair of equal values
9311  *	-1 otherwise
9312  *	-2 if some error occurred.
9313  */
isl_set_follows_at(__isl_keep isl_set * set1,__isl_keep isl_set * set2,int pos)9314 int isl_set_follows_at(__isl_keep isl_set *set1,
9315 	__isl_keep isl_set *set2, int pos)
9316 {
9317 	int i, j;
9318 	int follows = -1;
9319 
9320 	if (!set1 || !set2)
9321 		return -2;
9322 
9323 	for (i = 0; i < set1->n; ++i)
9324 		for (j = 0; j < set2->n; ++j) {
9325 			int f;
9326 			f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9327 			if (f == 1 || f == -2)
9328 				return f;
9329 			if (f > follows)
9330 				follows = f;
9331 		}
9332 
9333 	return follows;
9334 }
9335 
isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * val)9336 static isl_bool isl_basic_map_plain_has_fixed_var(
9337 	__isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9338 {
9339 	int i;
9340 	int d;
9341 	unsigned total;
9342 
9343 	if (!bmap)
9344 		return isl_bool_error;
9345 	total = isl_basic_map_total_dim(bmap);
9346 	for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9347 		for (; d+1 > pos; --d)
9348 			if (!isl_int_is_zero(bmap->eq[i][1+d]))
9349 				break;
9350 		if (d != pos)
9351 			continue;
9352 		if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9353 			return isl_bool_false;
9354 		if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9355 			return isl_bool_false;
9356 		if (!isl_int_is_one(bmap->eq[i][1+d]))
9357 			return isl_bool_false;
9358 		if (val)
9359 			isl_int_neg(*val, bmap->eq[i][0]);
9360 		return isl_bool_true;
9361 	}
9362 	return isl_bool_false;
9363 }
9364 
isl_map_plain_has_fixed_var(__isl_keep isl_map * map,unsigned pos,isl_int * val)9365 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9366 	unsigned pos, isl_int *val)
9367 {
9368 	int i;
9369 	isl_int v;
9370 	isl_int tmp;
9371 	isl_bool fixed;
9372 
9373 	if (!map)
9374 		return isl_bool_error;
9375 	if (map->n == 0)
9376 		return isl_bool_false;
9377 	if (map->n == 1)
9378 		return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9379 	isl_int_init(v);
9380 	isl_int_init(tmp);
9381 	fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9382 	for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9383 		fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9384 		if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9385 			fixed = isl_bool_false;
9386 	}
9387 	if (val)
9388 		isl_int_set(*val, v);
9389 	isl_int_clear(tmp);
9390 	isl_int_clear(v);
9391 	return fixed;
9392 }
9393 
isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set * bset,unsigned pos,isl_int * val)9394 static isl_bool isl_basic_set_plain_has_fixed_var(
9395 	__isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9396 {
9397 	return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9398 						pos, val);
9399 }
9400 
isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int * val)9401 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9402 	enum isl_dim_type type, unsigned pos, isl_int *val)
9403 {
9404 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9405 		return isl_bool_error;
9406 	return isl_basic_map_plain_has_fixed_var(bmap,
9407 		isl_basic_map_offset(bmap, type) - 1 + pos, val);
9408 }
9409 
9410 /* If "bmap" obviously lies on a hyperplane where the given dimension
9411  * has a fixed value, then return that value.
9412  * Otherwise return NaN.
9413  */
isl_basic_map_plain_get_val_if_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)9414 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9415 	__isl_keep isl_basic_map *bmap,
9416 	enum isl_dim_type type, unsigned pos)
9417 {
9418 	isl_ctx *ctx;
9419 	isl_val *v;
9420 	isl_bool fixed;
9421 
9422 	if (!bmap)
9423 		return NULL;
9424 	ctx = isl_basic_map_get_ctx(bmap);
9425 	v = isl_val_alloc(ctx);
9426 	if (!v)
9427 		return NULL;
9428 	fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9429 	if (fixed < 0)
9430 		return isl_val_free(v);
9431 	if (fixed) {
9432 		isl_int_set_si(v->d, 1);
9433 		return v;
9434 	}
9435 	isl_val_free(v);
9436 	return isl_val_nan(ctx);
9437 }
9438 
isl_map_plain_is_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_int * val)9439 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9440 	enum isl_dim_type type, unsigned pos, isl_int *val)
9441 {
9442 	if (pos >= isl_map_dim(map, type))
9443 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
9444 			"position out of bounds", return isl_bool_error);
9445 	return isl_map_plain_has_fixed_var(map,
9446 		map_offset(map, type) - 1 + pos, val);
9447 }
9448 
9449 /* If "map" obviously lies on a hyperplane where the given dimension
9450  * has a fixed value, then return that value.
9451  * Otherwise return NaN.
9452  */
isl_map_plain_get_val_if_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)9453 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9454 	enum isl_dim_type type, unsigned pos)
9455 {
9456 	isl_ctx *ctx;
9457 	isl_val *v;
9458 	isl_bool fixed;
9459 
9460 	if (!map)
9461 		return NULL;
9462 	ctx = isl_map_get_ctx(map);
9463 	v = isl_val_alloc(ctx);
9464 	if (!v)
9465 		return NULL;
9466 	fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9467 	if (fixed < 0)
9468 		return isl_val_free(v);
9469 	if (fixed) {
9470 		isl_int_set_si(v->d, 1);
9471 		return v;
9472 	}
9473 	isl_val_free(v);
9474 	return isl_val_nan(ctx);
9475 }
9476 
9477 /* If "set" obviously lies on a hyperplane where the given dimension
9478  * has a fixed value, then return that value.
9479  * Otherwise return NaN.
9480  */
isl_set_plain_get_val_if_fixed(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)9481 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
9482 	enum isl_dim_type type, unsigned pos)
9483 {
9484 	return isl_map_plain_get_val_if_fixed(set, type, pos);
9485 }
9486 
9487 /* Check if dimension dim has fixed value and if so and if val is not NULL,
9488  * then return this fixed value in *val.
9489  */
isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set * bset,unsigned dim,isl_int * val)9490 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
9491 	unsigned dim, isl_int *val)
9492 {
9493 	return isl_basic_set_plain_has_fixed_var(bset,
9494 					isl_basic_set_n_param(bset) + dim, val);
9495 }
9496 
9497 /* Return -1 if the constraint "c1" should be sorted before "c2"
9498  * and 1 if it should be sorted after "c2".
9499  * Return 0 if the two constraints are the same (up to the constant term).
9500  *
9501  * In particular, if a constraint involves later variables than another
9502  * then it is sorted after this other constraint.
9503  * uset_gist depends on constraints without existentially quantified
9504  * variables sorting first.
9505  *
9506  * For constraints that have the same latest variable, those
9507  * with the same coefficient for this latest variable (first in absolute value
9508  * and then in actual value) are grouped together.
9509  * This is useful for detecting pairs of constraints that can
9510  * be chained in their printed representation.
9511  *
9512  * Finally, within a group, constraints are sorted according to
9513  * their coefficients (excluding the constant term).
9514  */
sort_constraint_cmp(const void * p1,const void * p2,void * arg)9515 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9516 {
9517 	isl_int **c1 = (isl_int **) p1;
9518 	isl_int **c2 = (isl_int **) p2;
9519 	int l1, l2;
9520 	unsigned size = *(unsigned *) arg;
9521 	int cmp;
9522 
9523 	l1 = isl_seq_last_non_zero(*c1 + 1, size);
9524 	l2 = isl_seq_last_non_zero(*c2 + 1, size);
9525 
9526 	if (l1 != l2)
9527 		return l1 - l2;
9528 
9529 	cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9530 	if (cmp != 0)
9531 		return cmp;
9532 	cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9533 	if (cmp != 0)
9534 		return -cmp;
9535 
9536 	return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9537 }
9538 
9539 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
9540  * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
9541  * and 0 if the two constraints are the same (up to the constant term).
9542  */
isl_basic_map_constraint_cmp(__isl_keep isl_basic_map * bmap,isl_int * c1,isl_int * c2)9543 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
9544 	isl_int *c1, isl_int *c2)
9545 {
9546 	unsigned total;
9547 
9548 	if (!bmap)
9549 		return -2;
9550 	total = isl_basic_map_total_dim(bmap);
9551 	return sort_constraint_cmp(&c1, &c2, &total);
9552 }
9553 
isl_basic_map_sort_constraints(__isl_take isl_basic_map * bmap)9554 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9555 	__isl_take isl_basic_map *bmap)
9556 {
9557 	unsigned total;
9558 
9559 	if (!bmap)
9560 		return NULL;
9561 	if (bmap->n_ineq == 0)
9562 		return bmap;
9563 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9564 		return bmap;
9565 	total = isl_basic_map_total_dim(bmap);
9566 	if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9567 		    &sort_constraint_cmp, &total) < 0)
9568 		return isl_basic_map_free(bmap);
9569 	return bmap;
9570 }
9571 
isl_basic_set_sort_constraints(__isl_take isl_basic_set * bset)9572 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9573 	__isl_take isl_basic_set *bset)
9574 {
9575 	isl_basic_map *bmap = bset_to_bmap(bset);
9576 	return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9577 }
9578 
isl_basic_map_normalize(__isl_take isl_basic_map * bmap)9579 __isl_give isl_basic_map *isl_basic_map_normalize(
9580 	__isl_take isl_basic_map *bmap)
9581 {
9582 	if (!bmap)
9583 		return NULL;
9584 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9585 		return bmap;
9586 	bmap = isl_basic_map_remove_redundancies(bmap);
9587 	bmap = isl_basic_map_sort_constraints(bmap);
9588 	if (bmap)
9589 		ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
9590 	return bmap;
9591 }
isl_basic_map_plain_cmp(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9592 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9593 	__isl_keep isl_basic_map *bmap2)
9594 {
9595 	int i, cmp;
9596 	unsigned total;
9597 	isl_space *space1, *space2;
9598 
9599 	if (!bmap1 || !bmap2)
9600 		return -1;
9601 
9602 	if (bmap1 == bmap2)
9603 		return 0;
9604 	space1 = isl_basic_map_peek_space(bmap1);
9605 	space2 = isl_basic_map_peek_space(bmap2);
9606 	cmp = isl_space_cmp(space1, space2);
9607 	if (cmp)
9608 		return cmp;
9609 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9610 	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9611 		return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9612 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9613 	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9614 		return 0;
9615 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9616 		return 1;
9617 	if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9618 		return -1;
9619 	if (bmap1->n_eq != bmap2->n_eq)
9620 		return bmap1->n_eq - bmap2->n_eq;
9621 	if (bmap1->n_ineq != bmap2->n_ineq)
9622 		return bmap1->n_ineq - bmap2->n_ineq;
9623 	if (bmap1->n_div != bmap2->n_div)
9624 		return bmap1->n_div - bmap2->n_div;
9625 	total = isl_basic_map_total_dim(bmap1);
9626 	for (i = 0; i < bmap1->n_eq; ++i) {
9627 		cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9628 		if (cmp)
9629 			return cmp;
9630 	}
9631 	for (i = 0; i < bmap1->n_ineq; ++i) {
9632 		cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9633 		if (cmp)
9634 			return cmp;
9635 	}
9636 	for (i = 0; i < bmap1->n_div; ++i) {
9637 		cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9638 		if (cmp)
9639 			return cmp;
9640 	}
9641 	return 0;
9642 }
9643 
isl_basic_set_plain_cmp(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9644 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9645 	__isl_keep isl_basic_set *bset2)
9646 {
9647 	return isl_basic_map_plain_cmp(bset1, bset2);
9648 }
9649 
isl_set_plain_cmp(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9650 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9651 {
9652 	int i, cmp;
9653 
9654 	if (set1 == set2)
9655 		return 0;
9656 	if (set1->n != set2->n)
9657 		return set1->n - set2->n;
9658 
9659 	for (i = 0; i < set1->n; ++i) {
9660 		cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9661 		if (cmp)
9662 			return cmp;
9663 	}
9664 
9665 	return 0;
9666 }
9667 
isl_basic_map_plain_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9668 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9669 	__isl_keep isl_basic_map *bmap2)
9670 {
9671 	if (!bmap1 || !bmap2)
9672 		return isl_bool_error;
9673 	return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9674 }
9675 
isl_basic_set_plain_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9676 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9677 	__isl_keep isl_basic_set *bset2)
9678 {
9679 	return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9680 					    bset_to_bmap(bset2));
9681 }
9682 
qsort_bmap_cmp(const void * p1,const void * p2)9683 static int qsort_bmap_cmp(const void *p1, const void *p2)
9684 {
9685 	isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9686 	isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9687 
9688 	return isl_basic_map_plain_cmp(bmap1, bmap2);
9689 }
9690 
9691 /* Sort the basic maps of "map" and remove duplicate basic maps.
9692  *
9693  * While removing basic maps, we make sure that the basic maps remain
9694  * sorted because isl_map_normalize expects the basic maps of the result
9695  * to be sorted.
9696  */
sort_and_remove_duplicates(__isl_take isl_map * map)9697 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9698 {
9699 	int i, j;
9700 
9701 	map = isl_map_remove_empty_parts(map);
9702 	if (!map)
9703 		return NULL;
9704 	qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9705 	for (i = map->n - 1; i >= 1; --i) {
9706 		if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9707 			continue;
9708 		isl_basic_map_free(map->p[i-1]);
9709 		for (j = i; j < map->n; ++j)
9710 			map->p[j - 1] = map->p[j];
9711 		map->n--;
9712 	}
9713 
9714 	return map;
9715 }
9716 
9717 /* Remove obvious duplicates among the basic maps of "map".
9718  *
9719  * Unlike isl_map_normalize, this function does not remove redundant
9720  * constraints and only removes duplicates that have exactly the same
9721  * constraints in the input.  It does sort the constraints and
9722  * the basic maps to ease the detection of duplicates.
9723  *
9724  * If "map" has already been normalized or if the basic maps are
9725  * disjoint, then there can be no duplicates.
9726  */
isl_map_remove_obvious_duplicates(__isl_take isl_map * map)9727 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9728 {
9729 	int i;
9730 	isl_basic_map *bmap;
9731 
9732 	if (!map)
9733 		return NULL;
9734 	if (map->n <= 1)
9735 		return map;
9736 	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9737 		return map;
9738 	for (i = 0; i < map->n; ++i) {
9739 		bmap = isl_basic_map_copy(map->p[i]);
9740 		bmap = isl_basic_map_sort_constraints(bmap);
9741 		if (!bmap)
9742 			return isl_map_free(map);
9743 		isl_basic_map_free(map->p[i]);
9744 		map->p[i] = bmap;
9745 	}
9746 
9747 	map = sort_and_remove_duplicates(map);
9748 	return map;
9749 }
9750 
9751 /* We normalize in place, but if anything goes wrong we need
9752  * to return NULL, so we need to make sure we don't change the
9753  * meaning of any possible other copies of map.
9754  */
isl_map_normalize(__isl_take isl_map * map)9755 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9756 {
9757 	int i;
9758 	struct isl_basic_map *bmap;
9759 
9760 	if (!map)
9761 		return NULL;
9762 	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9763 		return map;
9764 	for (i = 0; i < map->n; ++i) {
9765 		bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9766 		if (!bmap)
9767 			goto error;
9768 		isl_basic_map_free(map->p[i]);
9769 		map->p[i] = bmap;
9770 	}
9771 
9772 	map = sort_and_remove_duplicates(map);
9773 	if (map)
9774 		ISL_F_SET(map, ISL_MAP_NORMALIZED);
9775 	return map;
9776 error:
9777 	isl_map_free(map);
9778 	return NULL;
9779 }
9780 
isl_set_normalize(struct isl_set * set)9781 struct isl_set *isl_set_normalize(struct isl_set *set)
9782 {
9783 	return set_from_map(isl_map_normalize(set_to_map(set)));
9784 }
9785 
isl_map_plain_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9786 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9787 	__isl_keep isl_map *map2)
9788 {
9789 	int i;
9790 	isl_bool equal;
9791 
9792 	if (!map1 || !map2)
9793 		return isl_bool_error;
9794 
9795 	if (map1 == map2)
9796 		return isl_bool_true;
9797 	if (!isl_space_is_equal(map1->dim, map2->dim))
9798 		return isl_bool_false;
9799 
9800 	map1 = isl_map_copy(map1);
9801 	map2 = isl_map_copy(map2);
9802 	map1 = isl_map_normalize(map1);
9803 	map2 = isl_map_normalize(map2);
9804 	if (!map1 || !map2)
9805 		goto error;
9806 	equal = map1->n == map2->n;
9807 	for (i = 0; equal && i < map1->n; ++i) {
9808 		equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9809 		if (equal < 0)
9810 			goto error;
9811 	}
9812 	isl_map_free(map1);
9813 	isl_map_free(map2);
9814 	return equal;
9815 error:
9816 	isl_map_free(map1);
9817 	isl_map_free(map2);
9818 	return isl_bool_error;
9819 }
9820 
isl_set_plain_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9821 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9822 	__isl_keep isl_set *set2)
9823 {
9824 	return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9825 }
9826 
9827 /* Return the basic maps in "map" as a list.
9828  */
isl_map_get_basic_map_list(__isl_keep isl_map * map)9829 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9830 	__isl_keep isl_map *map)
9831 {
9832 	int i;
9833 	isl_ctx *ctx;
9834 	isl_basic_map_list *list;
9835 
9836 	if (!map)
9837 		return NULL;
9838 	ctx = isl_map_get_ctx(map);
9839 	list = isl_basic_map_list_alloc(ctx, map->n);
9840 
9841 	for (i = 0; i < map->n; ++i) {
9842 		isl_basic_map *bmap;
9843 
9844 		bmap = isl_basic_map_copy(map->p[i]);
9845 		list = isl_basic_map_list_add(list, bmap);
9846 	}
9847 
9848 	return list;
9849 }
9850 
9851 /* Return the intersection of the elements in the non-empty list "list".
9852  * All elements are assumed to live in the same space.
9853  */
isl_basic_map_list_intersect(__isl_take isl_basic_map_list * list)9854 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9855 	__isl_take isl_basic_map_list *list)
9856 {
9857 	int i, n;
9858 	isl_basic_map *bmap;
9859 
9860 	if (!list)
9861 		return NULL;
9862 	n = isl_basic_map_list_n_basic_map(list);
9863 	if (n < 1)
9864 		isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9865 			"expecting non-empty list", goto error);
9866 
9867 	bmap = isl_basic_map_list_get_basic_map(list, 0);
9868 	for (i = 1; i < n; ++i) {
9869 		isl_basic_map *bmap_i;
9870 
9871 		bmap_i = isl_basic_map_list_get_basic_map(list, i);
9872 		bmap = isl_basic_map_intersect(bmap, bmap_i);
9873 	}
9874 
9875 	isl_basic_map_list_free(list);
9876 	return bmap;
9877 error:
9878 	isl_basic_map_list_free(list);
9879 	return NULL;
9880 }
9881 
9882 /* Return the intersection of the elements in the non-empty list "list".
9883  * All elements are assumed to live in the same space.
9884  */
isl_basic_set_list_intersect(__isl_take isl_basic_set_list * list)9885 __isl_give isl_basic_set *isl_basic_set_list_intersect(
9886 	__isl_take isl_basic_set_list *list)
9887 {
9888 	return isl_basic_map_list_intersect(list);
9889 }
9890 
9891 /* Return the union of the elements of "list".
9892  * The list is required to have at least one element.
9893  */
isl_basic_set_list_union(__isl_take isl_basic_set_list * list)9894 __isl_give isl_set *isl_basic_set_list_union(
9895 	__isl_take isl_basic_set_list *list)
9896 {
9897 	int i, n;
9898 	isl_space *space;
9899 	isl_basic_set *bset;
9900 	isl_set *set;
9901 
9902 	if (!list)
9903 		return NULL;
9904 	n = isl_basic_set_list_n_basic_set(list);
9905 	if (n < 1)
9906 		isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9907 			"expecting non-empty list", goto error);
9908 
9909 	bset = isl_basic_set_list_get_basic_set(list, 0);
9910 	space = isl_basic_set_get_space(bset);
9911 	isl_basic_set_free(bset);
9912 
9913 	set = isl_set_alloc_space(space, n, 0);
9914 	for (i = 0; i < n; ++i) {
9915 		bset = isl_basic_set_list_get_basic_set(list, i);
9916 		set = isl_set_add_basic_set(set, bset);
9917 	}
9918 
9919 	isl_basic_set_list_free(list);
9920 	return set;
9921 error:
9922 	isl_basic_set_list_free(list);
9923 	return NULL;
9924 }
9925 
9926 /* Return the union of the elements in the non-empty list "list".
9927  * All elements are assumed to live in the same space.
9928  */
isl_set_list_union(__isl_take isl_set_list * list)9929 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9930 {
9931 	int i, n;
9932 	isl_set *set;
9933 
9934 	if (!list)
9935 		return NULL;
9936 	n = isl_set_list_n_set(list);
9937 	if (n < 1)
9938 		isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9939 			"expecting non-empty list", goto error);
9940 
9941 	set = isl_set_list_get_set(list, 0);
9942 	for (i = 1; i < n; ++i) {
9943 		isl_set *set_i;
9944 
9945 		set_i = isl_set_list_get_set(list, i);
9946 		set = isl_set_union(set, set_i);
9947 	}
9948 
9949 	isl_set_list_free(list);
9950 	return set;
9951 error:
9952 	isl_set_list_free(list);
9953 	return NULL;
9954 }
9955 
isl_basic_map_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)9956 __isl_give isl_basic_map *isl_basic_map_product(
9957 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9958 {
9959 	isl_space *dim_result = NULL;
9960 	struct isl_basic_map *bmap;
9961 	unsigned in1, in2, out1, out2, nparam, total, pos;
9962 	struct isl_dim_map *dim_map1, *dim_map2;
9963 
9964 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9965 		goto error;
9966 	dim_result = isl_space_product(isl_space_copy(bmap1->dim),
9967 						   isl_space_copy(bmap2->dim));
9968 
9969 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9970 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9971 	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9972 	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9973 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9974 
9975 	total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9976 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9977 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9978 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9979 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9980 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9981 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9982 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9983 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9984 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
9985 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9986 
9987 	bmap = isl_basic_map_alloc_space(dim_result,
9988 			bmap1->n_div + bmap2->n_div,
9989 			bmap1->n_eq + bmap2->n_eq,
9990 			bmap1->n_ineq + bmap2->n_ineq);
9991 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9992 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9993 	bmap = isl_basic_map_simplify(bmap);
9994 	return isl_basic_map_finalize(bmap);
9995 error:
9996 	isl_basic_map_free(bmap1);
9997 	isl_basic_map_free(bmap2);
9998 	return NULL;
9999 }
10000 
isl_basic_map_flat_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10001 __isl_give isl_basic_map *isl_basic_map_flat_product(
10002 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10003 {
10004 	isl_basic_map *prod;
10005 
10006 	prod = isl_basic_map_product(bmap1, bmap2);
10007 	prod = isl_basic_map_flatten(prod);
10008 	return prod;
10009 }
10010 
isl_basic_set_flat_product(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)10011 __isl_give isl_basic_set *isl_basic_set_flat_product(
10012 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10013 {
10014 	return isl_basic_map_flat_range_product(bset1, bset2);
10015 }
10016 
isl_basic_map_domain_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10017 __isl_give isl_basic_map *isl_basic_map_domain_product(
10018 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10019 {
10020 	isl_space *space_result = NULL;
10021 	isl_basic_map *bmap;
10022 	unsigned in1, in2, out, nparam, total, pos;
10023 	struct isl_dim_map *dim_map1, *dim_map2;
10024 
10025 	if (!bmap1 || !bmap2)
10026 		goto error;
10027 
10028 	space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
10029 						isl_space_copy(bmap2->dim));
10030 
10031 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10032 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10033 	out = isl_basic_map_dim(bmap1, isl_dim_out);
10034 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10035 
10036 	total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10037 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10038 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10039 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10040 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10041 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10042 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10043 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10044 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10045 	isl_dim_map_div(dim_map1, bmap1, pos += out);
10046 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10047 
10048 	bmap = isl_basic_map_alloc_space(space_result,
10049 			bmap1->n_div + bmap2->n_div,
10050 			bmap1->n_eq + bmap2->n_eq,
10051 			bmap1->n_ineq + bmap2->n_ineq);
10052 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10053 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10054 	bmap = isl_basic_map_simplify(bmap);
10055 	return isl_basic_map_finalize(bmap);
10056 error:
10057 	isl_basic_map_free(bmap1);
10058 	isl_basic_map_free(bmap2);
10059 	return NULL;
10060 }
10061 
isl_basic_map_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10062 __isl_give isl_basic_map *isl_basic_map_range_product(
10063 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10064 {
10065 	isl_bool rational;
10066 	isl_space *dim_result = NULL;
10067 	isl_basic_map *bmap;
10068 	unsigned in, out1, out2, nparam, total, pos;
10069 	struct isl_dim_map *dim_map1, *dim_map2;
10070 
10071 	rational = isl_basic_map_is_rational(bmap1);
10072 	if (rational >= 0 && rational)
10073 		rational = isl_basic_map_is_rational(bmap2);
10074 	if (!bmap1 || !bmap2 || rational < 0)
10075 		goto error;
10076 
10077 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10078 		goto error;
10079 
10080 	dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10081 					   isl_space_copy(bmap2->dim));
10082 
10083 	in = isl_basic_map_dim(bmap1, isl_dim_in);
10084 	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10085 	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10086 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10087 
10088 	total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10089 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10090 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10091 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10092 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10093 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10094 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10095 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10096 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10097 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
10098 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10099 
10100 	bmap = isl_basic_map_alloc_space(dim_result,
10101 			bmap1->n_div + bmap2->n_div,
10102 			bmap1->n_eq + bmap2->n_eq,
10103 			bmap1->n_ineq + bmap2->n_ineq);
10104 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10105 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10106 	if (rational)
10107 		bmap = isl_basic_map_set_rational(bmap);
10108 	bmap = isl_basic_map_simplify(bmap);
10109 	return isl_basic_map_finalize(bmap);
10110 error:
10111 	isl_basic_map_free(bmap1);
10112 	isl_basic_map_free(bmap2);
10113 	return NULL;
10114 }
10115 
isl_basic_map_flat_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10116 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10117 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10118 {
10119 	isl_basic_map *prod;
10120 
10121 	prod = isl_basic_map_range_product(bmap1, bmap2);
10122 	prod = isl_basic_map_flatten_range(prod);
10123 	return prod;
10124 }
10125 
10126 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10127  * and collect the results.
10128  * The result live in the space obtained by calling "space_product"
10129  * on the spaces of "map1" and "map2".
10130  * If "remove_duplicates" is set then the result may contain duplicates
10131  * (even if the inputs do not) and so we try and remove the obvious
10132  * duplicates.
10133  */
map_product(__isl_take isl_map * map1,__isl_take isl_map * map2,__isl_give isl_space * (* space_product)(__isl_take isl_space * left,__isl_take isl_space * right),__isl_give isl_basic_map * (* basic_map_product)(__isl_take isl_basic_map * left,__isl_take isl_basic_map * right),int remove_duplicates)10134 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10135 	__isl_take isl_map *map2,
10136 	__isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10137 					   __isl_take isl_space *right),
10138 	__isl_give isl_basic_map *(*basic_map_product)(
10139 		__isl_take isl_basic_map *left,
10140 		__isl_take isl_basic_map *right),
10141 	int remove_duplicates)
10142 {
10143 	unsigned flags = 0;
10144 	struct isl_map *result;
10145 	int i, j;
10146 	isl_bool m;
10147 
10148 	m = isl_map_has_equal_params(map1, map2);
10149 	if (m < 0)
10150 		goto error;
10151 	if (!m)
10152 		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10153 			"parameters don't match", goto error);
10154 
10155 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10156 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10157 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10158 
10159 	result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10160 					       isl_space_copy(map2->dim)),
10161 				map1->n * map2->n, flags);
10162 	if (!result)
10163 		goto error;
10164 	for (i = 0; i < map1->n; ++i)
10165 		for (j = 0; j < map2->n; ++j) {
10166 			struct isl_basic_map *part;
10167 			part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10168 						 isl_basic_map_copy(map2->p[j]));
10169 			if (isl_basic_map_is_empty(part))
10170 				isl_basic_map_free(part);
10171 			else
10172 				result = isl_map_add_basic_map(result, part);
10173 			if (!result)
10174 				goto error;
10175 		}
10176 	if (remove_duplicates)
10177 		result = isl_map_remove_obvious_duplicates(result);
10178 	isl_map_free(map1);
10179 	isl_map_free(map2);
10180 	return result;
10181 error:
10182 	isl_map_free(map1);
10183 	isl_map_free(map2);
10184 	return NULL;
10185 }
10186 
10187 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10188  */
map_product_aligned(__isl_take isl_map * map1,__isl_take isl_map * map2)10189 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
10190 	__isl_take isl_map *map2)
10191 {
10192 	return map_product(map1, map2, &isl_space_product,
10193 			&isl_basic_map_product, 0);
10194 }
10195 
isl_map_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10196 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10197 	__isl_take isl_map *map2)
10198 {
10199 	return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
10200 }
10201 
10202 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10203  */
isl_map_flat_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10204 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10205 	__isl_take isl_map *map2)
10206 {
10207 	isl_map *prod;
10208 
10209 	prod = isl_map_product(map1, map2);
10210 	prod = isl_map_flatten(prod);
10211 	return prod;
10212 }
10213 
10214 /* Given two set A and B, construct its Cartesian product A x B.
10215  */
isl_set_product(struct isl_set * set1,struct isl_set * set2)10216 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
10217 {
10218 	return isl_map_range_product(set1, set2);
10219 }
10220 
isl_set_flat_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10221 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10222 	__isl_take isl_set *set2)
10223 {
10224 	return isl_map_flat_range_product(set1, set2);
10225 }
10226 
10227 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10228  */
map_domain_product_aligned(__isl_take isl_map * map1,__isl_take isl_map * map2)10229 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
10230 	__isl_take isl_map *map2)
10231 {
10232 	return map_product(map1, map2, &isl_space_domain_product,
10233 				&isl_basic_map_domain_product, 1);
10234 }
10235 
10236 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10237  */
map_range_product_aligned(__isl_take isl_map * map1,__isl_take isl_map * map2)10238 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
10239 	__isl_take isl_map *map2)
10240 {
10241 	return map_product(map1, map2, &isl_space_range_product,
10242 				&isl_basic_map_range_product, 1);
10243 }
10244 
isl_map_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10245 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10246 	__isl_take isl_map *map2)
10247 {
10248 	return isl_map_align_params_map_map_and(map1, map2,
10249 						&map_domain_product_aligned);
10250 }
10251 
isl_map_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10252 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10253 	__isl_take isl_map *map2)
10254 {
10255 	return isl_map_align_params_map_map_and(map1, map2,
10256 						&map_range_product_aligned);
10257 }
10258 
10259 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10260  */
isl_map_factor_domain(__isl_take isl_map * map)10261 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10262 {
10263 	isl_space *space;
10264 	int total1, keep1, total2, keep2;
10265 
10266 	if (!map)
10267 		return NULL;
10268 	if (!isl_space_domain_is_wrapping(map->dim) ||
10269 	    !isl_space_range_is_wrapping(map->dim))
10270 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10271 			"not a product", return isl_map_free(map));
10272 
10273 	space = isl_map_get_space(map);
10274 	total1 = isl_space_dim(space, isl_dim_in);
10275 	total2 = isl_space_dim(space, isl_dim_out);
10276 	space = isl_space_factor_domain(space);
10277 	keep1 = isl_space_dim(space, isl_dim_in);
10278 	keep2 = isl_space_dim(space, isl_dim_out);
10279 	map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10280 	map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10281 	map = isl_map_reset_space(map, space);
10282 
10283 	return map;
10284 }
10285 
10286 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10287  */
isl_map_factor_range(__isl_take isl_map * map)10288 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10289 {
10290 	isl_space *space;
10291 	int total1, keep1, total2, keep2;
10292 
10293 	if (!map)
10294 		return NULL;
10295 	if (!isl_space_domain_is_wrapping(map->dim) ||
10296 	    !isl_space_range_is_wrapping(map->dim))
10297 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10298 			"not a product", return isl_map_free(map));
10299 
10300 	space = isl_map_get_space(map);
10301 	total1 = isl_space_dim(space, isl_dim_in);
10302 	total2 = isl_space_dim(space, isl_dim_out);
10303 	space = isl_space_factor_range(space);
10304 	keep1 = isl_space_dim(space, isl_dim_in);
10305 	keep2 = isl_space_dim(space, isl_dim_out);
10306 	map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10307 	map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10308 	map = isl_map_reset_space(map, space);
10309 
10310 	return map;
10311 }
10312 
10313 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10314  */
isl_map_domain_factor_domain(__isl_take isl_map * map)10315 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10316 {
10317 	isl_space *space;
10318 	int total, keep;
10319 
10320 	if (!map)
10321 		return NULL;
10322 	if (!isl_space_domain_is_wrapping(map->dim))
10323 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10324 			"domain is not a product", return isl_map_free(map));
10325 
10326 	space = isl_map_get_space(map);
10327 	total = isl_space_dim(space, isl_dim_in);
10328 	space = isl_space_domain_factor_domain(space);
10329 	keep = isl_space_dim(space, isl_dim_in);
10330 	map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10331 	map = isl_map_reset_space(map, space);
10332 
10333 	return map;
10334 }
10335 
10336 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10337  */
isl_map_domain_factor_range(__isl_take isl_map * map)10338 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10339 {
10340 	isl_space *space;
10341 	int total, keep;
10342 
10343 	if (!map)
10344 		return NULL;
10345 	if (!isl_space_domain_is_wrapping(map->dim))
10346 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10347 			"domain is not a product", return isl_map_free(map));
10348 
10349 	space = isl_map_get_space(map);
10350 	total = isl_space_dim(space, isl_dim_in);
10351 	space = isl_space_domain_factor_range(space);
10352 	keep = isl_space_dim(space, isl_dim_in);
10353 	map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10354 	map = isl_map_reset_space(map, space);
10355 
10356 	return map;
10357 }
10358 
10359 /* Given a map A -> [B -> C], extract the map A -> B.
10360  */
isl_map_range_factor_domain(__isl_take isl_map * map)10361 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10362 {
10363 	isl_space *space;
10364 	int total, keep;
10365 
10366 	if (!map)
10367 		return NULL;
10368 	if (!isl_space_range_is_wrapping(map->dim))
10369 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10370 			"range is not a product", return isl_map_free(map));
10371 
10372 	space = isl_map_get_space(map);
10373 	total = isl_space_dim(space, isl_dim_out);
10374 	space = isl_space_range_factor_domain(space);
10375 	keep = isl_space_dim(space, isl_dim_out);
10376 	map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10377 	map = isl_map_reset_space(map, space);
10378 
10379 	return map;
10380 }
10381 
10382 /* Given a map A -> [B -> C], extract the map A -> C.
10383  */
isl_map_range_factor_range(__isl_take isl_map * map)10384 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10385 {
10386 	isl_space *space;
10387 	int total, keep;
10388 
10389 	if (!map)
10390 		return NULL;
10391 	if (!isl_space_range_is_wrapping(map->dim))
10392 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10393 			"range is not a product", return isl_map_free(map));
10394 
10395 	space = isl_map_get_space(map);
10396 	total = isl_space_dim(space, isl_dim_out);
10397 	space = isl_space_range_factor_range(space);
10398 	keep = isl_space_dim(space, isl_dim_out);
10399 	map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10400 	map = isl_map_reset_space(map, space);
10401 
10402 	return map;
10403 }
10404 
10405 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10406  */
isl_map_flat_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10407 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10408 	__isl_take isl_map *map2)
10409 {
10410 	isl_map *prod;
10411 
10412 	prod = isl_map_domain_product(map1, map2);
10413 	prod = isl_map_flatten_domain(prod);
10414 	return prod;
10415 }
10416 
10417 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10418  */
isl_map_flat_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10419 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10420 	__isl_take isl_map *map2)
10421 {
10422 	isl_map *prod;
10423 
10424 	prod = isl_map_range_product(map1, map2);
10425 	prod = isl_map_flatten_range(prod);
10426 	return prod;
10427 }
10428 
isl_basic_map_get_hash(__isl_keep isl_basic_map * bmap)10429 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10430 {
10431 	int i;
10432 	uint32_t hash = isl_hash_init();
10433 	unsigned total;
10434 
10435 	if (!bmap)
10436 		return 0;
10437 	bmap = isl_basic_map_copy(bmap);
10438 	bmap = isl_basic_map_normalize(bmap);
10439 	if (!bmap)
10440 		return 0;
10441 	total = isl_basic_map_total_dim(bmap);
10442 	isl_hash_byte(hash, bmap->n_eq & 0xFF);
10443 	for (i = 0; i < bmap->n_eq; ++i) {
10444 		uint32_t c_hash;
10445 		c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
10446 		isl_hash_hash(hash, c_hash);
10447 	}
10448 	isl_hash_byte(hash, bmap->n_ineq & 0xFF);
10449 	for (i = 0; i < bmap->n_ineq; ++i) {
10450 		uint32_t c_hash;
10451 		c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
10452 		isl_hash_hash(hash, c_hash);
10453 	}
10454 	isl_hash_byte(hash, bmap->n_div & 0xFF);
10455 	for (i = 0; i < bmap->n_div; ++i) {
10456 		uint32_t c_hash;
10457 		if (isl_int_is_zero(bmap->div[i][0]))
10458 			continue;
10459 		isl_hash_byte(hash, i & 0xFF);
10460 		c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
10461 		isl_hash_hash(hash, c_hash);
10462 	}
10463 	isl_basic_map_free(bmap);
10464 	return hash;
10465 }
10466 
isl_basic_set_get_hash(__isl_keep isl_basic_set * bset)10467 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
10468 {
10469 	return isl_basic_map_get_hash(bset_to_bmap(bset));
10470 }
10471 
isl_map_get_hash(__isl_keep isl_map * map)10472 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
10473 {
10474 	int i;
10475 	uint32_t hash;
10476 
10477 	if (!map)
10478 		return 0;
10479 	map = isl_map_copy(map);
10480 	map = isl_map_normalize(map);
10481 	if (!map)
10482 		return 0;
10483 
10484 	hash = isl_hash_init();
10485 	for (i = 0; i < map->n; ++i) {
10486 		uint32_t bmap_hash;
10487 		bmap_hash = isl_basic_map_get_hash(map->p[i]);
10488 		isl_hash_hash(hash, bmap_hash);
10489 	}
10490 
10491 	isl_map_free(map);
10492 
10493 	return hash;
10494 }
10495 
isl_set_get_hash(__isl_keep isl_set * set)10496 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
10497 {
10498 	return isl_map_get_hash(set_to_map(set));
10499 }
10500 
10501 /* Return the number of basic maps in the (current) representation of "map".
10502  */
isl_map_n_basic_map(__isl_keep isl_map * map)10503 int isl_map_n_basic_map(__isl_keep isl_map *map)
10504 {
10505 	return map ? map->n : 0;
10506 }
10507 
isl_set_n_basic_set(__isl_keep isl_set * set)10508 int isl_set_n_basic_set(__isl_keep isl_set *set)
10509 {
10510 	return set ? set->n : 0;
10511 }
10512 
isl_map_foreach_basic_map(__isl_keep isl_map * map,isl_stat (* fn)(__isl_take isl_basic_map * bmap,void * user),void * user)10513 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
10514 	isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10515 {
10516 	int i;
10517 
10518 	if (!map)
10519 		return isl_stat_error;
10520 
10521 	for (i = 0; i < map->n; ++i)
10522 		if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10523 			return isl_stat_error;
10524 
10525 	return isl_stat_ok;
10526 }
10527 
isl_set_foreach_basic_set(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_basic_set * bset,void * user),void * user)10528 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10529 	isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10530 {
10531 	int i;
10532 
10533 	if (!set)
10534 		return isl_stat_error;
10535 
10536 	for (i = 0; i < set->n; ++i)
10537 		if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10538 			return isl_stat_error;
10539 
10540 	return isl_stat_ok;
10541 }
10542 
10543 /* Return a list of basic sets, the union of which is equal to "set".
10544  */
isl_set_get_basic_set_list(__isl_keep isl_set * set)10545 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10546 	__isl_keep isl_set *set)
10547 {
10548 	int i;
10549 	isl_basic_set_list *list;
10550 
10551 	if (!set)
10552 		return NULL;
10553 
10554 	list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10555 	for (i = 0; i < set->n; ++i) {
10556 		isl_basic_set *bset;
10557 
10558 		bset = isl_basic_set_copy(set->p[i]);
10559 		list = isl_basic_set_list_add(list, bset);
10560 	}
10561 
10562 	return list;
10563 }
10564 
isl_basic_set_lift(__isl_take isl_basic_set * bset)10565 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10566 {
10567 	isl_space *dim;
10568 
10569 	if (!bset)
10570 		return NULL;
10571 
10572 	bset = isl_basic_set_cow(bset);
10573 	if (!bset)
10574 		return NULL;
10575 
10576 	dim = isl_basic_set_get_space(bset);
10577 	dim = isl_space_lift(dim, bset->n_div);
10578 	if (!dim)
10579 		goto error;
10580 	isl_space_free(bset->dim);
10581 	bset->dim = dim;
10582 	bset->extra -= bset->n_div;
10583 	bset->n_div = 0;
10584 
10585 	bset = isl_basic_set_finalize(bset);
10586 
10587 	return bset;
10588 error:
10589 	isl_basic_set_free(bset);
10590 	return NULL;
10591 }
10592 
isl_set_lift(__isl_take isl_set * set)10593 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10594 {
10595 	int i;
10596 	isl_space *dim;
10597 	unsigned n_div;
10598 
10599 	set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10600 
10601 	if (!set)
10602 		return NULL;
10603 
10604 	set = isl_set_cow(set);
10605 	if (!set)
10606 		return NULL;
10607 
10608 	n_div = set->p[0]->n_div;
10609 	dim = isl_set_get_space(set);
10610 	dim = isl_space_lift(dim, n_div);
10611 	if (!dim)
10612 		goto error;
10613 	isl_space_free(set->dim);
10614 	set->dim = dim;
10615 
10616 	for (i = 0; i < set->n; ++i) {
10617 		set->p[i] = isl_basic_set_lift(set->p[i]);
10618 		if (!set->p[i])
10619 			goto error;
10620 	}
10621 
10622 	return set;
10623 error:
10624 	isl_set_free(set);
10625 	return NULL;
10626 }
10627 
isl_basic_set_size(__isl_keep isl_basic_set * bset)10628 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10629 {
10630 	unsigned dim;
10631 	int size = 0;
10632 
10633 	if (!bset)
10634 		return -1;
10635 
10636 	dim = isl_basic_set_total_dim(bset);
10637 	size += bset->n_eq * (1 + dim);
10638 	size += bset->n_ineq * (1 + dim);
10639 	size += bset->n_div * (2 + dim);
10640 
10641 	return size;
10642 }
10643 
isl_set_size(__isl_keep isl_set * set)10644 int isl_set_size(__isl_keep isl_set *set)
10645 {
10646 	int i;
10647 	int size = 0;
10648 
10649 	if (!set)
10650 		return -1;
10651 
10652 	for (i = 0; i < set->n; ++i)
10653 		size += isl_basic_set_size(set->p[i]);
10654 
10655 	return size;
10656 }
10657 
10658 /* Check if there is any lower bound (if lower == 0) and/or upper
10659  * bound (if upper == 0) on the specified dim.
10660  */
basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int lower,int upper)10661 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10662 	enum isl_dim_type type, unsigned pos, int lower, int upper)
10663 {
10664 	int i;
10665 
10666 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10667 		return isl_bool_error;
10668 
10669 	pos += isl_basic_map_offset(bmap, type);
10670 
10671 	for (i = 0; i < bmap->n_div; ++i) {
10672 		if (isl_int_is_zero(bmap->div[i][0]))
10673 			continue;
10674 		if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10675 			return isl_bool_true;
10676 	}
10677 
10678 	for (i = 0; i < bmap->n_eq; ++i)
10679 		if (!isl_int_is_zero(bmap->eq[i][pos]))
10680 			return isl_bool_true;
10681 
10682 	for (i = 0; i < bmap->n_ineq; ++i) {
10683 		int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10684 		if (sgn > 0)
10685 			lower = 1;
10686 		if (sgn < 0)
10687 			upper = 1;
10688 	}
10689 
10690 	return lower && upper;
10691 }
10692 
isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)10693 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10694 	enum isl_dim_type type, unsigned pos)
10695 {
10696 	return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10697 }
10698 
isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)10699 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10700 	enum isl_dim_type type, unsigned pos)
10701 {
10702 	return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10703 }
10704 
isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)10705 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10706 	enum isl_dim_type type, unsigned pos)
10707 {
10708 	return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10709 }
10710 
isl_map_dim_is_bounded(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)10711 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10712 	enum isl_dim_type type, unsigned pos)
10713 {
10714 	int i;
10715 
10716 	if (!map)
10717 		return isl_bool_error;
10718 
10719 	for (i = 0; i < map->n; ++i) {
10720 		isl_bool bounded;
10721 		bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10722 		if (bounded < 0 || !bounded)
10723 			return bounded;
10724 	}
10725 
10726 	return isl_bool_true;
10727 }
10728 
10729 /* Return true if the specified dim is involved in both an upper bound
10730  * and a lower bound.
10731  */
isl_set_dim_is_bounded(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10732 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10733 	enum isl_dim_type type, unsigned pos)
10734 {
10735 	return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10736 }
10737 
10738 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10739  */
has_any_bound(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_bool (* fn)(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos))10740 static isl_bool has_any_bound(__isl_keep isl_map *map,
10741 	enum isl_dim_type type, unsigned pos,
10742 	isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10743 		  enum isl_dim_type type, unsigned pos))
10744 {
10745 	int i;
10746 
10747 	if (!map)
10748 		return isl_bool_error;
10749 
10750 	for (i = 0; i < map->n; ++i) {
10751 		isl_bool bounded;
10752 		bounded = fn(map->p[i], type, pos);
10753 		if (bounded < 0 || bounded)
10754 			return bounded;
10755 	}
10756 
10757 	return isl_bool_false;
10758 }
10759 
10760 /* Return 1 if the specified dim is involved in any lower bound.
10761  */
isl_set_dim_has_any_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10762 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10763 	enum isl_dim_type type, unsigned pos)
10764 {
10765 	return has_any_bound(set, type, pos,
10766 				&isl_basic_map_dim_has_lower_bound);
10767 }
10768 
10769 /* Return 1 if the specified dim is involved in any upper bound.
10770  */
isl_set_dim_has_any_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10771 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10772 	enum isl_dim_type type, unsigned pos)
10773 {
10774 	return has_any_bound(set, type, pos,
10775 				&isl_basic_map_dim_has_upper_bound);
10776 }
10777 
10778 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10779  */
has_bound(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_bool (* fn)(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos))10780 static isl_bool has_bound(__isl_keep isl_map *map,
10781 	enum isl_dim_type type, unsigned pos,
10782 	isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10783 		  enum isl_dim_type type, unsigned pos))
10784 {
10785 	int i;
10786 
10787 	if (!map)
10788 		return isl_bool_error;
10789 
10790 	for (i = 0; i < map->n; ++i) {
10791 		isl_bool bounded;
10792 		bounded = fn(map->p[i], type, pos);
10793 		if (bounded < 0 || !bounded)
10794 			return bounded;
10795 	}
10796 
10797 	return isl_bool_true;
10798 }
10799 
10800 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10801  */
isl_set_dim_has_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10802 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10803 	enum isl_dim_type type, unsigned pos)
10804 {
10805 	return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10806 }
10807 
10808 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10809  */
isl_set_dim_has_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10810 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10811 	enum isl_dim_type type, unsigned pos)
10812 {
10813 	return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10814 }
10815 
10816 /* For each of the "n" variables starting at "first", determine
10817  * the sign of the variable and put the results in the first "n"
10818  * elements of the array "signs".
10819  * Sign
10820  *	1 means that the variable is non-negative
10821  *	-1 means that the variable is non-positive
10822  *	0 means the variable attains both positive and negative values.
10823  */
isl_basic_set_vars_get_sign(__isl_keep isl_basic_set * bset,unsigned first,unsigned n,int * signs)10824 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10825 	unsigned first, unsigned n, int *signs)
10826 {
10827 	isl_vec *bound = NULL;
10828 	struct isl_tab *tab = NULL;
10829 	struct isl_tab_undo *snap;
10830 	int i;
10831 
10832 	if (!bset || !signs)
10833 		return isl_stat_error;
10834 
10835 	bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10836 	tab = isl_tab_from_basic_set(bset, 0);
10837 	if (!bound || !tab)
10838 		goto error;
10839 
10840 	isl_seq_clr(bound->el, bound->size);
10841 	isl_int_set_si(bound->el[0], -1);
10842 
10843 	snap = isl_tab_snap(tab);
10844 	for (i = 0; i < n; ++i) {
10845 		int empty;
10846 
10847 		isl_int_set_si(bound->el[1 + first + i], -1);
10848 		if (isl_tab_add_ineq(tab, bound->el) < 0)
10849 			goto error;
10850 		empty = tab->empty;
10851 		isl_int_set_si(bound->el[1 + first + i], 0);
10852 		if (isl_tab_rollback(tab, snap) < 0)
10853 			goto error;
10854 
10855 		if (empty) {
10856 			signs[i] = 1;
10857 			continue;
10858 		}
10859 
10860 		isl_int_set_si(bound->el[1 + first + i], 1);
10861 		if (isl_tab_add_ineq(tab, bound->el) < 0)
10862 			goto error;
10863 		empty = tab->empty;
10864 		isl_int_set_si(bound->el[1 + first + i], 0);
10865 		if (isl_tab_rollback(tab, snap) < 0)
10866 			goto error;
10867 
10868 		signs[i] = empty ? -1 : 0;
10869 	}
10870 
10871 	isl_tab_free(tab);
10872 	isl_vec_free(bound);
10873 	return isl_stat_ok;
10874 error:
10875 	isl_tab_free(tab);
10876 	isl_vec_free(bound);
10877 	return isl_stat_error;
10878 }
10879 
isl_basic_set_dims_get_sign(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n,int * signs)10880 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10881 	enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10882 {
10883 	if (!bset || !signs)
10884 		return isl_stat_error;
10885 	isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
10886 		return isl_stat_error);
10887 
10888 	first += pos(bset->dim, type) - 1;
10889 	return isl_basic_set_vars_get_sign(bset, first, n, signs);
10890 }
10891 
10892 /* Is it possible for the integer division "div" to depend (possibly
10893  * indirectly) on any output dimensions?
10894  *
10895  * If the div is undefined, then we conservatively assume that it
10896  * may depend on them.
10897  * Otherwise, we check if it actually depends on them or on any integer
10898  * divisions that may depend on them.
10899  */
div_may_involve_output(__isl_keep isl_basic_map * bmap,int div)10900 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10901 {
10902 	int i;
10903 	unsigned n_out, o_out;
10904 	unsigned n_div, o_div;
10905 
10906 	if (isl_int_is_zero(bmap->div[div][0]))
10907 		return isl_bool_true;
10908 
10909 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
10910 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
10911 
10912 	if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10913 		return isl_bool_true;
10914 
10915 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
10916 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
10917 
10918 	for (i = 0; i < n_div; ++i) {
10919 		isl_bool may_involve;
10920 
10921 		if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10922 			continue;
10923 		may_involve = div_may_involve_output(bmap, i);
10924 		if (may_involve < 0 || may_involve)
10925 			return may_involve;
10926 	}
10927 
10928 	return isl_bool_false;
10929 }
10930 
10931 /* Return the first integer division of "bmap" in the range
10932  * [first, first + n[ that may depend on any output dimensions and
10933  * that has a non-zero coefficient in "c" (where the first coefficient
10934  * in "c" corresponds to integer division "first").
10935  */
first_div_may_involve_output(__isl_keep isl_basic_map * bmap,isl_int * c,int first,int n)10936 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10937 	isl_int *c, int first, int n)
10938 {
10939 	int k;
10940 
10941 	if (!bmap)
10942 		return -1;
10943 
10944 	for (k = first; k < first + n; ++k) {
10945 		isl_bool may_involve;
10946 
10947 		if (isl_int_is_zero(c[k]))
10948 			continue;
10949 		may_involve = div_may_involve_output(bmap, k);
10950 		if (may_involve < 0)
10951 			return -1;
10952 		if (may_involve)
10953 			return k;
10954 	}
10955 
10956 	return first + n;
10957 }
10958 
10959 /* Look for a pair of inequality constraints in "bmap" of the form
10960  *
10961  *	-l + i >= 0		or		i >= l
10962  * and
10963  *	n + l - i >= 0		or		i <= l + n
10964  *
10965  * with n < "m" and i the output dimension at position "pos".
10966  * (Note that n >= 0 as otherwise the two constraints would conflict.)
10967  * Furthermore, "l" is only allowed to involve parameters, input dimensions
10968  * and earlier output dimensions, as well as integer divisions that do
10969  * not involve any of the output dimensions.
10970  *
10971  * Return the index of the first inequality constraint or bmap->n_ineq
10972  * if no such pair can be found.
10973  */
find_modulo_constraint_pair(__isl_keep isl_basic_map * bmap,int pos,isl_int m)10974 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10975 	int pos, isl_int m)
10976 {
10977 	int i, j;
10978 	isl_ctx *ctx;
10979 	unsigned total;
10980 	unsigned n_div, o_div;
10981 	unsigned n_out, o_out;
10982 	int less;
10983 
10984 	if (!bmap)
10985 		return -1;
10986 
10987 	ctx = isl_basic_map_get_ctx(bmap);
10988 	total = isl_basic_map_total_dim(bmap);
10989 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
10990 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
10991 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
10992 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
10993 	for (i = 0; i < bmap->n_ineq; ++i) {
10994 		if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
10995 			continue;
10996 		if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
10997 					n_out - (pos + 1)) != -1)
10998 			continue;
10999 		if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11000 						0, n_div) < n_div)
11001 			continue;
11002 		for (j = i + 1; j < bmap->n_ineq; ++j) {
11003 			if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11004 					    ctx->one))
11005 				continue;
11006 			if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11007 					    bmap->ineq[j] + 1, total))
11008 				continue;
11009 			break;
11010 		}
11011 		if (j >= bmap->n_ineq)
11012 			continue;
11013 		isl_int_add(bmap->ineq[i][0],
11014 			    bmap->ineq[i][0], bmap->ineq[j][0]);
11015 		less = isl_int_abs_lt(bmap->ineq[i][0], m);
11016 		isl_int_sub(bmap->ineq[i][0],
11017 			    bmap->ineq[i][0], bmap->ineq[j][0]);
11018 		if (!less)
11019 			continue;
11020 		if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11021 			return i;
11022 		else
11023 			return j;
11024 	}
11025 
11026 	return bmap->n_ineq;
11027 }
11028 
11029 /* Return the index of the equality of "bmap" that defines
11030  * the output dimension "pos" in terms of earlier dimensions.
11031  * The equality may also involve integer divisions, as long
11032  * as those integer divisions are defined in terms of
11033  * parameters or input dimensions.
11034  * In this case, *div is set to the number of integer divisions and
11035  * *ineq is set to the number of inequality constraints (provided
11036  * div and ineq are not NULL).
11037  *
11038  * The equality may also involve a single integer division involving
11039  * the output dimensions (typically only output dimension "pos") as
11040  * long as the coefficient of output dimension "pos" is 1 or -1 and
11041  * there is a pair of constraints i >= l and i <= l + n, with i referring
11042  * to output dimension "pos", l an expression involving only earlier
11043  * dimensions and n smaller than the coefficient of the integer division
11044  * in the equality.  In this case, the output dimension can be defined
11045  * in terms of a modulo expression that does not involve the integer division.
11046  * *div is then set to this single integer division and
11047  * *ineq is set to the index of constraint i >= l.
11048  *
11049  * Return bmap->n_eq if there is no such equality.
11050  * Return -1 on error.
11051  */
isl_basic_map_output_defining_equality(__isl_keep isl_basic_map * bmap,int pos,int * div,int * ineq)11052 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11053 	int pos, int *div, int *ineq)
11054 {
11055 	int j, k, l;
11056 	unsigned n_out, o_out;
11057 	unsigned n_div, o_div;
11058 
11059 	if (!bmap)
11060 		return -1;
11061 
11062 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11063 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11064 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11065 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11066 
11067 	if (ineq)
11068 		*ineq = bmap->n_ineq;
11069 	if (div)
11070 		*div = n_div;
11071 	for (j = 0; j < bmap->n_eq; ++j) {
11072 		if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11073 			continue;
11074 		if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11075 					n_out - (pos + 1)) != -1)
11076 			continue;
11077 		k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11078 						0, n_div);
11079 		if (k >= n_div)
11080 			return j;
11081 		if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11082 		    !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11083 			continue;
11084 		if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11085 						k + 1, n_div - (k+1)) < n_div)
11086 			continue;
11087 		l = find_modulo_constraint_pair(bmap, pos,
11088 						bmap->eq[j][o_div + k]);
11089 		if (l < 0)
11090 			return -1;
11091 		if (l >= bmap->n_ineq)
11092 			continue;
11093 		if (div)
11094 			*div = k;
11095 		if (ineq)
11096 			*ineq = l;
11097 		return j;
11098 	}
11099 
11100 	return bmap->n_eq;
11101 }
11102 
11103 /* Check if the given basic map is obviously single-valued.
11104  * In particular, for each output dimension, check that there is
11105  * an equality that defines the output dimension in terms of
11106  * earlier dimensions.
11107  */
isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map * bmap)11108 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11109 {
11110 	int i;
11111 	unsigned n_out;
11112 
11113 	if (!bmap)
11114 		return isl_bool_error;
11115 
11116 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11117 
11118 	for (i = 0; i < n_out; ++i) {
11119 		int eq;
11120 
11121 		eq = isl_basic_map_output_defining_equality(bmap, i,
11122 							    NULL, NULL);
11123 		if (eq < 0)
11124 			return isl_bool_error;
11125 		if (eq >= bmap->n_eq)
11126 			return isl_bool_false;
11127 	}
11128 
11129 	return isl_bool_true;
11130 }
11131 
11132 /* Check if the given basic map is single-valued.
11133  * We simply compute
11134  *
11135  *	M \circ M^-1
11136  *
11137  * and check if the result is a subset of the identity mapping.
11138  */
isl_basic_map_is_single_valued(__isl_keep isl_basic_map * bmap)11139 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11140 {
11141 	isl_space *space;
11142 	isl_basic_map *test;
11143 	isl_basic_map *id;
11144 	isl_bool sv;
11145 
11146 	sv = isl_basic_map_plain_is_single_valued(bmap);
11147 	if (sv < 0 || sv)
11148 		return sv;
11149 
11150 	test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11151 	test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11152 
11153 	space = isl_basic_map_get_space(bmap);
11154 	space = isl_space_map_from_set(isl_space_range(space));
11155 	id = isl_basic_map_identity(space);
11156 
11157 	sv = isl_basic_map_is_subset(test, id);
11158 
11159 	isl_basic_map_free(test);
11160 	isl_basic_map_free(id);
11161 
11162 	return sv;
11163 }
11164 
11165 /* Check if the given map is obviously single-valued.
11166  */
isl_map_plain_is_single_valued(__isl_keep isl_map * map)11167 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11168 {
11169 	if (!map)
11170 		return isl_bool_error;
11171 	if (map->n == 0)
11172 		return isl_bool_true;
11173 	if (map->n >= 2)
11174 		return isl_bool_false;
11175 
11176 	return isl_basic_map_plain_is_single_valued(map->p[0]);
11177 }
11178 
11179 /* Check if the given map is single-valued.
11180  * We simply compute
11181  *
11182  *	M \circ M^-1
11183  *
11184  * and check if the result is a subset of the identity mapping.
11185  */
isl_map_is_single_valued(__isl_keep isl_map * map)11186 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11187 {
11188 	isl_space *dim;
11189 	isl_map *test;
11190 	isl_map *id;
11191 	isl_bool sv;
11192 
11193 	sv = isl_map_plain_is_single_valued(map);
11194 	if (sv < 0 || sv)
11195 		return sv;
11196 
11197 	test = isl_map_reverse(isl_map_copy(map));
11198 	test = isl_map_apply_range(test, isl_map_copy(map));
11199 
11200 	dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11201 	id = isl_map_identity(dim);
11202 
11203 	sv = isl_map_is_subset(test, id);
11204 
11205 	isl_map_free(test);
11206 	isl_map_free(id);
11207 
11208 	return sv;
11209 }
11210 
isl_map_is_injective(__isl_keep isl_map * map)11211 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11212 {
11213 	isl_bool in;
11214 
11215 	map = isl_map_copy(map);
11216 	map = isl_map_reverse(map);
11217 	in = isl_map_is_single_valued(map);
11218 	isl_map_free(map);
11219 
11220 	return in;
11221 }
11222 
11223 /* Check if the given map is obviously injective.
11224  */
isl_map_plain_is_injective(__isl_keep isl_map * map)11225 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11226 {
11227 	isl_bool in;
11228 
11229 	map = isl_map_copy(map);
11230 	map = isl_map_reverse(map);
11231 	in = isl_map_plain_is_single_valued(map);
11232 	isl_map_free(map);
11233 
11234 	return in;
11235 }
11236 
isl_map_is_bijective(__isl_keep isl_map * map)11237 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11238 {
11239 	isl_bool sv;
11240 
11241 	sv = isl_map_is_single_valued(map);
11242 	if (sv < 0 || !sv)
11243 		return sv;
11244 
11245 	return isl_map_is_injective(map);
11246 }
11247 
isl_set_is_singleton(__isl_keep isl_set * set)11248 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11249 {
11250 	return isl_map_is_single_valued(set_to_map(set));
11251 }
11252 
11253 /* Does "map" only map elements to themselves?
11254  *
11255  * If the domain and range spaces are different, then "map"
11256  * is considered not to be an identity relation, even if it is empty.
11257  * Otherwise, construct the maximal identity relation and
11258  * check whether "map" is a subset of this relation.
11259  */
isl_map_is_identity(__isl_keep isl_map * map)11260 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11261 {
11262 	isl_space *space;
11263 	isl_map *id;
11264 	isl_bool equal, is_identity;
11265 
11266 	space = isl_map_get_space(map);
11267 	equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
11268 	isl_space_free(space);
11269 	if (equal < 0 || !equal)
11270 		return equal;
11271 
11272 	id = isl_map_identity(isl_map_get_space(map));
11273 	is_identity = isl_map_is_subset(map, id);
11274 	isl_map_free(id);
11275 
11276 	return is_identity;
11277 }
11278 
isl_map_is_translation(__isl_keep isl_map * map)11279 int isl_map_is_translation(__isl_keep isl_map *map)
11280 {
11281 	int ok;
11282 	isl_set *delta;
11283 
11284 	delta = isl_map_deltas(isl_map_copy(map));
11285 	ok = isl_set_is_singleton(delta);
11286 	isl_set_free(delta);
11287 
11288 	return ok;
11289 }
11290 
unique(isl_int * p,unsigned pos,unsigned len)11291 static int unique(isl_int *p, unsigned pos, unsigned len)
11292 {
11293 	if (isl_seq_first_non_zero(p, pos) != -1)
11294 		return 0;
11295 	if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11296 		return 0;
11297 	return 1;
11298 }
11299 
isl_basic_set_is_box(__isl_keep isl_basic_set * bset)11300 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11301 {
11302 	int i, j;
11303 	unsigned nvar;
11304 	unsigned ovar;
11305 
11306 	if (!bset)
11307 		return isl_bool_error;
11308 
11309 	if (isl_basic_set_dim(bset, isl_dim_div) != 0)
11310 		return isl_bool_false;
11311 
11312 	nvar = isl_basic_set_dim(bset, isl_dim_set);
11313 	ovar = isl_space_offset(bset->dim, isl_dim_set);
11314 	for (j = 0; j < nvar; ++j) {
11315 		int lower = 0, upper = 0;
11316 		for (i = 0; i < bset->n_eq; ++i) {
11317 			if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11318 				continue;
11319 			if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11320 				return isl_bool_false;
11321 			break;
11322 		}
11323 		if (i < bset->n_eq)
11324 			continue;
11325 		for (i = 0; i < bset->n_ineq; ++i) {
11326 			if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11327 				continue;
11328 			if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11329 				return isl_bool_false;
11330 			if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11331 				lower = 1;
11332 			else
11333 				upper = 1;
11334 		}
11335 		if (!lower || !upper)
11336 			return isl_bool_false;
11337 	}
11338 
11339 	return isl_bool_true;
11340 }
11341 
isl_set_is_box(__isl_keep isl_set * set)11342 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11343 {
11344 	if (!set)
11345 		return isl_bool_error;
11346 	if (set->n != 1)
11347 		return isl_bool_false;
11348 
11349 	return isl_basic_set_is_box(set->p[0]);
11350 }
11351 
isl_basic_set_is_wrapping(__isl_keep isl_basic_set * bset)11352 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11353 {
11354 	if (!bset)
11355 		return isl_bool_error;
11356 
11357 	return isl_space_is_wrapping(bset->dim);
11358 }
11359 
isl_set_is_wrapping(__isl_keep isl_set * set)11360 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11361 {
11362 	if (!set)
11363 		return isl_bool_error;
11364 
11365 	return isl_space_is_wrapping(set->dim);
11366 }
11367 
11368 /* Modify the space of "map" through a call to "change".
11369  * If "can_change" is set (not NULL), then first call it to check
11370  * if the modification is allowed, printing the error message "cannot_change"
11371  * if it is not.
11372  */
isl_map_change_space(__isl_take isl_map * map,isl_bool (* can_change)(__isl_keep isl_map * map),const char * cannot_change,__isl_give isl_space * (* change)(__isl_take isl_space * space))11373 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11374 	isl_bool (*can_change)(__isl_keep isl_map *map),
11375 	const char *cannot_change,
11376 	__isl_give isl_space *(*change)(__isl_take isl_space *space))
11377 {
11378 	isl_bool ok;
11379 	isl_space *space;
11380 
11381 	if (!map)
11382 		return NULL;
11383 
11384 	ok = can_change ? can_change(map) : isl_bool_true;
11385 	if (ok < 0)
11386 		return isl_map_free(map);
11387 	if (!ok)
11388 		isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11389 			return isl_map_free(map));
11390 
11391 	space = change(isl_map_get_space(map));
11392 	map = isl_map_reset_space(map, space);
11393 
11394 	return map;
11395 }
11396 
11397 /* Is the domain of "map" a wrapped relation?
11398  */
isl_map_domain_is_wrapping(__isl_keep isl_map * map)11399 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11400 {
11401 	if (!map)
11402 		return isl_bool_error;
11403 
11404 	return isl_space_domain_is_wrapping(map->dim);
11405 }
11406 
11407 /* Does "map" have a wrapped relation in both domain and range?
11408  */
isl_map_is_product(__isl_keep isl_map * map)11409 isl_bool isl_map_is_product(__isl_keep isl_map *map)
11410 {
11411 	return isl_space_is_product(isl_map_peek_space(map));
11412 }
11413 
11414 /* Is the range of "map" a wrapped relation?
11415  */
isl_map_range_is_wrapping(__isl_keep isl_map * map)11416 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
11417 {
11418 	if (!map)
11419 		return isl_bool_error;
11420 
11421 	return isl_space_range_is_wrapping(map->dim);
11422 }
11423 
isl_basic_map_wrap(__isl_take isl_basic_map * bmap)11424 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
11425 {
11426 	bmap = isl_basic_map_cow(bmap);
11427 	if (!bmap)
11428 		return NULL;
11429 
11430 	bmap->dim = isl_space_wrap(bmap->dim);
11431 	if (!bmap->dim)
11432 		goto error;
11433 
11434 	bmap = isl_basic_map_finalize(bmap);
11435 
11436 	return bset_from_bmap(bmap);
11437 error:
11438 	isl_basic_map_free(bmap);
11439 	return NULL;
11440 }
11441 
11442 /* Given a map A -> B, return the set (A -> B).
11443  */
isl_map_wrap(__isl_take isl_map * map)11444 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
11445 {
11446 	return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
11447 }
11448 
isl_basic_set_unwrap(__isl_take isl_basic_set * bset)11449 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
11450 {
11451 	bset = isl_basic_set_cow(bset);
11452 	if (!bset)
11453 		return NULL;
11454 
11455 	bset->dim = isl_space_unwrap(bset->dim);
11456 	if (!bset->dim)
11457 		goto error;
11458 
11459 	bset = isl_basic_set_finalize(bset);
11460 
11461 	return bset_to_bmap(bset);
11462 error:
11463 	isl_basic_set_free(bset);
11464 	return NULL;
11465 }
11466 
11467 /* Given a set (A -> B), return the map A -> B.
11468  * Error out if "set" is not of the form (A -> B).
11469  */
isl_set_unwrap(__isl_take isl_set * set)11470 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
11471 {
11472 	return isl_map_change_space(set, &isl_set_is_wrapping,
11473 				    "not a wrapping set", &isl_space_unwrap);
11474 }
11475 
isl_basic_map_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)11476 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
11477 	enum isl_dim_type type)
11478 {
11479 	if (!bmap)
11480 		return NULL;
11481 
11482 	if (!isl_space_is_named_or_nested(bmap->dim, type))
11483 		return bmap;
11484 
11485 	bmap = isl_basic_map_cow(bmap);
11486 	if (!bmap)
11487 		return NULL;
11488 
11489 	bmap->dim = isl_space_reset(bmap->dim, type);
11490 	if (!bmap->dim)
11491 		goto error;
11492 
11493 	bmap = isl_basic_map_finalize(bmap);
11494 
11495 	return bmap;
11496 error:
11497 	isl_basic_map_free(bmap);
11498 	return NULL;
11499 }
11500 
isl_map_reset(__isl_take isl_map * map,enum isl_dim_type type)11501 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
11502 	enum isl_dim_type type)
11503 {
11504 	int i;
11505 
11506 	if (!map)
11507 		return NULL;
11508 
11509 	if (!isl_space_is_named_or_nested(map->dim, type))
11510 		return map;
11511 
11512 	map = isl_map_cow(map);
11513 	if (!map)
11514 		return NULL;
11515 
11516 	for (i = 0; i < map->n; ++i) {
11517 		map->p[i] = isl_basic_map_reset(map->p[i], type);
11518 		if (!map->p[i])
11519 			goto error;
11520 	}
11521 	map->dim = isl_space_reset(map->dim, type);
11522 	if (!map->dim)
11523 		goto error;
11524 
11525 	return map;
11526 error:
11527 	isl_map_free(map);
11528 	return NULL;
11529 }
11530 
isl_basic_map_flatten(__isl_take isl_basic_map * bmap)11531 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11532 {
11533 	if (!bmap)
11534 		return NULL;
11535 
11536 	if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11537 		return bmap;
11538 
11539 	bmap = isl_basic_map_cow(bmap);
11540 	if (!bmap)
11541 		return NULL;
11542 
11543 	bmap->dim = isl_space_flatten(bmap->dim);
11544 	if (!bmap->dim)
11545 		goto error;
11546 
11547 	bmap = isl_basic_map_finalize(bmap);
11548 
11549 	return bmap;
11550 error:
11551 	isl_basic_map_free(bmap);
11552 	return NULL;
11553 }
11554 
isl_basic_set_flatten(__isl_take isl_basic_set * bset)11555 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11556 {
11557 	return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11558 }
11559 
isl_basic_map_flatten_domain(__isl_take isl_basic_map * bmap)11560 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11561 	__isl_take isl_basic_map *bmap)
11562 {
11563 	if (!bmap)
11564 		return NULL;
11565 
11566 	if (!bmap->dim->nested[0])
11567 		return bmap;
11568 
11569 	bmap = isl_basic_map_cow(bmap);
11570 	if (!bmap)
11571 		return NULL;
11572 
11573 	bmap->dim = isl_space_flatten_domain(bmap->dim);
11574 	if (!bmap->dim)
11575 		goto error;
11576 
11577 	bmap = isl_basic_map_finalize(bmap);
11578 
11579 	return bmap;
11580 error:
11581 	isl_basic_map_free(bmap);
11582 	return NULL;
11583 }
11584 
isl_basic_map_flatten_range(__isl_take isl_basic_map * bmap)11585 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11586 	__isl_take isl_basic_map *bmap)
11587 {
11588 	if (!bmap)
11589 		return NULL;
11590 
11591 	if (!bmap->dim->nested[1])
11592 		return bmap;
11593 
11594 	bmap = isl_basic_map_cow(bmap);
11595 	if (!bmap)
11596 		return NULL;
11597 
11598 	bmap->dim = isl_space_flatten_range(bmap->dim);
11599 	if (!bmap->dim)
11600 		goto error;
11601 
11602 	bmap = isl_basic_map_finalize(bmap);
11603 
11604 	return bmap;
11605 error:
11606 	isl_basic_map_free(bmap);
11607 	return NULL;
11608 }
11609 
11610 /* Remove any internal structure from the spaces of domain and range of "map".
11611  */
isl_map_flatten(__isl_take isl_map * map)11612 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11613 {
11614 	if (!map)
11615 		return NULL;
11616 
11617 	if (!map->dim->nested[0] && !map->dim->nested[1])
11618 		return map;
11619 
11620 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11621 }
11622 
isl_set_flatten(__isl_take isl_set * set)11623 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11624 {
11625 	return set_from_map(isl_map_flatten(set_to_map(set)));
11626 }
11627 
isl_set_flatten_map(__isl_take isl_set * set)11628 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11629 {
11630 	isl_space *dim, *flat_dim;
11631 	isl_map *map;
11632 
11633 	dim = isl_set_get_space(set);
11634 	flat_dim = isl_space_flatten(isl_space_copy(dim));
11635 	map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
11636 	map = isl_map_intersect_domain(map, set);
11637 
11638 	return map;
11639 }
11640 
11641 /* Remove any internal structure from the space of the domain of "map".
11642  */
isl_map_flatten_domain(__isl_take isl_map * map)11643 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11644 {
11645 	if (!map)
11646 		return NULL;
11647 
11648 	if (!map->dim->nested[0])
11649 		return map;
11650 
11651 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11652 }
11653 
11654 /* Remove any internal structure from the space of the range of "map".
11655  */
isl_map_flatten_range(__isl_take isl_map * map)11656 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11657 {
11658 	if (!map)
11659 		return NULL;
11660 
11661 	if (!map->dim->nested[1])
11662 		return map;
11663 
11664 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11665 }
11666 
11667 /* Reorder the dimensions of "bmap" according to the given dim_map
11668  * and set the dimension specification to "space" and
11669  * perform Gaussian elimination on the result.
11670  */
isl_basic_map_realign(__isl_take isl_basic_map * bmap,__isl_take isl_space * space,__isl_take struct isl_dim_map * dim_map)11671 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11672 	__isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
11673 {
11674 	isl_basic_map *res;
11675 	unsigned flags;
11676 	unsigned n_div;
11677 
11678 	if (!bmap || !space || !dim_map)
11679 		goto error;
11680 
11681 	flags = bmap->flags;
11682 	ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11683 	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
11684 	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11685 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11686 	res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
11687 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11688 	if (res)
11689 		res->flags = flags;
11690 	res = isl_basic_map_gauss(res, NULL);
11691 	res = isl_basic_map_finalize(res);
11692 	return res;
11693 error:
11694 	free(dim_map);
11695 	isl_basic_map_free(bmap);
11696 	isl_space_free(space);
11697 	return NULL;
11698 }
11699 
11700 /* Reorder the dimensions of "map" according to given reordering.
11701  */
isl_map_realign(__isl_take isl_map * map,__isl_take isl_reordering * r)11702 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11703 	__isl_take isl_reordering *r)
11704 {
11705 	int i;
11706 	struct isl_dim_map *dim_map;
11707 
11708 	map = isl_map_cow(map);
11709 	dim_map = isl_dim_map_from_reordering(r);
11710 	if (!map || !r || !dim_map)
11711 		goto error;
11712 
11713 	for (i = 0; i < map->n; ++i) {
11714 		struct isl_dim_map *dim_map_i;
11715 		isl_space *space;
11716 
11717 		dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11718 
11719 		space = isl_reordering_get_space(r);
11720 		map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
11721 
11722 		if (!map->p[i])
11723 			goto error;
11724 	}
11725 
11726 	map = isl_map_reset_space(map, isl_reordering_get_space(r));
11727 	map = isl_map_unmark_normalized(map);
11728 
11729 	isl_reordering_free(r);
11730 	free(dim_map);
11731 	return map;
11732 error:
11733 	free(dim_map);
11734 	isl_map_free(map);
11735 	isl_reordering_free(r);
11736 	return NULL;
11737 }
11738 
isl_set_realign(__isl_take isl_set * set,__isl_take isl_reordering * r)11739 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11740 	__isl_take isl_reordering *r)
11741 {
11742 	return set_from_map(isl_map_realign(set_to_map(set), r));
11743 }
11744 
isl_map_align_params(__isl_take isl_map * map,__isl_take isl_space * model)11745 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11746 	__isl_take isl_space *model)
11747 {
11748 	isl_ctx *ctx;
11749 	isl_bool aligned;
11750 
11751 	if (!map || !model)
11752 		goto error;
11753 
11754 	ctx = isl_space_get_ctx(model);
11755 	if (!isl_space_has_named_params(model))
11756 		isl_die(ctx, isl_error_invalid,
11757 			"model has unnamed parameters", goto error);
11758 	if (isl_map_check_named_params(map) < 0)
11759 		goto error;
11760 	aligned = isl_map_space_has_equal_params(map, model);
11761 	if (aligned < 0)
11762 		goto error;
11763 	if (!aligned) {
11764 		isl_reordering *exp;
11765 
11766 		exp = isl_parameter_alignment_reordering(map->dim, model);
11767 		exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11768 		map = isl_map_realign(map, exp);
11769 	}
11770 
11771 	isl_space_free(model);
11772 	return map;
11773 error:
11774 	isl_space_free(model);
11775 	isl_map_free(map);
11776 	return NULL;
11777 }
11778 
isl_set_align_params(__isl_take isl_set * set,__isl_take isl_space * model)11779 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11780 	__isl_take isl_space *model)
11781 {
11782 	return isl_map_align_params(set, model);
11783 }
11784 
11785 /* Align the parameters of "bmap" to those of "model", introducing
11786  * additional parameters if needed.
11787  */
isl_basic_map_align_params(__isl_take isl_basic_map * bmap,__isl_take isl_space * model)11788 __isl_give isl_basic_map *isl_basic_map_align_params(
11789 	__isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11790 {
11791 	isl_ctx *ctx;
11792 	isl_bool equal_params;
11793 
11794 	if (!bmap || !model)
11795 		goto error;
11796 
11797 	ctx = isl_space_get_ctx(model);
11798 	if (!isl_space_has_named_params(model))
11799 		isl_die(ctx, isl_error_invalid,
11800 			"model has unnamed parameters", goto error);
11801 	if (isl_basic_map_check_named_params(bmap) < 0)
11802 		goto error;
11803 	equal_params = isl_space_has_equal_params(bmap->dim, model);
11804 	if (equal_params < 0)
11805 		goto error;
11806 	if (!equal_params) {
11807 		isl_reordering *exp;
11808 		struct isl_dim_map *dim_map;
11809 
11810 		exp = isl_parameter_alignment_reordering(bmap->dim, model);
11811 		exp = isl_reordering_extend_space(exp,
11812 					isl_basic_map_get_space(bmap));
11813 		dim_map = isl_dim_map_from_reordering(exp);
11814 		bmap = isl_basic_map_realign(bmap,
11815 				    isl_reordering_get_space(exp),
11816 				    isl_dim_map_extend(dim_map, bmap));
11817 		isl_reordering_free(exp);
11818 		free(dim_map);
11819 	}
11820 
11821 	isl_space_free(model);
11822 	return bmap;
11823 error:
11824 	isl_space_free(model);
11825 	isl_basic_map_free(bmap);
11826 	return NULL;
11827 }
11828 
11829 /* Do "bset" and "space" have the same parameters?
11830  */
isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set * bset,__isl_keep isl_space * space)11831 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
11832 	__isl_keep isl_space *space)
11833 {
11834 	isl_space *bset_space;
11835 
11836 	bset_space = isl_basic_set_peek_space(bset);
11837 	return isl_space_has_equal_params(bset_space, space);
11838 }
11839 
11840 /* Do "map" and "space" have the same parameters?
11841  */
isl_map_space_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_space * space)11842 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
11843 	__isl_keep isl_space *space)
11844 {
11845 	isl_space *map_space;
11846 
11847 	map_space = isl_map_peek_space(map);
11848 	return isl_space_has_equal_params(map_space, space);
11849 }
11850 
11851 /* Do "set" and "space" have the same parameters?
11852  */
isl_set_space_has_equal_params(__isl_keep isl_set * set,__isl_keep isl_space * space)11853 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
11854 	__isl_keep isl_space *space)
11855 {
11856 	return isl_map_space_has_equal_params(set_to_map(set), space);
11857 }
11858 
11859 /* Align the parameters of "bset" to those of "model", introducing
11860  * additional parameters if needed.
11861  */
isl_basic_set_align_params(__isl_take isl_basic_set * bset,__isl_take isl_space * model)11862 __isl_give isl_basic_set *isl_basic_set_align_params(
11863 	__isl_take isl_basic_set *bset, __isl_take isl_space *model)
11864 {
11865 	return isl_basic_map_align_params(bset, model);
11866 }
11867 
11868 /* Drop all parameters not referenced by "map".
11869  */
isl_map_drop_unused_params(__isl_take isl_map * map)11870 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
11871 {
11872 	int i;
11873 
11874 	if (isl_map_check_named_params(map) < 0)
11875 		return isl_map_free(map);
11876 
11877 	for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
11878 		isl_bool involves;
11879 
11880 		involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
11881 		if (involves < 0)
11882 			return isl_map_free(map);
11883 		if (!involves)
11884 			map = isl_map_project_out(map, isl_dim_param, i, 1);
11885 	}
11886 
11887 	return map;
11888 }
11889 
11890 /* Drop all parameters not referenced by "set".
11891  */
isl_set_drop_unused_params(__isl_take isl_set * set)11892 __isl_give isl_set *isl_set_drop_unused_params(
11893 	__isl_take isl_set *set)
11894 {
11895 	return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
11896 }
11897 
11898 /* Drop all parameters not referenced by "bmap".
11899  */
isl_basic_map_drop_unused_params(__isl_take isl_basic_map * bmap)11900 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
11901 	__isl_take isl_basic_map *bmap)
11902 {
11903 	int i;
11904 
11905 	if (isl_basic_map_check_named_params(bmap) < 0)
11906 		return isl_basic_map_free(bmap);
11907 
11908 	for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
11909 		isl_bool involves;
11910 
11911 		involves = isl_basic_map_involves_dims(bmap,
11912 							isl_dim_param, i, 1);
11913 		if (involves < 0)
11914 			return isl_basic_map_free(bmap);
11915 		if (!involves)
11916 			bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
11917 	}
11918 
11919 	return bmap;
11920 }
11921 
11922 /* Drop all parameters not referenced by "bset".
11923  */
isl_basic_set_drop_unused_params(__isl_take isl_basic_set * bset)11924 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
11925 	__isl_take isl_basic_set *bset)
11926 {
11927 	return bset_from_bmap(isl_basic_map_drop_unused_params(
11928 							bset_to_bmap(bset)));
11929 }
11930 
isl_basic_map_equalities_matrix(__isl_keep isl_basic_map * bmap,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4,enum isl_dim_type c5)11931 __isl_give isl_mat *isl_basic_map_equalities_matrix(
11932 		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11933 		enum isl_dim_type c2, enum isl_dim_type c3,
11934 		enum isl_dim_type c4, enum isl_dim_type c5)
11935 {
11936 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11937 	struct isl_mat *mat;
11938 	int i, j, k;
11939 	int pos;
11940 
11941 	if (!bmap)
11942 		return NULL;
11943 	mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11944 				isl_basic_map_total_dim(bmap) + 1);
11945 	if (!mat)
11946 		return NULL;
11947 	for (i = 0; i < bmap->n_eq; ++i)
11948 		for (j = 0, pos = 0; j < 5; ++j) {
11949 			int off = isl_basic_map_offset(bmap, c[j]);
11950 			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11951 				isl_int_set(mat->row[i][pos],
11952 					    bmap->eq[i][off + k]);
11953 				++pos;
11954 			}
11955 		}
11956 
11957 	return mat;
11958 }
11959 
isl_basic_map_inequalities_matrix(__isl_keep isl_basic_map * bmap,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4,enum isl_dim_type c5)11960 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11961 		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11962 		enum isl_dim_type c2, enum isl_dim_type c3,
11963 		enum isl_dim_type c4, enum isl_dim_type c5)
11964 {
11965 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11966 	struct isl_mat *mat;
11967 	int i, j, k;
11968 	int pos;
11969 
11970 	if (!bmap)
11971 		return NULL;
11972 	mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11973 				isl_basic_map_total_dim(bmap) + 1);
11974 	if (!mat)
11975 		return NULL;
11976 	for (i = 0; i < bmap->n_ineq; ++i)
11977 		for (j = 0, pos = 0; j < 5; ++j) {
11978 			int off = isl_basic_map_offset(bmap, c[j]);
11979 			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11980 				isl_int_set(mat->row[i][pos],
11981 					    bmap->ineq[i][off + k]);
11982 				++pos;
11983 			}
11984 		}
11985 
11986 	return mat;
11987 }
11988 
isl_basic_map_from_constraint_matrices(__isl_take isl_space * dim,__isl_take isl_mat * eq,__isl_take isl_mat * ineq,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4,enum isl_dim_type c5)11989 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11990 	__isl_take isl_space *dim,
11991 	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11992 	enum isl_dim_type c2, enum isl_dim_type c3,
11993 	enum isl_dim_type c4, enum isl_dim_type c5)
11994 {
11995 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11996 	isl_basic_map *bmap;
11997 	unsigned total;
11998 	unsigned extra;
11999 	int i, j, k, l;
12000 	int pos;
12001 
12002 	if (!dim || !eq || !ineq)
12003 		goto error;
12004 
12005 	if (eq->n_col != ineq->n_col)
12006 		isl_die(dim->ctx, isl_error_invalid,
12007 			"equalities and inequalities matrices should have "
12008 			"same number of columns", goto error);
12009 
12010 	total = 1 + isl_space_dim(dim, isl_dim_all);
12011 
12012 	if (eq->n_col < total)
12013 		isl_die(dim->ctx, isl_error_invalid,
12014 			"number of columns too small", goto error);
12015 
12016 	extra = eq->n_col - total;
12017 
12018 	bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
12019 				       eq->n_row, ineq->n_row);
12020 	if (!bmap)
12021 		goto error;
12022 	for (i = 0; i < extra; ++i) {
12023 		k = isl_basic_map_alloc_div(bmap);
12024 		if (k < 0)
12025 			goto error;
12026 		isl_int_set_si(bmap->div[k][0], 0);
12027 	}
12028 	for (i = 0; i < eq->n_row; ++i) {
12029 		l = isl_basic_map_alloc_equality(bmap);
12030 		if (l < 0)
12031 			goto error;
12032 		for (j = 0, pos = 0; j < 5; ++j) {
12033 			int off = isl_basic_map_offset(bmap, c[j]);
12034 			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
12035 				isl_int_set(bmap->eq[l][off + k],
12036 					    eq->row[i][pos]);
12037 				++pos;
12038 			}
12039 		}
12040 	}
12041 	for (i = 0; i < ineq->n_row; ++i) {
12042 		l = isl_basic_map_alloc_inequality(bmap);
12043 		if (l < 0)
12044 			goto error;
12045 		for (j = 0, pos = 0; j < 5; ++j) {
12046 			int off = isl_basic_map_offset(bmap, c[j]);
12047 			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
12048 				isl_int_set(bmap->ineq[l][off + k],
12049 					    ineq->row[i][pos]);
12050 				++pos;
12051 			}
12052 		}
12053 	}
12054 
12055 	isl_space_free(dim);
12056 	isl_mat_free(eq);
12057 	isl_mat_free(ineq);
12058 
12059 	bmap = isl_basic_map_simplify(bmap);
12060 	return isl_basic_map_finalize(bmap);
12061 error:
12062 	isl_space_free(dim);
12063 	isl_mat_free(eq);
12064 	isl_mat_free(ineq);
12065 	return NULL;
12066 }
12067 
isl_basic_set_equalities_matrix(__isl_keep isl_basic_set * bset,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4)12068 __isl_give isl_mat *isl_basic_set_equalities_matrix(
12069 	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12070 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12071 {
12072 	return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12073 						c1, c2, c3, c4, isl_dim_in);
12074 }
12075 
isl_basic_set_inequalities_matrix(__isl_keep isl_basic_set * bset,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4)12076 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12077 	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12078 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12079 {
12080 	return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12081 						 c1, c2, c3, c4, isl_dim_in);
12082 }
12083 
isl_basic_set_from_constraint_matrices(__isl_take isl_space * dim,__isl_take isl_mat * eq,__isl_take isl_mat * ineq,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4)12084 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12085 	__isl_take isl_space *dim,
12086 	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12087 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12088 {
12089 	isl_basic_map *bmap;
12090 	bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
12091 						   c1, c2, c3, c4, isl_dim_in);
12092 	return bset_from_bmap(bmap);
12093 }
12094 
isl_basic_map_can_zip(__isl_keep isl_basic_map * bmap)12095 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12096 {
12097 	if (!bmap)
12098 		return isl_bool_error;
12099 
12100 	return isl_space_can_zip(bmap->dim);
12101 }
12102 
isl_map_can_zip(__isl_keep isl_map * map)12103 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12104 {
12105 	if (!map)
12106 		return isl_bool_error;
12107 
12108 	return isl_space_can_zip(map->dim);
12109 }
12110 
12111 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12112  * (A -> C) -> (B -> D).
12113  */
isl_basic_map_zip(__isl_take isl_basic_map * bmap)12114 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12115 {
12116 	unsigned pos;
12117 	unsigned n1;
12118 	unsigned n2;
12119 
12120 	if (!bmap)
12121 		return NULL;
12122 
12123 	if (!isl_basic_map_can_zip(bmap))
12124 		isl_die(bmap->ctx, isl_error_invalid,
12125 			"basic map cannot be zipped", goto error);
12126 	pos = isl_basic_map_offset(bmap, isl_dim_in) +
12127 		isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12128 	n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12129 	n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12130 	bmap = isl_basic_map_cow(bmap);
12131 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12132 	if (!bmap)
12133 		return NULL;
12134 	bmap->dim = isl_space_zip(bmap->dim);
12135 	if (!bmap->dim)
12136 		goto error;
12137 	bmap = isl_basic_map_mark_final(bmap);
12138 	return bmap;
12139 error:
12140 	isl_basic_map_free(bmap);
12141 	return NULL;
12142 }
12143 
12144 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12145  * (A -> C) -> (B -> D).
12146  */
isl_map_zip(__isl_take isl_map * map)12147 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12148 {
12149 	int i;
12150 
12151 	if (!map)
12152 		return NULL;
12153 
12154 	if (!isl_map_can_zip(map))
12155 		isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12156 			goto error);
12157 
12158 	map = isl_map_cow(map);
12159 	if (!map)
12160 		return NULL;
12161 
12162 	for (i = 0; i < map->n; ++i) {
12163 		map->p[i] = isl_basic_map_zip(map->p[i]);
12164 		if (!map->p[i])
12165 			goto error;
12166 	}
12167 
12168 	map->dim = isl_space_zip(map->dim);
12169 	if (!map->dim)
12170 		goto error;
12171 
12172 	return map;
12173 error:
12174 	isl_map_free(map);
12175 	return NULL;
12176 }
12177 
12178 /* Can we apply isl_basic_map_curry to "bmap"?
12179  * That is, does it have a nested relation in its domain?
12180  */
isl_basic_map_can_curry(__isl_keep isl_basic_map * bmap)12181 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12182 {
12183 	if (!bmap)
12184 		return isl_bool_error;
12185 
12186 	return isl_space_can_curry(bmap->dim);
12187 }
12188 
12189 /* Can we apply isl_map_curry to "map"?
12190  * That is, does it have a nested relation in its domain?
12191  */
isl_map_can_curry(__isl_keep isl_map * map)12192 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12193 {
12194 	if (!map)
12195 		return isl_bool_error;
12196 
12197 	return isl_space_can_curry(map->dim);
12198 }
12199 
12200 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12201  * A -> (B -> C).
12202  */
isl_basic_map_curry(__isl_take isl_basic_map * bmap)12203 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12204 {
12205 
12206 	if (!bmap)
12207 		return NULL;
12208 
12209 	if (!isl_basic_map_can_curry(bmap))
12210 		isl_die(bmap->ctx, isl_error_invalid,
12211 			"basic map cannot be curried", goto error);
12212 	bmap = isl_basic_map_cow(bmap);
12213 	if (!bmap)
12214 		return NULL;
12215 	bmap->dim = isl_space_curry(bmap->dim);
12216 	if (!bmap->dim)
12217 		goto error;
12218 	bmap = isl_basic_map_mark_final(bmap);
12219 	return bmap;
12220 error:
12221 	isl_basic_map_free(bmap);
12222 	return NULL;
12223 }
12224 
12225 /* Given a map (A -> B) -> C, return the corresponding map
12226  * A -> (B -> C).
12227  */
isl_map_curry(__isl_take isl_map * map)12228 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
12229 {
12230 	return isl_map_change_space(map, &isl_map_can_curry,
12231 				    "map cannot be curried", &isl_space_curry);
12232 }
12233 
12234 /* Can isl_map_range_curry be applied to "map"?
12235  * That is, does it have a nested relation in its range,
12236  * the domain of which is itself a nested relation?
12237  */
isl_map_can_range_curry(__isl_keep isl_map * map)12238 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
12239 {
12240 	if (!map)
12241 		return isl_bool_error;
12242 
12243 	return isl_space_can_range_curry(map->dim);
12244 }
12245 
12246 /* Given a map A -> ((B -> C) -> D), return the corresponding map
12247  * A -> (B -> (C -> D)).
12248  */
isl_map_range_curry(__isl_take isl_map * map)12249 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
12250 {
12251 	return isl_map_change_space(map, &isl_map_can_range_curry,
12252 				    "map range cannot be curried",
12253 				    &isl_space_range_curry);
12254 }
12255 
12256 /* Can we apply isl_basic_map_uncurry to "bmap"?
12257  * That is, does it have a nested relation in its domain?
12258  */
isl_basic_map_can_uncurry(__isl_keep isl_basic_map * bmap)12259 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
12260 {
12261 	if (!bmap)
12262 		return isl_bool_error;
12263 
12264 	return isl_space_can_uncurry(bmap->dim);
12265 }
12266 
12267 /* Can we apply isl_map_uncurry to "map"?
12268  * That is, does it have a nested relation in its domain?
12269  */
isl_map_can_uncurry(__isl_keep isl_map * map)12270 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
12271 {
12272 	if (!map)
12273 		return isl_bool_error;
12274 
12275 	return isl_space_can_uncurry(map->dim);
12276 }
12277 
12278 /* Given a basic map A -> (B -> C), return the corresponding basic map
12279  * (A -> B) -> C.
12280  */
isl_basic_map_uncurry(__isl_take isl_basic_map * bmap)12281 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
12282 {
12283 
12284 	if (!bmap)
12285 		return NULL;
12286 
12287 	if (!isl_basic_map_can_uncurry(bmap))
12288 		isl_die(bmap->ctx, isl_error_invalid,
12289 			"basic map cannot be uncurried",
12290 			return isl_basic_map_free(bmap));
12291 	bmap = isl_basic_map_cow(bmap);
12292 	if (!bmap)
12293 		return NULL;
12294 	bmap->dim = isl_space_uncurry(bmap->dim);
12295 	if (!bmap->dim)
12296 		return isl_basic_map_free(bmap);
12297 	bmap = isl_basic_map_mark_final(bmap);
12298 	return bmap;
12299 }
12300 
12301 /* Given a map A -> (B -> C), return the corresponding map
12302  * (A -> B) -> C.
12303  */
isl_map_uncurry(__isl_take isl_map * map)12304 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
12305 {
12306 	return isl_map_change_space(map, &isl_map_can_uncurry,
12307 				"map cannot be uncurried", &isl_space_uncurry);
12308 }
12309 
isl_set_equate(__isl_take isl_set * set,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12310 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
12311 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12312 {
12313 	return isl_map_equate(set, type1, pos1, type2, pos2);
12314 }
12315 
12316 /* Construct a basic map where the given dimensions are equal to each other.
12317  */
equator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12318 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
12319 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12320 {
12321 	isl_basic_map *bmap = NULL;
12322 	int i;
12323 
12324 	if (!space)
12325 		return NULL;
12326 
12327 	if (pos1 >= isl_space_dim(space, type1))
12328 		isl_die(isl_space_get_ctx(space), isl_error_invalid,
12329 			"index out of bounds", goto error);
12330 	if (pos2 >= isl_space_dim(space, type2))
12331 		isl_die(isl_space_get_ctx(space), isl_error_invalid,
12332 			"index out of bounds", goto error);
12333 
12334 	if (type1 == type2 && pos1 == pos2)
12335 		return isl_basic_map_universe(space);
12336 
12337 	bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
12338 	i = isl_basic_map_alloc_equality(bmap);
12339 	if (i < 0)
12340 		goto error;
12341 	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12342 	pos1 += isl_basic_map_offset(bmap, type1);
12343 	pos2 += isl_basic_map_offset(bmap, type2);
12344 	isl_int_set_si(bmap->eq[i][pos1], -1);
12345 	isl_int_set_si(bmap->eq[i][pos2], 1);
12346 	bmap = isl_basic_map_finalize(bmap);
12347 	isl_space_free(space);
12348 	return bmap;
12349 error:
12350 	isl_space_free(space);
12351 	isl_basic_map_free(bmap);
12352 	return NULL;
12353 }
12354 
12355 /* Add a constraint imposing that the given two dimensions are equal.
12356  */
isl_basic_map_equate(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12357 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
12358 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12359 {
12360 	isl_basic_map *eq;
12361 
12362 	eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12363 
12364 	bmap = isl_basic_map_intersect(bmap, eq);
12365 
12366 	return bmap;
12367 }
12368 
12369 /* Add a constraint imposing that the given two dimensions are equal.
12370  */
isl_map_equate(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12371 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
12372 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12373 {
12374 	isl_basic_map *bmap;
12375 
12376 	bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
12377 
12378 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12379 
12380 	return map;
12381 }
12382 
12383 /* Add a constraint imposing that the given two dimensions have opposite values.
12384  */
isl_map_oppose(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12385 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
12386 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12387 {
12388 	isl_basic_map *bmap = NULL;
12389 	int i;
12390 
12391 	if (!map)
12392 		return NULL;
12393 
12394 	if (pos1 >= isl_map_dim(map, type1))
12395 		isl_die(map->ctx, isl_error_invalid,
12396 			"index out of bounds", goto error);
12397 	if (pos2 >= isl_map_dim(map, type2))
12398 		isl_die(map->ctx, isl_error_invalid,
12399 			"index out of bounds", goto error);
12400 
12401 	bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
12402 	i = isl_basic_map_alloc_equality(bmap);
12403 	if (i < 0)
12404 		goto error;
12405 	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12406 	pos1 += isl_basic_map_offset(bmap, type1);
12407 	pos2 += isl_basic_map_offset(bmap, type2);
12408 	isl_int_set_si(bmap->eq[i][pos1], 1);
12409 	isl_int_set_si(bmap->eq[i][pos2], 1);
12410 	bmap = isl_basic_map_finalize(bmap);
12411 
12412 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12413 
12414 	return map;
12415 error:
12416 	isl_basic_map_free(bmap);
12417 	isl_map_free(map);
12418 	return NULL;
12419 }
12420 
12421 /* Construct a constraint imposing that the value of the first dimension is
12422  * greater than or equal to that of the second.
12423  */
constraint_order_ge(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12424 static __isl_give isl_constraint *constraint_order_ge(
12425 	__isl_take isl_space *space, enum isl_dim_type type1, int pos1,
12426 	enum isl_dim_type type2, int pos2)
12427 {
12428 	isl_constraint *c;
12429 
12430 	if (!space)
12431 		return NULL;
12432 
12433 	c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
12434 
12435 	if (pos1 >= isl_constraint_dim(c, type1))
12436 		isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
12437 			"index out of bounds", return isl_constraint_free(c));
12438 	if (pos2 >= isl_constraint_dim(c, type2))
12439 		isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
12440 			"index out of bounds", return isl_constraint_free(c));
12441 
12442 	if (type1 == type2 && pos1 == pos2)
12443 		return c;
12444 
12445 	c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
12446 	c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
12447 
12448 	return c;
12449 }
12450 
12451 /* Add a constraint imposing that the value of the first dimension is
12452  * greater than or equal to that of the second.
12453  */
isl_basic_map_order_ge(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12454 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
12455 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12456 {
12457 	isl_constraint *c;
12458 	isl_space *space;
12459 
12460 	if (type1 == type2 && pos1 == pos2)
12461 		return bmap;
12462 	space = isl_basic_map_get_space(bmap);
12463 	c = constraint_order_ge(space, type1, pos1, type2, pos2);
12464 	bmap = isl_basic_map_add_constraint(bmap, c);
12465 
12466 	return bmap;
12467 }
12468 
12469 /* Add a constraint imposing that the value of the first dimension is
12470  * greater than or equal to that of the second.
12471  */
isl_map_order_ge(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12472 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12473 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12474 {
12475 	isl_constraint *c;
12476 	isl_space *space;
12477 
12478 	if (type1 == type2 && pos1 == pos2)
12479 		return map;
12480 	space = isl_map_get_space(map);
12481 	c = constraint_order_ge(space, type1, pos1, type2, pos2);
12482 	map = isl_map_add_constraint(map, c);
12483 
12484 	return map;
12485 }
12486 
12487 /* Add a constraint imposing that the value of the first dimension is
12488  * less than or equal to that of the second.
12489  */
isl_map_order_le(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12490 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12491 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12492 {
12493 	return isl_map_order_ge(map, type2, pos2, type1, pos1);
12494 }
12495 
12496 /* Construct a basic map where the value of the first dimension is
12497  * greater than that of the second.
12498  */
greator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12499 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12500 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12501 {
12502 	isl_basic_map *bmap = NULL;
12503 	int i;
12504 
12505 	if (!space)
12506 		return NULL;
12507 
12508 	if (pos1 >= isl_space_dim(space, type1))
12509 		isl_die(isl_space_get_ctx(space), isl_error_invalid,
12510 			"index out of bounds", goto error);
12511 	if (pos2 >= isl_space_dim(space, type2))
12512 		isl_die(isl_space_get_ctx(space), isl_error_invalid,
12513 			"index out of bounds", goto error);
12514 
12515 	if (type1 == type2 && pos1 == pos2)
12516 		return isl_basic_map_empty(space);
12517 
12518 	bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12519 	i = isl_basic_map_alloc_inequality(bmap);
12520 	if (i < 0)
12521 		return isl_basic_map_free(bmap);
12522 	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12523 	pos1 += isl_basic_map_offset(bmap, type1);
12524 	pos2 += isl_basic_map_offset(bmap, type2);
12525 	isl_int_set_si(bmap->ineq[i][pos1], 1);
12526 	isl_int_set_si(bmap->ineq[i][pos2], -1);
12527 	isl_int_set_si(bmap->ineq[i][0], -1);
12528 	bmap = isl_basic_map_finalize(bmap);
12529 
12530 	return bmap;
12531 error:
12532 	isl_space_free(space);
12533 	isl_basic_map_free(bmap);
12534 	return NULL;
12535 }
12536 
12537 /* Add a constraint imposing that the value of the first dimension is
12538  * greater than that of the second.
12539  */
isl_basic_map_order_gt(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12540 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12541 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12542 {
12543 	isl_basic_map *gt;
12544 
12545 	gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12546 
12547 	bmap = isl_basic_map_intersect(bmap, gt);
12548 
12549 	return bmap;
12550 }
12551 
12552 /* Add a constraint imposing that the value of the first dimension is
12553  * greater than that of the second.
12554  */
isl_map_order_gt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12555 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12556 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12557 {
12558 	isl_basic_map *bmap;
12559 
12560 	bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12561 
12562 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12563 
12564 	return map;
12565 }
12566 
12567 /* Add a constraint imposing that the value of the first dimension is
12568  * smaller than that of the second.
12569  */
isl_map_order_lt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)12570 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12571 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12572 {
12573 	return isl_map_order_gt(map, type2, pos2, type1, pos1);
12574 }
12575 
isl_basic_map_get_div(__isl_keep isl_basic_map * bmap,int pos)12576 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12577 	int pos)
12578 {
12579 	isl_aff *div;
12580 	isl_local_space *ls;
12581 
12582 	if (!bmap)
12583 		return NULL;
12584 
12585 	if (!isl_basic_map_divs_known(bmap))
12586 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12587 			"some divs are unknown", return NULL);
12588 
12589 	ls = isl_basic_map_get_local_space(bmap);
12590 	div = isl_local_space_get_div(ls, pos);
12591 	isl_local_space_free(ls);
12592 
12593 	return div;
12594 }
12595 
isl_basic_set_get_div(__isl_keep isl_basic_set * bset,int pos)12596 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12597 	int pos)
12598 {
12599 	return isl_basic_map_get_div(bset, pos);
12600 }
12601 
12602 /* Plug in "subs" for dimension "type", "pos" of "bset".
12603  *
12604  * Let i be the dimension to replace and let "subs" be of the form
12605  *
12606  *	f/d
12607  *
12608  * Any integer division with a non-zero coefficient for i,
12609  *
12610  *	floor((a i + g)/m)
12611  *
12612  * is replaced by
12613  *
12614  *	floor((a f + d g)/(m d))
12615  *
12616  * Constraints of the form
12617  *
12618  *	a i + g
12619  *
12620  * are replaced by
12621  *
12622  *	a f + d g
12623  *
12624  * We currently require that "subs" is an integral expression.
12625  * Handling rational expressions may require us to add stride constraints
12626  * as we do in isl_basic_set_preimage_multi_aff.
12627  */
isl_basic_set_substitute(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)12628 __isl_give isl_basic_set *isl_basic_set_substitute(
12629 	__isl_take isl_basic_set *bset,
12630 	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12631 {
12632 	int i;
12633 	isl_int v;
12634 	isl_ctx *ctx;
12635 
12636 	if (bset && isl_basic_set_plain_is_empty(bset))
12637 		return bset;
12638 
12639 	bset = isl_basic_set_cow(bset);
12640 	if (!bset || !subs)
12641 		goto error;
12642 
12643 	ctx = isl_basic_set_get_ctx(bset);
12644 	if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12645 		isl_die(ctx, isl_error_invalid,
12646 			"spaces don't match", goto error);
12647 	if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12648 		isl_die(ctx, isl_error_unsupported,
12649 			"cannot handle divs yet", goto error);
12650 	if (!isl_int_is_one(subs->v->el[0]))
12651 		isl_die(ctx, isl_error_invalid,
12652 			"can only substitute integer expressions", goto error);
12653 
12654 	pos += isl_basic_set_offset(bset, type);
12655 
12656 	isl_int_init(v);
12657 
12658 	for (i = 0; i < bset->n_eq; ++i) {
12659 		if (isl_int_is_zero(bset->eq[i][pos]))
12660 			continue;
12661 		isl_int_set(v, bset->eq[i][pos]);
12662 		isl_int_set_si(bset->eq[i][pos], 0);
12663 		isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12664 				v, subs->v->el + 1, subs->v->size - 1);
12665 	}
12666 
12667 	for (i = 0; i < bset->n_ineq; ++i) {
12668 		if (isl_int_is_zero(bset->ineq[i][pos]))
12669 			continue;
12670 		isl_int_set(v, bset->ineq[i][pos]);
12671 		isl_int_set_si(bset->ineq[i][pos], 0);
12672 		isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12673 				v, subs->v->el + 1, subs->v->size - 1);
12674 	}
12675 
12676 	for (i = 0; i < bset->n_div; ++i) {
12677 		if (isl_int_is_zero(bset->div[i][1 + pos]))
12678 			continue;
12679 		isl_int_set(v, bset->div[i][1 + pos]);
12680 		isl_int_set_si(bset->div[i][1 + pos], 0);
12681 		isl_seq_combine(bset->div[i] + 1,
12682 				subs->v->el[0], bset->div[i] + 1,
12683 				v, subs->v->el + 1, subs->v->size - 1);
12684 		isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12685 	}
12686 
12687 	isl_int_clear(v);
12688 
12689 	bset = isl_basic_set_simplify(bset);
12690 	return isl_basic_set_finalize(bset);
12691 error:
12692 	isl_basic_set_free(bset);
12693 	return NULL;
12694 }
12695 
12696 /* Plug in "subs" for dimension "type", "pos" of "set".
12697  */
isl_set_substitute(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)12698 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12699 	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12700 {
12701 	int i;
12702 
12703 	if (set && isl_set_plain_is_empty(set))
12704 		return set;
12705 
12706 	set = isl_set_cow(set);
12707 	if (!set || !subs)
12708 		goto error;
12709 
12710 	for (i = set->n - 1; i >= 0; --i) {
12711 		set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12712 		set = set_from_map(remove_if_empty(set_to_map(set), i));
12713 		if (!set)
12714 			return NULL;
12715 	}
12716 
12717 	return set;
12718 error:
12719 	isl_set_free(set);
12720 	return NULL;
12721 }
12722 
12723 /* Check if the range of "ma" is compatible with the domain or range
12724  * (depending on "type") of "bmap".
12725  */
check_basic_map_compatible_range_multi_aff(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)12726 static isl_stat check_basic_map_compatible_range_multi_aff(
12727 	__isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12728 	__isl_keep isl_multi_aff *ma)
12729 {
12730 	isl_bool m;
12731 	isl_space *ma_space;
12732 
12733 	ma_space = isl_multi_aff_get_space(ma);
12734 
12735 	m = isl_space_has_equal_params(bmap->dim, ma_space);
12736 	if (m < 0)
12737 		goto error;
12738 	if (!m)
12739 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12740 			"parameters don't match", goto error);
12741 	m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12742 	if (m < 0)
12743 		goto error;
12744 	if (!m)
12745 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12746 			"spaces don't match", goto error);
12747 
12748 	isl_space_free(ma_space);
12749 	return isl_stat_ok;
12750 error:
12751 	isl_space_free(ma_space);
12752 	return isl_stat_error;
12753 }
12754 
12755 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12756  * coefficients before the transformed range of dimensions,
12757  * the "n_after" coefficients after the transformed range of dimensions
12758  * and the coefficients of the other divs in "bmap".
12759  */
set_ma_divs(__isl_keep isl_basic_map * bmap,__isl_keep isl_multi_aff * ma,int n_before,int n_after,int n_div)12760 static int set_ma_divs(__isl_keep isl_basic_map *bmap,
12761 	__isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12762 {
12763 	int i;
12764 	int n_param;
12765 	int n_set;
12766 	isl_local_space *ls;
12767 
12768 	if (n_div == 0)
12769 		return 0;
12770 
12771 	ls = isl_aff_get_domain_local_space(ma->u.p[0]);
12772 	if (!ls)
12773 		return -1;
12774 
12775 	n_param = isl_local_space_dim(ls, isl_dim_param);
12776 	n_set = isl_local_space_dim(ls, isl_dim_set);
12777 	for (i = 0; i < n_div; ++i) {
12778 		int o_bmap = 0, o_ls = 0;
12779 
12780 		isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12781 		o_bmap += 1 + 1 + n_param;
12782 		o_ls += 1 + 1 + n_param;
12783 		isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12784 		o_bmap += n_before;
12785 		isl_seq_cpy(bmap->div[i] + o_bmap,
12786 			    ls->div->row[i] + o_ls, n_set);
12787 		o_bmap += n_set;
12788 		o_ls += n_set;
12789 		isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12790 		o_bmap += n_after;
12791 		isl_seq_cpy(bmap->div[i] + o_bmap,
12792 			    ls->div->row[i] + o_ls, n_div);
12793 		o_bmap += n_div;
12794 		o_ls += n_div;
12795 		isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12796 		if (isl_basic_map_add_div_constraints(bmap, i) < 0)
12797 			goto error;
12798 	}
12799 
12800 	isl_local_space_free(ls);
12801 	return 0;
12802 error:
12803 	isl_local_space_free(ls);
12804 	return -1;
12805 }
12806 
12807 /* How many stride constraints does "ma" enforce?
12808  * That is, how many of the affine expressions have a denominator
12809  * different from one?
12810  */
multi_aff_strides(__isl_keep isl_multi_aff * ma)12811 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12812 {
12813 	int i;
12814 	int strides = 0;
12815 
12816 	for (i = 0; i < ma->n; ++i)
12817 		if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
12818 			strides++;
12819 
12820 	return strides;
12821 }
12822 
12823 /* For each affine expression in ma of the form
12824  *
12825  *	x_i = (f_i y + h_i)/m_i
12826  *
12827  * with m_i different from one, add a constraint to "bmap"
12828  * of the form
12829  *
12830  *	f_i y + h_i = m_i alpha_i
12831  *
12832  * with alpha_i an additional existentially quantified variable.
12833  *
12834  * The input variables of "ma" correspond to a subset of the variables
12835  * of "bmap".  There are "n_before" variables in "bmap" before this
12836  * subset and "n_after" variables after this subset.
12837  * The integer divisions of the affine expressions in "ma" are assumed
12838  * to have been aligned.  There are "n_div_ma" of them and
12839  * they appear first in "bmap", straight after the "n_after" variables.
12840  */
add_ma_strides(__isl_take isl_basic_map * bmap,__isl_keep isl_multi_aff * ma,int n_before,int n_after,int n_div_ma)12841 static __isl_give isl_basic_map *add_ma_strides(
12842 	__isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12843 	int n_before, int n_after, int n_div_ma)
12844 {
12845 	int i, k;
12846 	int div;
12847 	int total;
12848 	int n_param;
12849 	int n_in;
12850 
12851 	total = isl_basic_map_total_dim(bmap);
12852 	n_param = isl_multi_aff_dim(ma, isl_dim_param);
12853 	n_in = isl_multi_aff_dim(ma, isl_dim_in);
12854 	for (i = 0; i < ma->n; ++i) {
12855 		int o_bmap = 0, o_ma = 1;
12856 
12857 		if (isl_int_is_one(ma->u.p[i]->v->el[0]))
12858 			continue;
12859 		div = isl_basic_map_alloc_div(bmap);
12860 		k = isl_basic_map_alloc_equality(bmap);
12861 		if (div < 0 || k < 0)
12862 			goto error;
12863 		isl_int_set_si(bmap->div[div][0], 0);
12864 		isl_seq_cpy(bmap->eq[k] + o_bmap,
12865 			    ma->u.p[i]->v->el + o_ma, 1 + n_param);
12866 		o_bmap += 1 + n_param;
12867 		o_ma += 1 + n_param;
12868 		isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12869 		o_bmap += n_before;
12870 		isl_seq_cpy(bmap->eq[k] + o_bmap,
12871 			    ma->u.p[i]->v->el + o_ma, n_in);
12872 		o_bmap += n_in;
12873 		o_ma += n_in;
12874 		isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12875 		o_bmap += n_after;
12876 		isl_seq_cpy(bmap->eq[k] + o_bmap,
12877 			    ma->u.p[i]->v->el + o_ma, n_div_ma);
12878 		o_bmap += n_div_ma;
12879 		o_ma += n_div_ma;
12880 		isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12881 		isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
12882 		total++;
12883 	}
12884 
12885 	return bmap;
12886 error:
12887 	isl_basic_map_free(bmap);
12888 	return NULL;
12889 }
12890 
12891 /* Replace the domain or range space (depending on "type) of "space" by "set".
12892  */
isl_space_set(__isl_take isl_space * space,enum isl_dim_type type,__isl_take isl_space * set)12893 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12894 	enum isl_dim_type type, __isl_take isl_space *set)
12895 {
12896 	if (type == isl_dim_in) {
12897 		space = isl_space_range(space);
12898 		space = isl_space_map_from_domain_and_range(set, space);
12899 	} else {
12900 		space = isl_space_domain(space);
12901 		space = isl_space_map_from_domain_and_range(space, set);
12902 	}
12903 
12904 	return space;
12905 }
12906 
12907 /* Compute the preimage of the domain or range (depending on "type")
12908  * of "bmap" under the function represented by "ma".
12909  * In other words, plug in "ma" in the domain or range of "bmap".
12910  * The result is a basic map that lives in the same space as "bmap"
12911  * except that the domain or range has been replaced by
12912  * the domain space of "ma".
12913  *
12914  * If bmap is represented by
12915  *
12916  *	A(p) + S u + B x + T v + C(divs) >= 0,
12917  *
12918  * where u and x are input and output dimensions if type == isl_dim_out
12919  * while x and v are input and output dimensions if type == isl_dim_in,
12920  * and ma is represented by
12921  *
12922  *	x = D(p) + F(y) + G(divs')
12923  *
12924  * then the result is
12925  *
12926  *	A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12927  *
12928  * The divs in the input set are similarly adjusted.
12929  * In particular
12930  *
12931  *	floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12932  *
12933  * becomes
12934  *
12935  *	floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12936  *		B_i G(divs') + c_i(divs))/n_i)
12937  *
12938  * If bmap is not a rational map and if F(y) involves any denominators
12939  *
12940  *	x_i = (f_i y + h_i)/m_i
12941  *
12942  * then additional constraints are added to ensure that we only
12943  * map back integer points.  That is we enforce
12944  *
12945  *	f_i y + h_i = m_i alpha_i
12946  *
12947  * with alpha_i an additional existentially quantified variable.
12948  *
12949  * We first copy over the divs from "ma".
12950  * Then we add the modified constraints and divs from "bmap".
12951  * Finally, we add the stride constraints, if needed.
12952  */
isl_basic_map_preimage_multi_aff(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_multi_aff * ma)12953 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12954 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
12955 	__isl_take isl_multi_aff *ma)
12956 {
12957 	int i, k;
12958 	isl_space *space;
12959 	isl_basic_map *res = NULL;
12960 	int n_before, n_after, n_div_bmap, n_div_ma;
12961 	isl_int f, c1, c2, g;
12962 	isl_bool rational;
12963 	int strides;
12964 
12965 	isl_int_init(f);
12966 	isl_int_init(c1);
12967 	isl_int_init(c2);
12968 	isl_int_init(g);
12969 
12970 	ma = isl_multi_aff_align_divs(ma);
12971 	if (!bmap || !ma)
12972 		goto error;
12973 	if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12974 		goto error;
12975 
12976 	if (type == isl_dim_in) {
12977 		n_before = 0;
12978 		n_after = isl_basic_map_dim(bmap, isl_dim_out);
12979 	} else {
12980 		n_before = isl_basic_map_dim(bmap, isl_dim_in);
12981 		n_after = 0;
12982 	}
12983 	n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12984 	n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
12985 
12986 	space = isl_multi_aff_get_domain_space(ma);
12987 	space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12988 	rational = isl_basic_map_is_rational(bmap);
12989 	strides = rational ? 0 : multi_aff_strides(ma);
12990 	res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12991 			    bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12992 	if (rational)
12993 		res = isl_basic_map_set_rational(res);
12994 
12995 	for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12996 		if (isl_basic_map_alloc_div(res) < 0)
12997 			goto error;
12998 
12999 	if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
13000 		goto error;
13001 
13002 	for (i = 0; i < bmap->n_eq; ++i) {
13003 		k = isl_basic_map_alloc_equality(res);
13004 		if (k < 0)
13005 			goto error;
13006 		isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13007 				n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
13008 	}
13009 
13010 	for (i = 0; i < bmap->n_ineq; ++i) {
13011 		k = isl_basic_map_alloc_inequality(res);
13012 		if (k < 0)
13013 			goto error;
13014 		isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13015 				n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
13016 	}
13017 
13018 	for (i = 0; i < bmap->n_div; ++i) {
13019 		if (isl_int_is_zero(bmap->div[i][0])) {
13020 			isl_int_set_si(res->div[n_div_ma + i][0], 0);
13021 			continue;
13022 		}
13023 		isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13024 				    n_before, n_after, n_div_ma, n_div_bmap,
13025 				    f, c1, c2, g, 1);
13026 	}
13027 
13028 	if (strides)
13029 		res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13030 
13031 	isl_int_clear(f);
13032 	isl_int_clear(c1);
13033 	isl_int_clear(c2);
13034 	isl_int_clear(g);
13035 	isl_basic_map_free(bmap);
13036 	isl_multi_aff_free(ma);
13037 	res = isl_basic_map_simplify(res);
13038 	return isl_basic_map_finalize(res);
13039 error:
13040 	isl_int_clear(f);
13041 	isl_int_clear(c1);
13042 	isl_int_clear(c2);
13043 	isl_int_clear(g);
13044 	isl_basic_map_free(bmap);
13045 	isl_multi_aff_free(ma);
13046 	isl_basic_map_free(res);
13047 	return NULL;
13048 }
13049 
13050 /* Compute the preimage of "bset" under the function represented by "ma".
13051  * In other words, plug in "ma" in "bset".  The result is a basic set
13052  * that lives in the domain space of "ma".
13053  */
isl_basic_set_preimage_multi_aff(__isl_take isl_basic_set * bset,__isl_take isl_multi_aff * ma)13054 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13055 	__isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13056 {
13057 	return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13058 }
13059 
13060 /* Compute the preimage of the domain of "bmap" under the function
13061  * represented by "ma".
13062  * In other words, plug in "ma" in the domain of "bmap".
13063  * The result is a basic map that lives in the same space as "bmap"
13064  * except that the domain has been replaced by the domain space of "ma".
13065  */
isl_basic_map_preimage_domain_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13066 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13067 	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13068 {
13069 	return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13070 }
13071 
13072 /* Compute the preimage of the range of "bmap" under the function
13073  * represented by "ma".
13074  * In other words, plug in "ma" in the range of "bmap".
13075  * The result is a basic map that lives in the same space as "bmap"
13076  * except that the range has been replaced by the domain space of "ma".
13077  */
isl_basic_map_preimage_range_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13078 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13079 	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13080 {
13081 	return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13082 }
13083 
13084 /* Check if the range of "ma" is compatible with the domain or range
13085  * (depending on "type") of "map".
13086  * Return isl_stat_error if anything is wrong.
13087  */
check_map_compatible_range_multi_aff(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13088 static isl_stat check_map_compatible_range_multi_aff(
13089 	__isl_keep isl_map *map, enum isl_dim_type type,
13090 	__isl_keep isl_multi_aff *ma)
13091 {
13092 	isl_bool m;
13093 	isl_space *ma_space;
13094 
13095 	ma_space = isl_multi_aff_get_space(ma);
13096 	m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
13097 	isl_space_free(ma_space);
13098 	if (m < 0)
13099 		return isl_stat_error;
13100 	if (!m)
13101 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
13102 			"spaces don't match", return isl_stat_error);
13103 	return isl_stat_ok;
13104 }
13105 
13106 /* Compute the preimage of the domain or range (depending on "type")
13107  * of "map" under the function represented by "ma".
13108  * In other words, plug in "ma" in the domain or range of "map".
13109  * The result is a map that lives in the same space as "map"
13110  * except that the domain or range has been replaced by
13111  * the domain space of "ma".
13112  *
13113  * The parameters are assumed to have been aligned.
13114  */
map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13115 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13116 	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13117 {
13118 	int i;
13119 	isl_space *space;
13120 
13121 	map = isl_map_cow(map);
13122 	ma = isl_multi_aff_align_divs(ma);
13123 	if (!map || !ma)
13124 		goto error;
13125 	if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13126 		goto error;
13127 
13128 	for (i = 0; i < map->n; ++i) {
13129 		map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13130 							isl_multi_aff_copy(ma));
13131 		if (!map->p[i])
13132 			goto error;
13133 	}
13134 
13135 	space = isl_multi_aff_get_domain_space(ma);
13136 	space = isl_space_set(isl_map_get_space(map), type, space);
13137 
13138 	isl_space_free(map->dim);
13139 	map->dim = space;
13140 	if (!map->dim)
13141 		goto error;
13142 
13143 	isl_multi_aff_free(ma);
13144 	if (map->n > 1)
13145 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
13146 	ISL_F_CLR(map, ISL_SET_NORMALIZED);
13147 	return map;
13148 error:
13149 	isl_multi_aff_free(ma);
13150 	isl_map_free(map);
13151 	return NULL;
13152 }
13153 
13154 /* Compute the preimage of the domain or range (depending on "type")
13155  * of "map" under the function represented by "ma".
13156  * In other words, plug in "ma" in the domain or range of "map".
13157  * The result is a map that lives in the same space as "map"
13158  * except that the domain or range has been replaced by
13159  * the domain space of "ma".
13160  */
isl_map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13161 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13162 	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13163 {
13164 	isl_bool aligned;
13165 
13166 	if (!map || !ma)
13167 		goto error;
13168 
13169 	aligned = isl_map_space_has_equal_params(map, ma->space);
13170 	if (aligned < 0)
13171 		goto error;
13172 	if (aligned)
13173 		return map_preimage_multi_aff(map, type, ma);
13174 
13175 	if (isl_map_check_named_params(map) < 0)
13176 		goto error;
13177 	if (!isl_space_has_named_params(ma->space))
13178 		isl_die(map->ctx, isl_error_invalid,
13179 			"unaligned unnamed parameters", goto error);
13180 	map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13181 	ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13182 
13183 	return map_preimage_multi_aff(map, type, ma);
13184 error:
13185 	isl_multi_aff_free(ma);
13186 	return isl_map_free(map);
13187 }
13188 
13189 /* Compute the preimage of "set" under the function represented by "ma".
13190  * In other words, plug in "ma" in "set".  The result is a set
13191  * that lives in the domain space of "ma".
13192  */
isl_set_preimage_multi_aff(__isl_take isl_set * set,__isl_take isl_multi_aff * ma)13193 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13194 	__isl_take isl_multi_aff *ma)
13195 {
13196 	return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13197 }
13198 
13199 /* Compute the preimage of the domain of "map" under the function
13200  * represented by "ma".
13201  * In other words, plug in "ma" in the domain of "map".
13202  * The result is a map that lives in the same space as "map"
13203  * except that the domain has been replaced by the domain space of "ma".
13204  */
isl_map_preimage_domain_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)13205 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13206 	__isl_take isl_multi_aff *ma)
13207 {
13208 	return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13209 }
13210 
13211 /* Compute the preimage of the range of "map" under the function
13212  * represented by "ma".
13213  * In other words, plug in "ma" in the range of "map".
13214  * The result is a map that lives in the same space as "map"
13215  * except that the range has been replaced by the domain space of "ma".
13216  */
isl_map_preimage_range_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)13217 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13218 	__isl_take isl_multi_aff *ma)
13219 {
13220 	return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
13221 }
13222 
13223 /* Compute the preimage of "map" under the function represented by "pma".
13224  * In other words, plug in "pma" in the domain or range of "map".
13225  * The result is a map that lives in the same space as "map",
13226  * except that the space of type "type" has been replaced by
13227  * the domain space of "pma".
13228  *
13229  * The parameters of "map" and "pma" are assumed to have been aligned.
13230  */
isl_map_preimage_pw_multi_aff_aligned(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)13231 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
13232 	__isl_take isl_map *map, enum isl_dim_type type,
13233 	__isl_take isl_pw_multi_aff *pma)
13234 {
13235 	int i;
13236 	isl_map *res;
13237 
13238 	if (!pma)
13239 		goto error;
13240 
13241 	if (pma->n == 0) {
13242 		isl_pw_multi_aff_free(pma);
13243 		res = isl_map_empty(isl_map_get_space(map));
13244 		isl_map_free(map);
13245 		return res;
13246 	}
13247 
13248 	res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13249 					isl_multi_aff_copy(pma->p[0].maff));
13250 	if (type == isl_dim_in)
13251 		res = isl_map_intersect_domain(res,
13252 						isl_map_copy(pma->p[0].set));
13253 	else
13254 		res = isl_map_intersect_range(res,
13255 						isl_map_copy(pma->p[0].set));
13256 
13257 	for (i = 1; i < pma->n; ++i) {
13258 		isl_map *res_i;
13259 
13260 		res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13261 					isl_multi_aff_copy(pma->p[i].maff));
13262 		if (type == isl_dim_in)
13263 			res_i = isl_map_intersect_domain(res_i,
13264 						isl_map_copy(pma->p[i].set));
13265 		else
13266 			res_i = isl_map_intersect_range(res_i,
13267 						isl_map_copy(pma->p[i].set));
13268 		res = isl_map_union(res, res_i);
13269 	}
13270 
13271 	isl_pw_multi_aff_free(pma);
13272 	isl_map_free(map);
13273 	return res;
13274 error:
13275 	isl_pw_multi_aff_free(pma);
13276 	isl_map_free(map);
13277 	return NULL;
13278 }
13279 
13280 /* Compute the preimage of "map" under the function represented by "pma".
13281  * In other words, plug in "pma" in the domain or range of "map".
13282  * The result is a map that lives in the same space as "map",
13283  * except that the space of type "type" has been replaced by
13284  * the domain space of "pma".
13285  */
isl_map_preimage_pw_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)13286 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
13287 	enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
13288 {
13289 	isl_bool aligned;
13290 
13291 	if (!map || !pma)
13292 		goto error;
13293 
13294 	aligned = isl_map_space_has_equal_params(map, pma->dim);
13295 	if (aligned < 0)
13296 		goto error;
13297 	if (aligned)
13298 		return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13299 
13300 	if (isl_map_check_named_params(map) < 0)
13301 		goto error;
13302 	if (isl_pw_multi_aff_check_named_params(pma) < 0)
13303 		goto error;
13304 	map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
13305 	pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
13306 
13307 	return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13308 error:
13309 	isl_pw_multi_aff_free(pma);
13310 	return isl_map_free(map);
13311 }
13312 
13313 /* Compute the preimage of "set" under the function represented by "pma".
13314  * In other words, plug in "pma" in "set".  The result is a set
13315  * that lives in the domain space of "pma".
13316  */
isl_set_preimage_pw_multi_aff(__isl_take isl_set * set,__isl_take isl_pw_multi_aff * pma)13317 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
13318 	__isl_take isl_pw_multi_aff *pma)
13319 {
13320 	return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
13321 }
13322 
13323 /* Compute the preimage of the domain of "map" under the function
13324  * represented by "pma".
13325  * In other words, plug in "pma" in the domain of "map".
13326  * The result is a map that lives in the same space as "map",
13327  * except that domain space has been replaced by the domain space of "pma".
13328  */
isl_map_preimage_domain_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)13329 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
13330 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13331 {
13332 	return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
13333 }
13334 
13335 /* Compute the preimage of the range of "map" under the function
13336  * represented by "pma".
13337  * In other words, plug in "pma" in the range of "map".
13338  * The result is a map that lives in the same space as "map",
13339  * except that range space has been replaced by the domain space of "pma".
13340  */
isl_map_preimage_range_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)13341 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
13342 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13343 {
13344 	return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
13345 }
13346 
13347 /* Compute the preimage of "map" under the function represented by "mpa".
13348  * In other words, plug in "mpa" in the domain or range of "map".
13349  * The result is a map that lives in the same space as "map",
13350  * except that the space of type "type" has been replaced by
13351  * the domain space of "mpa".
13352  *
13353  * If the map does not involve any constraints that refer to the
13354  * dimensions of the substituted space, then the only possible
13355  * effect of "mpa" on the map is to map the space to a different space.
13356  * We create a separate isl_multi_aff to effectuate this change
13357  * in order to avoid spurious splitting of the map along the pieces
13358  * of "mpa".
13359  * If "mpa" has a non-trivial explicit domain, however,
13360  * then the full substitution should be performed.
13361  */
isl_map_preimage_multi_pw_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_pw_aff * mpa)13362 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
13363 	enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
13364 {
13365 	int n;
13366 	isl_bool full;
13367 	isl_pw_multi_aff *pma;
13368 
13369 	if (!map || !mpa)
13370 		goto error;
13371 
13372 	n = isl_map_dim(map, type);
13373 	full = isl_map_involves_dims(map, type, 0, n);
13374 	if (full >= 0 && !full)
13375 		full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
13376 	if (full < 0)
13377 		goto error;
13378 	if (!full) {
13379 		isl_space *space;
13380 		isl_multi_aff *ma;
13381 
13382 		space = isl_multi_pw_aff_get_space(mpa);
13383 		isl_multi_pw_aff_free(mpa);
13384 		ma = isl_multi_aff_zero(space);
13385 		return isl_map_preimage_multi_aff(map, type, ma);
13386 	}
13387 
13388 	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
13389 	return isl_map_preimage_pw_multi_aff(map, type, pma);
13390 error:
13391 	isl_map_free(map);
13392 	isl_multi_pw_aff_free(mpa);
13393 	return NULL;
13394 }
13395 
13396 /* Compute the preimage of "map" under the function represented by "mpa".
13397  * In other words, plug in "mpa" in the domain "map".
13398  * The result is a map that lives in the same space as "map",
13399  * except that domain space has been replaced by the domain space of "mpa".
13400  */
isl_map_preimage_domain_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * mpa)13401 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
13402 	__isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
13403 {
13404 	return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
13405 }
13406 
13407 /* Compute the preimage of "set" by the function represented by "mpa".
13408  * In other words, plug in "mpa" in "set".
13409  */
isl_set_preimage_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * mpa)13410 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
13411 	__isl_take isl_multi_pw_aff *mpa)
13412 {
13413 	return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
13414 }
13415 
13416 /* Return a copy of the equality constraints of "bset" as a matrix.
13417  */
isl_basic_set_extract_equalities(__isl_keep isl_basic_set * bset)13418 __isl_give isl_mat *isl_basic_set_extract_equalities(
13419 	__isl_keep isl_basic_set *bset)
13420 {
13421 	isl_ctx *ctx;
13422 	unsigned total;
13423 
13424 	if (!bset)
13425 		return NULL;
13426 
13427 	ctx = isl_basic_set_get_ctx(bset);
13428 	total = 1 + isl_basic_set_dim(bset, isl_dim_all);
13429 	return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
13430 }
13431 
13432 /* Are the "n" "coefficients" starting at "first" of the integer division
13433  * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
13434  * to each other?
13435  * The "coefficient" at position 0 is the denominator.
13436  * The "coefficient" at position 1 is the constant term.
13437  */
isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map * bmap1,int pos1,__isl_keep isl_basic_map * bmap2,int pos2,unsigned first,unsigned n)13438 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
13439 	int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
13440 	unsigned first, unsigned n)
13441 {
13442 	if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
13443 		return isl_bool_error;
13444 	if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
13445 		return isl_bool_error;
13446 	return isl_seq_eq(bmap1->div[pos1] + first,
13447 			  bmap2->div[pos2] + first, n);
13448 }
13449 
13450 /* Are the integer division expressions at position "pos1" in "bmap1" and
13451  * "pos2" in "bmap2" equal to each other, except that the constant terms
13452  * are different?
13453  */
isl_basic_map_equal_div_expr_except_constant(__isl_keep isl_basic_map * bmap1,int pos1,__isl_keep isl_basic_map * bmap2,int pos2)13454 isl_bool isl_basic_map_equal_div_expr_except_constant(
13455 	__isl_keep isl_basic_map *bmap1, int pos1,
13456 	__isl_keep isl_basic_map *bmap2, int pos2)
13457 {
13458 	isl_bool equal;
13459 	unsigned total;
13460 
13461 	if (!bmap1 || !bmap2)
13462 		return isl_bool_error;
13463 	total = isl_basic_map_total_dim(bmap1);
13464 	if (total != isl_basic_map_total_dim(bmap2))
13465 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
13466 			"incomparable div expressions", return isl_bool_error);
13467 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13468 						0, 1);
13469 	if (equal < 0 || !equal)
13470 		return equal;
13471 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13472 						1, 1);
13473 	if (equal < 0 || equal)
13474 		return isl_bool_not(equal);
13475 	return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13476 						2, total);
13477 }
13478 
13479 /* Replace the numerator of the constant term of the integer division
13480  * expression at position "div" in "bmap" by "value".
13481  * The caller guarantees that this does not change the meaning
13482  * of the input.
13483  */
isl_basic_map_set_div_expr_constant_num_si_inplace(__isl_take isl_basic_map * bmap,int div,int value)13484 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
13485 	__isl_take isl_basic_map *bmap, int div, int value)
13486 {
13487 	if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
13488 		return isl_basic_map_free(bmap);
13489 
13490 	isl_int_set_si(bmap->div[div][1], value);
13491 
13492 	return bmap;
13493 }
13494 
13495 /* Is the point "inner" internal to inequality constraint "ineq"
13496  * of "bset"?
13497  * The point is considered to be internal to the inequality constraint,
13498  * if it strictly lies on the positive side of the inequality constraint,
13499  * or if it lies on the constraint and the constraint is lexico-positive.
13500  */
is_internal(__isl_keep isl_vec * inner,__isl_keep isl_basic_set * bset,int ineq)13501 static isl_bool is_internal(__isl_keep isl_vec *inner,
13502 	__isl_keep isl_basic_set *bset, int ineq)
13503 {
13504 	isl_ctx *ctx;
13505 	int pos;
13506 	unsigned total;
13507 
13508 	if (!inner || !bset)
13509 		return isl_bool_error;
13510 
13511 	ctx = isl_basic_set_get_ctx(bset);
13512 	isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13513 				&ctx->normalize_gcd);
13514 	if (!isl_int_is_zero(ctx->normalize_gcd))
13515 		return isl_int_is_nonneg(ctx->normalize_gcd);
13516 
13517 	total = isl_basic_set_dim(bset, isl_dim_all);
13518 	pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13519 	return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13520 }
13521 
13522 /* Tighten the inequality constraints of "bset" that are outward with respect
13523  * to the point "vec".
13524  * That is, tighten the constraints that are not satisfied by "vec".
13525  *
13526  * "vec" is a point internal to some superset S of "bset" that is used
13527  * to make the subsets of S disjoint, by tightening one half of the constraints
13528  * that separate two subsets.  In particular, the constraints of S
13529  * are all satisfied by "vec" and should not be tightened.
13530  * Of the internal constraints, those that have "vec" on the outside
13531  * are tightened.  The shared facet is included in the adjacent subset
13532  * with the opposite constraint.
13533  * For constraints that saturate "vec", this criterion cannot be used
13534  * to determine which of the two sides should be tightened.
13535  * Instead, the sign of the first non-zero coefficient is used
13536  * to make this choice.  Note that this second criterion is never used
13537  * on the constraints of S since "vec" is interior to "S".
13538  */
isl_basic_set_tighten_outward(__isl_take isl_basic_set * bset,__isl_keep isl_vec * vec)13539 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13540 	__isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13541 {
13542 	int j;
13543 
13544 	bset = isl_basic_set_cow(bset);
13545 	if (!bset)
13546 		return NULL;
13547 	for (j = 0; j < bset->n_ineq; ++j) {
13548 		isl_bool internal;
13549 
13550 		internal = is_internal(vec, bset, j);
13551 		if (internal < 0)
13552 			return isl_basic_set_free(bset);
13553 		if (internal)
13554 			continue;
13555 		isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13556 	}
13557 
13558 	return bset;
13559 }
13560 
13561 /* Replace the variables x of type "type" starting at "first" in "bmap"
13562  * by x' with x = M x' with M the matrix trans.
13563  * That is, replace the corresponding coefficients c by c M.
13564  *
13565  * The transformation matrix should be a square matrix.
13566  */
isl_basic_map_transform_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)13567 __isl_give isl_basic_map *isl_basic_map_transform_dims(
13568 	__isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
13569 	__isl_take isl_mat *trans)
13570 {
13571 	unsigned pos;
13572 
13573 	bmap = isl_basic_map_cow(bmap);
13574 	if (!bmap || !trans)
13575 		goto error;
13576 
13577 	if (trans->n_row != trans->n_col)
13578 		isl_die(trans->ctx, isl_error_invalid,
13579 			"expecting square transformation matrix", goto error);
13580 	if (first + trans->n_row > isl_basic_map_dim(bmap, type))
13581 		isl_die(trans->ctx, isl_error_invalid,
13582 			"oversized transformation matrix", goto error);
13583 
13584 	pos = isl_basic_map_offset(bmap, type) + first;
13585 
13586 	if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
13587 			isl_mat_copy(trans)) < 0)
13588 		goto error;
13589 	if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
13590 		      isl_mat_copy(trans)) < 0)
13591 		goto error;
13592 	if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
13593 		      isl_mat_copy(trans)) < 0)
13594 		goto error;
13595 
13596 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
13597 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
13598 
13599 	isl_mat_free(trans);
13600 	return bmap;
13601 error:
13602 	isl_mat_free(trans);
13603 	isl_basic_map_free(bmap);
13604 	return NULL;
13605 }
13606 
13607 /* Replace the variables x of type "type" starting at "first" in "bset"
13608  * by x' with x = M x' with M the matrix trans.
13609  * That is, replace the corresponding coefficients c by c M.
13610  *
13611  * The transformation matrix should be a square matrix.
13612  */
isl_basic_set_transform_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)13613 __isl_give isl_basic_set *isl_basic_set_transform_dims(
13614 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
13615 	__isl_take isl_mat *trans)
13616 {
13617 	return isl_basic_map_transform_dims(bset, type, first, trans);
13618 }
13619