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  * Copyright 2018-2019 Cerebras Systems
9  *
10  * Use of this software is governed by the MIT license
11  *
12  * Written by Sven Verdoolaege, K.U.Leuven, Departement
13  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
14  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
15  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
16  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
17  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
18  * B.P. 105 - 78153 Le Chesnay, France
19  * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
20  * CS 42112, 75589 Paris Cedex 12, France
21  * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
22  */
23 
24 #include <string.h>
25 #include <isl_ctx_private.h>
26 #include <isl_map_private.h>
27 #include <isl_blk.h>
28 #include <isl_id_private.h>
29 #include <isl/constraint.h>
30 #include "isl_space_private.h"
31 #include "isl_equalities.h"
32 #include <isl_lp_private.h>
33 #include <isl_seq.h>
34 #include <isl/set.h>
35 #include <isl/map.h>
36 #include <isl_reordering.h>
37 #include "isl_sample.h"
38 #include <isl_sort.h>
39 #include "isl_tab.h"
40 #include <isl/vec.h>
41 #include <isl_mat_private.h>
42 #include <isl_vec_private.h>
43 #include <isl_dim_map.h>
44 #include <isl_local_space_private.h>
45 #include <isl_aff_private.h>
46 #include <isl_options_private.h>
47 #include <isl_morph.h>
48 #include <isl_val_private.h>
49 #include <isl_printer_private.h>
50 
51 #include <bset_to_bmap.c>
52 #include <bset_from_bmap.c>
53 #include <set_to_map.c>
54 #include <set_from_map.c>
55 
56 /* Treat "bset" as a basic map.
57  * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
58  * this function performs a redundant cast.
59  */
const_bset_to_bmap(__isl_keep const isl_basic_set * bset)60 static __isl_keep const isl_basic_map *const_bset_to_bmap(
61 	__isl_keep const isl_basic_set *bset)
62 {
63 	return (const isl_basic_map *) bset;
64 }
65 
66 #undef TYPE
67 #define TYPE	isl_basic_map
68 #include "has_single_reference_templ.c"
69 
pos(__isl_keep isl_space * space,enum isl_dim_type type)70 static unsigned pos(__isl_keep isl_space *space, enum isl_dim_type type)
71 {
72 	switch (type) {
73 	case isl_dim_param:	return 1;
74 	case isl_dim_in:	return 1 + space->nparam;
75 	case isl_dim_out:	return 1 + space->nparam + space->n_in;
76 	default:		return 0;
77 	}
78 }
79 
isl_basic_map_dim(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)80 isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
81 				enum isl_dim_type type)
82 {
83 	if (!bmap)
84 		return isl_size_error;
85 	switch (type) {
86 	case isl_dim_cst:	return 1;
87 	case isl_dim_param:
88 	case isl_dim_in:
89 	case isl_dim_out:	return isl_space_dim(bmap->dim, type);
90 	case isl_dim_div:	return bmap->n_div;
91 	case isl_dim_all:	return isl_basic_map_total_dim(bmap);
92 	default:		return 0;
93 	}
94 }
95 
96 /* Return the space of "map".
97  */
isl_map_peek_space(__isl_keep const isl_map * map)98 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
99 {
100 	return map ? map->dim : NULL;
101 }
102 
103 /* Return the space of "set".
104  */
isl_set_peek_space(__isl_keep isl_set * set)105 __isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
106 {
107 	return isl_map_peek_space(set_to_map(set));
108 }
109 
isl_map_dim(__isl_keep isl_map * map,enum isl_dim_type type)110 isl_size isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
111 {
112 	return isl_space_dim(isl_map_peek_space(map), type);
113 }
114 
isl_set_dim(__isl_keep isl_set * set,enum isl_dim_type type)115 isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
116 {
117 	return isl_map_dim(set_to_map(set), type);
118 }
119 
120 /* Return the position of the variables of the given type
121  * within the sequence of variables of "bmap".
122  */
isl_basic_map_var_offset(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)123 isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
124 	enum isl_dim_type type)
125 {
126 	isl_space *space;
127 
128 	space = isl_basic_map_peek_space(bmap);
129 	if (!space)
130 		return isl_size_error;
131 
132 	switch (type) {
133 	case isl_dim_param:
134 	case isl_dim_in:
135 	case isl_dim_out:	return isl_space_offset(space, type);
136 	case isl_dim_div:	return isl_space_dim(space, isl_dim_all);
137 	case isl_dim_cst:
138 	default:
139 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
140 			"invalid dimension type", return isl_size_error);
141 	}
142 }
143 
144 /* Return the position of the variables of the given type
145  * within the sequence of variables of "bset".
146  */
isl_basic_set_var_offset(__isl_keep isl_basic_set * bset,enum isl_dim_type type)147 isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
148 	enum isl_dim_type type)
149 {
150 	return isl_basic_map_var_offset(bset_to_bmap(bset), type);
151 }
152 
153 /* Return the position of the coefficients of the variables of the given type
154  * within the sequence of coefficients of "bmap".
155  */
isl_basic_map_offset(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)156 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
157 	enum isl_dim_type type)
158 {
159 	switch (type) {
160 	case isl_dim_cst:	return 0;
161 	case isl_dim_param:
162 	case isl_dim_in:
163 	case isl_dim_out:
164 	case isl_dim_div:	return 1 + isl_basic_map_var_offset(bmap, type);
165 	default:		return 0;
166 	}
167 }
168 
isl_basic_set_offset(__isl_keep isl_basic_set * bset,enum isl_dim_type type)169 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
170 					enum isl_dim_type type)
171 {
172 	return isl_basic_map_offset(bset, type);
173 }
174 
map_offset(__isl_keep isl_map * map,enum isl_dim_type type)175 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
176 {
177 	return pos(map->dim, type);
178 }
179 
isl_basic_set_dim(__isl_keep isl_basic_set * bset,enum isl_dim_type type)180 isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,
181 				enum isl_dim_type type)
182 {
183 	return isl_basic_map_dim(bset, type);
184 }
185 
isl_basic_set_n_dim(__isl_keep isl_basic_set * bset)186 isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
187 {
188 	return isl_basic_set_dim(bset, isl_dim_set);
189 }
190 
isl_basic_set_n_param(__isl_keep isl_basic_set * bset)191 isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
192 {
193 	return isl_basic_set_dim(bset, isl_dim_param);
194 }
195 
isl_basic_set_total_dim(__isl_keep const isl_basic_set * bset)196 isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
197 {
198 	return isl_basic_map_total_dim(const_bset_to_bmap(bset));
199 }
200 
isl_set_n_dim(__isl_keep isl_set * set)201 isl_size isl_set_n_dim(__isl_keep isl_set *set)
202 {
203 	return isl_set_dim(set, isl_dim_set);
204 }
205 
isl_set_n_param(__isl_keep isl_set * set)206 isl_size isl_set_n_param(__isl_keep isl_set *set)
207 {
208 	return isl_set_dim(set, isl_dim_param);
209 }
210 
isl_basic_map_total_dim(__isl_keep const isl_basic_map * bmap)211 isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
212 {
213 	isl_size dim;
214 
215 	if (!bmap)
216 		return isl_size_error;
217 	dim = isl_space_dim(bmap->dim, isl_dim_all);
218 	if (dim < 0)
219 		return isl_size_error;
220 	return dim + bmap->n_div;
221 }
222 
223 /* Return the number of equality constraints in the description of "bmap".
224  * Return isl_size_error on error.
225  */
isl_basic_map_n_equality(__isl_keep isl_basic_map * bmap)226 isl_size isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
227 {
228 	if (!bmap)
229 		return isl_size_error;
230 	return bmap->n_eq;
231 }
232 
233 /* Return the number of equality constraints in the description of "bset".
234  * Return isl_size_error on error.
235  */
isl_basic_set_n_equality(__isl_keep isl_basic_set * bset)236 isl_size isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
237 {
238 	return isl_basic_map_n_equality(bset_to_bmap(bset));
239 }
240 
241 /* Return the number of inequality constraints in the description of "bmap".
242  * Return isl_size_error on error.
243  */
isl_basic_map_n_inequality(__isl_keep isl_basic_map * bmap)244 isl_size isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
245 {
246 	if (!bmap)
247 		return isl_size_error;
248 	return bmap->n_ineq;
249 }
250 
251 /* Return the number of inequality constraints in the description of "bset".
252  * Return isl_size_error on error.
253  */
isl_basic_set_n_inequality(__isl_keep isl_basic_set * bset)254 isl_size isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
255 {
256 	return isl_basic_map_n_inequality(bset_to_bmap(bset));
257 }
258 
259 /* Do "bmap1" and "bmap2" have the same parameters?
260  */
isl_basic_map_has_equal_params(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)261 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
262 	__isl_keep isl_basic_map *bmap2)
263 {
264 	isl_space *space1, *space2;
265 
266 	space1 = isl_basic_map_peek_space(bmap1);
267 	space2 = isl_basic_map_peek_space(bmap2);
268 	return isl_space_has_equal_params(space1, space2);
269 }
270 
271 /* Do "map1" and "map2" have the same parameters?
272  */
isl_map_has_equal_params(__isl_keep isl_map * map1,__isl_keep isl_map * map2)273 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
274 	__isl_keep isl_map *map2)
275 {
276 	isl_space *space1, *space2;
277 
278 	space1 = isl_map_peek_space(map1);
279 	space2 = isl_map_peek_space(map2);
280 	return isl_space_has_equal_params(space1, space2);
281 }
282 
283 /* Do "map" and "set" have the same parameters?
284  */
isl_map_set_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_set * set)285 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
286 	__isl_keep isl_set *set)
287 {
288 	return isl_map_has_equal_params(map, set_to_map(set));
289 }
290 
291 /* Is the tuple of type "type" of "bmap" the same as the single tuple of "bset"?
292  */
isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_basic_set * bset)293 static isl_bool isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map *bmap,
294 	enum isl_dim_type type, __isl_keep isl_basic_set *bset)
295 {
296 	isl_space *bmap_space, *bset_space;
297 
298 	bmap_space = isl_basic_map_peek_space(bmap);
299 	bset_space = isl_basic_set_peek_space(bset);
300 	return isl_space_tuple_is_equal(bmap_space, type,
301 					bset_space, isl_dim_set);
302 }
303 
304 /* Is the tuple of type "type" of "map" the same as the single tuple of "set"?
305  */
isl_map_set_tuple_is_equal(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_set * set)306 static isl_bool isl_map_set_tuple_is_equal(__isl_keep isl_map *map,
307 	enum isl_dim_type type, __isl_keep isl_set *set)
308 {
309 	return isl_map_tuple_is_equal(map, type, set_to_map(set), isl_dim_set);
310 }
311 
isl_map_compatible_domain(__isl_keep isl_map * map,__isl_keep isl_set * set)312 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
313 	__isl_keep isl_set *set)
314 {
315 	isl_bool m;
316 	if (!map || !set)
317 		return isl_bool_error;
318 	m = isl_map_has_equal_params(map, set_to_map(set));
319 	if (m < 0 || !m)
320 		return m;
321 	return isl_map_set_tuple_is_equal(map, isl_dim_in, set);
322 }
323 
isl_basic_map_compatible_domain(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)324 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
325 	__isl_keep isl_basic_set *bset)
326 {
327 	isl_bool m;
328 	if (!bmap || !bset)
329 		return isl_bool_error;
330 	m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
331 	if (m < 0 || !m)
332 		return m;
333 	return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_in, bset);
334 }
335 
isl_map_compatible_range(__isl_keep isl_map * map,__isl_keep isl_set * set)336 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
337 	__isl_keep isl_set *set)
338 {
339 	isl_bool m;
340 	if (!map || !set)
341 		return isl_bool_error;
342 	m = isl_map_has_equal_params(map, set_to_map(set));
343 	if (m < 0 || !m)
344 		return m;
345 	return isl_map_set_tuple_is_equal(map, isl_dim_out, set);
346 }
347 
isl_basic_map_compatible_range(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)348 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
349 	__isl_keep isl_basic_set *bset)
350 {
351 	isl_bool m;
352 	if (!bmap || !bset)
353 		return isl_bool_error;
354 	m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
355 	if (m < 0 || !m)
356 		return m;
357 	return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_out, bset);
358 }
359 
isl_basic_map_get_ctx(__isl_keep isl_basic_map * bmap)360 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
361 {
362 	return bmap ? bmap->ctx : NULL;
363 }
364 
isl_basic_set_get_ctx(__isl_keep isl_basic_set * bset)365 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
366 {
367 	return bset ? bset->ctx : NULL;
368 }
369 
isl_map_get_ctx(__isl_keep isl_map * map)370 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
371 {
372 	return map ? map->ctx : NULL;
373 }
374 
isl_set_get_ctx(__isl_keep isl_set * set)375 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
376 {
377 	return set ? set->ctx : NULL;
378 }
379 
380 /* Return the space of "bmap".
381  */
isl_basic_map_peek_space(__isl_keep const isl_basic_map * bmap)382 __isl_keep isl_space *isl_basic_map_peek_space(
383 	__isl_keep const isl_basic_map *bmap)
384 {
385 	return bmap ? bmap->dim : NULL;
386 }
387 
388 /* Return the space of "bset".
389  */
isl_basic_set_peek_space(__isl_keep isl_basic_set * bset)390 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
391 {
392 	return isl_basic_map_peek_space(bset_to_bmap(bset));
393 }
394 
isl_basic_map_get_space(__isl_keep isl_basic_map * bmap)395 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
396 {
397 	return isl_space_copy(isl_basic_map_peek_space(bmap));
398 }
399 
isl_basic_set_get_space(__isl_keep isl_basic_set * bset)400 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
401 {
402 	return isl_basic_map_get_space(bset_to_bmap(bset));
403 }
404 
405 /* Return the space of "bmap".
406  * This may be either a copy or the space itself
407  * if there is only one reference to "bmap".
408  * This allows the space to be modified inplace
409  * if both the basic map and its space have only a single reference.
410  * The caller is not allowed to modify "bmap" between this call and
411  * a subsequent call to isl_basic_map_restore_space.
412  * The only exception is that isl_basic_map_free can be called instead.
413  */
isl_basic_map_take_space(__isl_keep isl_basic_map * bmap)414 static __isl_give isl_space *isl_basic_map_take_space(
415 	__isl_keep isl_basic_map *bmap)
416 {
417 	isl_space *space;
418 
419 	if (!bmap)
420 		return NULL;
421 	if (bmap->ref != 1)
422 		return isl_basic_map_get_space(bmap);
423 	space = bmap->dim;
424 	bmap->dim = NULL;
425 	return space;
426 }
427 
428 /* Set the space of "bmap" to "space", where the space of "bmap" may be missing
429  * due to a preceding call to isl_basic_map_take_space.
430  * However, in this case, "bmap" only has a single reference and
431  * then the call to isl_basic_map_cow has no effect.
432  */
isl_basic_map_restore_space(__isl_take isl_basic_map * bmap,__isl_take isl_space * space)433 static __isl_give isl_basic_map *isl_basic_map_restore_space(
434 	__isl_take isl_basic_map *bmap, __isl_take isl_space *space)
435 {
436 	if (!bmap || !space)
437 		goto error;
438 
439 	if (bmap->dim == space) {
440 		isl_space_free(space);
441 		return bmap;
442 	}
443 
444 	bmap = isl_basic_map_cow(bmap);
445 	if (!bmap)
446 		goto error;
447 	isl_space_free(bmap->dim);
448 	bmap->dim = space;
449 
450 	return bmap;
451 error:
452 	isl_basic_map_free(bmap);
453 	isl_space_free(space);
454 	return NULL;
455 }
456 
457 /* Extract the divs in "bmap" as a matrix.
458  */
isl_basic_map_get_divs(__isl_keep isl_basic_map * bmap)459 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
460 {
461 	int i;
462 	isl_ctx *ctx;
463 	isl_mat *div;
464 	isl_size v_div;
465 	unsigned cols;
466 
467 	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
468 	if (v_div < 0)
469 		return NULL;
470 
471 	ctx = isl_basic_map_get_ctx(bmap);
472 	cols = 1 + 1 + v_div + bmap->n_div;
473 	div = isl_mat_alloc(ctx, bmap->n_div, cols);
474 	if (!div)
475 		return NULL;
476 
477 	for (i = 0; i < bmap->n_div; ++i)
478 		isl_seq_cpy(div->row[i], bmap->div[i], cols);
479 
480 	return div;
481 }
482 
483 /* Extract the divs in "bset" as a matrix.
484  */
isl_basic_set_get_divs(__isl_keep isl_basic_set * bset)485 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
486 {
487 	return isl_basic_map_get_divs(bset);
488 }
489 
isl_basic_map_get_local_space(__isl_keep isl_basic_map * bmap)490 __isl_give isl_local_space *isl_basic_map_get_local_space(
491 	__isl_keep isl_basic_map *bmap)
492 {
493 	isl_mat *div;
494 
495 	if (!bmap)
496 		return NULL;
497 
498 	div = isl_basic_map_get_divs(bmap);
499 	return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
500 }
501 
isl_basic_set_get_local_space(__isl_keep isl_basic_set * bset)502 __isl_give isl_local_space *isl_basic_set_get_local_space(
503 	__isl_keep isl_basic_set *bset)
504 {
505 	return isl_basic_map_get_local_space(bset);
506 }
507 
508 /* For each known div d = floor(f/m), add the constraints
509  *
510  *		f - m d >= 0
511  *		-(f-(m-1)) + m d >= 0
512  *
513  * Do not finalize the result.
514  */
add_known_div_constraints(__isl_take isl_basic_map * bmap)515 static __isl_give isl_basic_map *add_known_div_constraints(
516 	__isl_take isl_basic_map *bmap)
517 {
518 	int i;
519 	isl_size n_div;
520 
521 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
522 	if (n_div < 0)
523 		return isl_basic_map_free(bmap);
524 	if (n_div == 0)
525 		return bmap;
526 	bmap = isl_basic_map_cow(bmap);
527 	bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
528 	if (!bmap)
529 		return NULL;
530 	for (i = 0; i < n_div; ++i) {
531 		if (isl_int_is_zero(bmap->div[i][0]))
532 			continue;
533 		bmap = isl_basic_map_add_div_constraints(bmap, i);
534 	}
535 
536 	return bmap;
537 }
538 
isl_basic_map_from_local_space(__isl_take isl_local_space * ls)539 __isl_give isl_basic_map *isl_basic_map_from_local_space(
540 	__isl_take isl_local_space *ls)
541 {
542 	int i;
543 	isl_size n_div;
544 	isl_basic_map *bmap;
545 
546 	n_div = isl_local_space_dim(ls, isl_dim_div);
547 	if (n_div < 0)
548 		ls = isl_local_space_free(ls);
549 	if (!ls)
550 		return NULL;
551 
552 	bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
553 					n_div, 0, 2 * n_div);
554 
555 	for (i = 0; i < n_div; ++i)
556 		if (isl_basic_map_alloc_div(bmap) < 0)
557 			goto error;
558 
559 	for (i = 0; i < n_div; ++i)
560 		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
561 	bmap = add_known_div_constraints(bmap);
562 
563 	isl_local_space_free(ls);
564 	return bmap;
565 error:
566 	isl_local_space_free(ls);
567 	isl_basic_map_free(bmap);
568 	return NULL;
569 }
570 
isl_basic_set_from_local_space(__isl_take isl_local_space * ls)571 __isl_give isl_basic_set *isl_basic_set_from_local_space(
572 	__isl_take isl_local_space *ls)
573 {
574 	return isl_basic_map_from_local_space(ls);
575 }
576 
isl_map_get_space(__isl_keep isl_map * map)577 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
578 {
579 	return isl_space_copy(isl_map_peek_space(map));
580 }
581 
isl_set_get_space(__isl_keep isl_set * set)582 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
583 {
584 	if (!set)
585 		return NULL;
586 	return isl_space_copy(set->dim);
587 }
588 
589 /* Return the space of "map".
590  * This may be either a copy or the space itself
591  * if there is only one reference to "map".
592  * This allows the space to be modified inplace
593  * if both the map and its space have only a single reference.
594  * The caller is not allowed to modify "map" between this call and
595  * a subsequent call to isl_map_restore_space.
596  * The only exception is that isl_map_free can be called instead.
597  */
isl_map_take_space(__isl_keep isl_map * map)598 static __isl_give isl_space *isl_map_take_space(__isl_keep isl_map *map)
599 {
600 	isl_space *space;
601 
602 	if (!map)
603 		return NULL;
604 	if (map->ref != 1)
605 		return isl_map_get_space(map);
606 	space = map->dim;
607 	map->dim = NULL;
608 	return space;
609 }
610 
611 /* Set the space of "map" to "space", where the space of "map" may be missing
612  * due to a preceding call to isl_map_take_space.
613  * However, in this case, "map" only has a single reference and
614  * then the call to isl_map_cow has no effect.
615  */
isl_map_restore_space(__isl_take isl_map * map,__isl_take isl_space * space)616 static __isl_give isl_map *isl_map_restore_space(__isl_take isl_map *map,
617 	__isl_take isl_space *space)
618 {
619 	if (!map || !space)
620 		goto error;
621 
622 	if (map->dim == space) {
623 		isl_space_free(space);
624 		return map;
625 	}
626 
627 	map = isl_map_cow(map);
628 	if (!map)
629 		goto error;
630 	isl_space_free(map->dim);
631 	map->dim = space;
632 
633 	return map;
634 error:
635 	isl_map_free(map);
636 	isl_space_free(space);
637 	return NULL;
638 }
639 
isl_basic_map_set_tuple_name(__isl_take isl_basic_map * bmap,enum isl_dim_type type,const char * s)640 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
641 	__isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
642 {
643 	isl_space *space;
644 
645 	space = isl_basic_map_take_space(bmap);
646 	space = isl_space_set_tuple_name(space, type, s);
647 	bmap = isl_basic_map_restore_space(bmap, space);
648 	bmap = isl_basic_map_finalize(bmap);
649 	return bmap;
650 }
651 
isl_basic_set_set_tuple_name(__isl_take isl_basic_set * bset,const char * s)652 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
653 	__isl_take isl_basic_set *bset, const char *s)
654 {
655 	return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
656 }
657 
isl_basic_map_get_tuple_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)658 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
659 	enum isl_dim_type type)
660 {
661 	return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
662 }
663 
isl_map_set_tuple_name(__isl_take isl_map * map,enum isl_dim_type type,const char * s)664 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
665 	enum isl_dim_type type, const char *s)
666 {
667 	int i;
668 	isl_space *space;
669 
670 	map = isl_map_cow(map);
671 	if (!map)
672 		return NULL;
673 
674 	for (i = 0; i < map->n; ++i) {
675 		map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
676 		if (!map->p[i])
677 			goto error;
678 	}
679 
680 	space = isl_map_take_space(map);
681 	space = isl_space_set_tuple_name(space, type, s);
682 	map = isl_map_restore_space(map, space);
683 
684 	return map;
685 error:
686 	isl_map_free(map);
687 	return NULL;
688 }
689 
690 /* Replace the identifier of the tuple of type "type" by "id".
691  */
isl_basic_map_set_tuple_id(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_id * id)692 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
693 	__isl_take isl_basic_map *bmap,
694 	enum isl_dim_type type, __isl_take isl_id *id)
695 {
696 	isl_space *space;
697 
698 	space = isl_basic_map_take_space(bmap);
699 	space = isl_space_set_tuple_id(space, type, id);
700 	bmap = isl_basic_map_restore_space(bmap, space);
701 	bmap = isl_basic_map_finalize(bmap);
702 	return bmap;
703 }
704 
705 /* Replace the identifier of the tuple by "id".
706  */
isl_basic_set_set_tuple_id(__isl_take isl_basic_set * bset,__isl_take isl_id * id)707 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
708 	__isl_take isl_basic_set *bset, __isl_take isl_id *id)
709 {
710 	return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
711 }
712 
713 /* Does the input or output tuple have a name?
714  */
isl_map_has_tuple_name(__isl_keep isl_map * map,enum isl_dim_type type)715 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
716 {
717 	return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
718 }
719 
isl_map_get_tuple_name(__isl_keep isl_map * map,enum isl_dim_type type)720 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
721 	enum isl_dim_type type)
722 {
723 	return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
724 }
725 
isl_set_set_tuple_name(__isl_take isl_set * set,const char * s)726 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
727 	const char *s)
728 {
729 	return set_from_map(isl_map_set_tuple_name(set_to_map(set),
730 						isl_dim_set, s));
731 }
732 
isl_map_set_tuple_id(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_id * id)733 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
734 	enum isl_dim_type type, __isl_take isl_id *id)
735 {
736 	isl_space *space;
737 
738 	space = isl_map_take_space(map);
739 	space = isl_space_set_tuple_id(space, type, id);
740 	map = isl_map_restore_space(map, space);
741 
742 	return isl_map_reset_space(map, isl_map_get_space(map));
743 }
744 
isl_set_set_tuple_id(__isl_take isl_set * set,__isl_take isl_id * id)745 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
746 	__isl_take isl_id *id)
747 {
748 	return isl_map_set_tuple_id(set, isl_dim_set, id);
749 }
750 
isl_map_reset_tuple_id(__isl_take isl_map * map,enum isl_dim_type type)751 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
752 	enum isl_dim_type type)
753 {
754 	isl_space *space;
755 
756 	space = isl_map_take_space(map);
757 	space = isl_space_reset_tuple_id(space, type);
758 	map = isl_map_restore_space(map, space);
759 
760 	return isl_map_reset_space(map, isl_map_get_space(map));
761 }
762 
isl_set_reset_tuple_id(__isl_take isl_set * set)763 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
764 {
765 	return isl_map_reset_tuple_id(set, isl_dim_set);
766 }
767 
isl_map_has_tuple_id(__isl_keep isl_map * map,enum isl_dim_type type)768 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
769 {
770 	return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
771 }
772 
isl_map_get_tuple_id(__isl_keep isl_map * map,enum isl_dim_type type)773 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
774 	enum isl_dim_type type)
775 {
776 	return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
777 }
778 
isl_set_has_tuple_id(__isl_keep isl_set * set)779 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
780 {
781 	return isl_map_has_tuple_id(set, isl_dim_set);
782 }
783 
isl_set_get_tuple_id(__isl_keep isl_set * set)784 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
785 {
786 	return isl_map_get_tuple_id(set, isl_dim_set);
787 }
788 
789 /* Does the set tuple have a name?
790  */
isl_set_has_tuple_name(__isl_keep isl_set * set)791 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
792 {
793 	if (!set)
794 		return isl_bool_error;
795 	return isl_space_has_tuple_name(set->dim, isl_dim_set);
796 }
797 
798 
isl_basic_set_get_tuple_name(__isl_keep isl_basic_set * bset)799 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
800 {
801 	return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
802 }
803 
isl_set_get_tuple_name(__isl_keep isl_set * set)804 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
805 {
806 	return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
807 }
808 
isl_basic_map_get_dim_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)809 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
810 	enum isl_dim_type type, unsigned pos)
811 {
812 	return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
813 }
814 
isl_basic_set_get_dim_name(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned pos)815 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
816 	enum isl_dim_type type, unsigned pos)
817 {
818 	return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
819 }
820 
821 /* Does the given dimension have a name?
822  */
isl_map_has_dim_name(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)823 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
824 	enum isl_dim_type type, unsigned pos)
825 {
826 	if (!map)
827 		return isl_bool_error;
828 	return isl_space_has_dim_name(map->dim, type, pos);
829 }
830 
isl_map_get_dim_name(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)831 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
832 	enum isl_dim_type type, unsigned pos)
833 {
834 	return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
835 }
836 
isl_set_get_dim_name(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)837 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
838 	enum isl_dim_type type, unsigned pos)
839 {
840 	return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
841 }
842 
843 /* Does the given dimension have a name?
844  */
isl_set_has_dim_name(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)845 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
846 	enum isl_dim_type type, unsigned pos)
847 {
848 	if (!set)
849 		return isl_bool_error;
850 	return isl_space_has_dim_name(set->dim, type, pos);
851 }
852 
isl_basic_map_set_dim_name(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,const char * s)853 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
854 	__isl_take isl_basic_map *bmap,
855 	enum isl_dim_type type, unsigned pos, const char *s)
856 {
857 	isl_space *space;
858 
859 	space = isl_basic_map_take_space(bmap);
860 	space = isl_space_set_dim_name(space, type, pos, s);
861 	bmap = isl_basic_map_restore_space(bmap, space);
862 	return isl_basic_map_finalize(bmap);
863 }
864 
isl_map_set_dim_name(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,const char * s)865 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
866 	enum isl_dim_type type, unsigned pos, const char *s)
867 {
868 	int i;
869 	isl_space *space;
870 
871 	map = isl_map_cow(map);
872 	if (!map)
873 		return NULL;
874 
875 	for (i = 0; i < map->n; ++i) {
876 		map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
877 		if (!map->p[i])
878 			goto error;
879 	}
880 
881 	space = isl_map_take_space(map);
882 	space = isl_space_set_dim_name(space, type, pos, s);
883 	map = isl_map_restore_space(map, space);
884 
885 	return map;
886 error:
887 	isl_map_free(map);
888 	return NULL;
889 }
890 
isl_basic_set_set_dim_name(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,const char * s)891 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
892 	__isl_take isl_basic_set *bset,
893 	enum isl_dim_type type, unsigned pos, const char *s)
894 {
895 	return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
896 							type, pos, s));
897 }
898 
isl_set_set_dim_name(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,const char * s)899 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
900 	enum isl_dim_type type, unsigned pos, const char *s)
901 {
902 	return set_from_map(isl_map_set_dim_name(set_to_map(set),
903 							type, pos, s));
904 }
905 
isl_basic_map_has_dim_id(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)906 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
907 	enum isl_dim_type type, unsigned pos)
908 {
909 	if (!bmap)
910 		return isl_bool_error;
911 	return isl_space_has_dim_id(bmap->dim, type, pos);
912 }
913 
isl_basic_set_get_dim_id(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned pos)914 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
915 	enum isl_dim_type type, unsigned pos)
916 {
917 	return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
918 }
919 
isl_map_has_dim_id(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)920 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
921 	enum isl_dim_type type, unsigned pos)
922 {
923 	return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
924 }
925 
isl_map_get_dim_id(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)926 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
927 	enum isl_dim_type type, unsigned pos)
928 {
929 	return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
930 }
931 
isl_set_has_dim_id(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)932 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
933 	enum isl_dim_type type, unsigned pos)
934 {
935 	return isl_map_has_dim_id(set, type, pos);
936 }
937 
isl_set_get_dim_id(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)938 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
939 	enum isl_dim_type type, unsigned pos)
940 {
941 	return isl_map_get_dim_id(set, type, pos);
942 }
943 
isl_map_set_dim_id(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_id * id)944 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
945 	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
946 {
947 	isl_space *space;
948 
949 	space = isl_map_take_space(map);
950 	space = isl_space_set_dim_id(space, type, pos, id);
951 	map = isl_map_restore_space(map, space);
952 
953 	return isl_map_reset_space(map, isl_map_get_space(map));
954 }
955 
isl_set_set_dim_id(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_id * id)956 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
957 	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
958 {
959 	return isl_map_set_dim_id(set, type, pos, id);
960 }
961 
isl_map_find_dim_by_id(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_id * id)962 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
963 	__isl_keep isl_id *id)
964 {
965 	if (!map)
966 		return -1;
967 	return isl_space_find_dim_by_id(map->dim, type, id);
968 }
969 
isl_set_find_dim_by_id(__isl_keep isl_set * set,enum isl_dim_type type,__isl_keep isl_id * id)970 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
971 	__isl_keep isl_id *id)
972 {
973 	return isl_map_find_dim_by_id(set, type, id);
974 }
975 
976 /* Return the position of the dimension of the given type and name
977  * in "bmap".
978  * Return -1 if no such dimension can be found.
979  */
isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,const char * name)980 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
981 	enum isl_dim_type type, const char *name)
982 {
983 	if (!bmap)
984 		return -1;
985 	return isl_space_find_dim_by_name(bmap->dim, type, name);
986 }
987 
isl_map_find_dim_by_name(__isl_keep isl_map * map,enum isl_dim_type type,const char * name)988 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
989 	const char *name)
990 {
991 	if (!map)
992 		return -1;
993 	return isl_space_find_dim_by_name(map->dim, type, name);
994 }
995 
isl_set_find_dim_by_name(__isl_keep isl_set * set,enum isl_dim_type type,const char * name)996 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
997 	const char *name)
998 {
999 	return isl_map_find_dim_by_name(set, type, name);
1000 }
1001 
1002 /* Check whether equality i of bset is a pure stride constraint
1003  * on a single dimension, i.e., of the form
1004  *
1005  *	v = k e
1006  *
1007  * with k a constant and e an existentially quantified variable.
1008  */
isl_basic_set_eq_is_stride(__isl_keep isl_basic_set * bset,int i)1009 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
1010 {
1011 	isl_size nparam;
1012 	isl_size d;
1013 	isl_size n_div;
1014 	int pos1;
1015 	int pos2;
1016 
1017 	nparam = isl_basic_set_dim(bset, isl_dim_param);
1018 	d = isl_basic_set_dim(bset, isl_dim_set);
1019 	n_div = isl_basic_set_dim(bset, isl_dim_div);
1020 	if (nparam < 0 || d < 0 || n_div < 0)
1021 		return isl_bool_error;
1022 
1023 	if (!isl_int_is_zero(bset->eq[i][0]))
1024 		return isl_bool_false;
1025 
1026 	if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
1027 		return isl_bool_false;
1028 	pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
1029 	if (pos1 == -1)
1030 		return isl_bool_false;
1031 	if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
1032 					d - pos1 - 1) != -1)
1033 		return isl_bool_false;
1034 
1035 	pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
1036 	if (pos2 == -1)
1037 		return isl_bool_false;
1038 	if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d  + pos2 + 1,
1039 				   n_div - pos2 - 1) != -1)
1040 		return isl_bool_false;
1041 	if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
1042 	    !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
1043 		return isl_bool_false;
1044 
1045 	return isl_bool_true;
1046 }
1047 
1048 /* Reset the user pointer on all identifiers of parameters and tuples
1049  * of the space of "map".
1050  */
isl_map_reset_user(__isl_take isl_map * map)1051 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
1052 {
1053 	isl_space *space;
1054 
1055 	space = isl_map_get_space(map);
1056 	space = isl_space_reset_user(space);
1057 	map = isl_map_reset_space(map, space);
1058 
1059 	return map;
1060 }
1061 
1062 /* Reset the user pointer on all identifiers of parameters and tuples
1063  * of the space of "set".
1064  */
isl_set_reset_user(__isl_take isl_set * set)1065 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
1066 {
1067 	return isl_map_reset_user(set);
1068 }
1069 
isl_basic_map_is_rational(__isl_keep isl_basic_map * bmap)1070 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
1071 {
1072 	if (!bmap)
1073 		return isl_bool_error;
1074 	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
1075 }
1076 
1077 /* Has "map" been marked as a rational map?
1078  * In particular, have all basic maps in "map" been marked this way?
1079  * An empty map is not considered to be rational.
1080  * Maps where only some of the basic maps are marked rational
1081  * are not allowed.
1082  */
isl_map_is_rational(__isl_keep isl_map * map)1083 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
1084 {
1085 	int i;
1086 	isl_bool rational;
1087 
1088 	if (!map)
1089 		return isl_bool_error;
1090 	if (map->n == 0)
1091 		return isl_bool_false;
1092 	rational = isl_basic_map_is_rational(map->p[0]);
1093 	if (rational < 0)
1094 		return rational;
1095 	for (i = 1; i < map->n; ++i) {
1096 		isl_bool rational_i;
1097 
1098 		rational_i = isl_basic_map_is_rational(map->p[i]);
1099 		if (rational_i < 0)
1100 			return rational_i;
1101 		if (rational != rational_i)
1102 			isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1103 				"mixed rational and integer basic maps "
1104 				"not supported", return isl_bool_error);
1105 	}
1106 
1107 	return rational;
1108 }
1109 
1110 /* Has "set" been marked as a rational set?
1111  * In particular, have all basic set in "set" been marked this way?
1112  * An empty set is not considered to be rational.
1113  * Sets where only some of the basic sets are marked rational
1114  * are not allowed.
1115  */
isl_set_is_rational(__isl_keep isl_set * set)1116 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1117 {
1118 	return isl_map_is_rational(set);
1119 }
1120 
isl_basic_set_is_rational(__isl_keep isl_basic_set * bset)1121 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1122 {
1123 	return isl_basic_map_is_rational(bset);
1124 }
1125 
1126 /* Does "bmap" contain any rational points?
1127  *
1128  * If "bmap" has an equality for each dimension, equating the dimension
1129  * to an integer constant, then it has no rational points, even if it
1130  * is marked as rational.
1131  */
isl_basic_map_has_rational(__isl_keep isl_basic_map * bmap)1132 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1133 {
1134 	isl_bool has_rational = isl_bool_true;
1135 	isl_size total;
1136 
1137 	if (!bmap)
1138 		return isl_bool_error;
1139 	if (isl_basic_map_plain_is_empty(bmap))
1140 		return isl_bool_false;
1141 	if (!isl_basic_map_is_rational(bmap))
1142 		return isl_bool_false;
1143 	bmap = isl_basic_map_copy(bmap);
1144 	bmap = isl_basic_map_implicit_equalities(bmap);
1145 	total = isl_basic_map_dim(bmap, isl_dim_all);
1146 	if (total < 0)
1147 		return isl_bool_error;
1148 	if (bmap->n_eq == total) {
1149 		int i, j;
1150 		for (i = 0; i < bmap->n_eq; ++i) {
1151 			j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1152 			if (j < 0)
1153 				break;
1154 			if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1155 			    !isl_int_is_negone(bmap->eq[i][1 + j]))
1156 				break;
1157 			j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1158 						    total - j - 1);
1159 			if (j >= 0)
1160 				break;
1161 		}
1162 		if (i == bmap->n_eq)
1163 			has_rational = isl_bool_false;
1164 	}
1165 	isl_basic_map_free(bmap);
1166 
1167 	return has_rational;
1168 }
1169 
1170 /* Does "map" contain any rational points?
1171  */
isl_map_has_rational(__isl_keep isl_map * map)1172 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1173 {
1174 	int i;
1175 	isl_bool has_rational;
1176 
1177 	if (!map)
1178 		return isl_bool_error;
1179 	for (i = 0; i < map->n; ++i) {
1180 		has_rational = isl_basic_map_has_rational(map->p[i]);
1181 		if (has_rational < 0 || has_rational)
1182 			return has_rational;
1183 	}
1184 	return isl_bool_false;
1185 }
1186 
1187 /* Does "set" contain any rational points?
1188  */
isl_set_has_rational(__isl_keep isl_set * set)1189 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1190 {
1191 	return isl_map_has_rational(set);
1192 }
1193 
1194 /* Is this basic set a parameter domain?
1195  */
isl_basic_set_is_params(__isl_keep isl_basic_set * bset)1196 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1197 {
1198 	if (!bset)
1199 		return isl_bool_error;
1200 	return isl_space_is_params(bset->dim);
1201 }
1202 
1203 /* Is this set a parameter domain?
1204  */
isl_set_is_params(__isl_keep isl_set * set)1205 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1206 {
1207 	if (!set)
1208 		return isl_bool_error;
1209 	return isl_space_is_params(set->dim);
1210 }
1211 
1212 /* Is this map actually a parameter domain?
1213  * Users should never call this function.  Outside of isl,
1214  * a map can never be a parameter domain.
1215  */
isl_map_is_params(__isl_keep isl_map * map)1216 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1217 {
1218 	if (!map)
1219 		return isl_bool_error;
1220 	return isl_space_is_params(map->dim);
1221 }
1222 
basic_map_init(isl_ctx * ctx,__isl_take isl_basic_map * bmap,unsigned extra,unsigned n_eq,unsigned n_ineq)1223 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1224 	__isl_take isl_basic_map *bmap, unsigned extra,
1225 	unsigned n_eq, unsigned n_ineq)
1226 {
1227 	int i;
1228 	isl_space *space = isl_basic_map_peek_space(bmap);
1229 	isl_size n_var = isl_space_dim(space, isl_dim_all);
1230 	size_t row_size = 1 + n_var + extra;
1231 
1232 	bmap->ctx = ctx;
1233 	isl_ctx_ref(ctx);
1234 
1235 	if (n_var < 0)
1236 		return isl_basic_map_free(bmap);
1237 
1238 	bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1239 	if (isl_blk_is_error(bmap->block))
1240 		goto error;
1241 
1242 	bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1243 	if ((n_ineq + n_eq) && !bmap->ineq)
1244 		goto error;
1245 
1246 	if (extra == 0) {
1247 		bmap->block2 = isl_blk_empty();
1248 		bmap->div = NULL;
1249 	} else {
1250 		bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1251 		if (isl_blk_is_error(bmap->block2))
1252 			goto error;
1253 
1254 		bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1255 		if (!bmap->div)
1256 			goto error;
1257 	}
1258 
1259 	for (i = 0; i < n_ineq + n_eq; ++i)
1260 		bmap->ineq[i] = bmap->block.data + i * row_size;
1261 
1262 	for (i = 0; i < extra; ++i)
1263 		bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1264 
1265 	bmap->ref = 1;
1266 	bmap->flags = 0;
1267 	bmap->c_size = n_eq + n_ineq;
1268 	bmap->eq = bmap->ineq + n_ineq;
1269 	bmap->extra = extra;
1270 	bmap->n_eq = 0;
1271 	bmap->n_ineq = 0;
1272 	bmap->n_div = 0;
1273 	bmap->sample = NULL;
1274 
1275 	return bmap;
1276 error:
1277 	isl_basic_map_free(bmap);
1278 	return NULL;
1279 }
1280 
isl_basic_set_alloc(isl_ctx * ctx,unsigned nparam,unsigned dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1281 __isl_give isl_basic_set *isl_basic_set_alloc(isl_ctx *ctx,
1282 		unsigned nparam, unsigned dim, unsigned extra,
1283 		unsigned n_eq, unsigned n_ineq)
1284 {
1285 	struct isl_basic_map *bmap;
1286 	isl_space *space;
1287 
1288 	space = isl_space_set_alloc(ctx, nparam, dim);
1289 	if (!space)
1290 		return NULL;
1291 
1292 	bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1293 	return bset_from_bmap(bmap);
1294 }
1295 
isl_basic_set_alloc_space(__isl_take isl_space * space,unsigned extra,unsigned n_eq,unsigned n_ineq)1296 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *space,
1297 		unsigned extra, unsigned n_eq, unsigned n_ineq)
1298 {
1299 	struct isl_basic_map *bmap;
1300 	if (!space)
1301 		return NULL;
1302 	isl_assert(space->ctx, space->n_in == 0, goto error);
1303 	bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1304 	return bset_from_bmap(bmap);
1305 error:
1306 	isl_space_free(space);
1307 	return NULL;
1308 }
1309 
isl_basic_map_alloc_space(__isl_take isl_space * space,unsigned extra,unsigned n_eq,unsigned n_ineq)1310 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1311 		unsigned extra, unsigned n_eq, unsigned n_ineq)
1312 {
1313 	struct isl_basic_map *bmap;
1314 
1315 	if (!space)
1316 		return NULL;
1317 	bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1318 	if (!bmap)
1319 		goto error;
1320 	bmap->dim = space;
1321 
1322 	return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1323 error:
1324 	isl_space_free(space);
1325 	return NULL;
1326 }
1327 
isl_basic_map_alloc(isl_ctx * ctx,unsigned nparam,unsigned in,unsigned out,unsigned extra,unsigned n_eq,unsigned n_ineq)1328 __isl_give isl_basic_map *isl_basic_map_alloc(isl_ctx *ctx,
1329 		unsigned nparam, unsigned in, unsigned out, unsigned extra,
1330 		unsigned n_eq, unsigned n_ineq)
1331 {
1332 	struct isl_basic_map *bmap;
1333 	isl_space *space;
1334 
1335 	space = isl_space_alloc(ctx, nparam, in, out);
1336 	if (!space)
1337 		return NULL;
1338 
1339 	bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1340 	return bmap;
1341 }
1342 
dup_constraints(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)1343 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1344 	__isl_keep isl_basic_map *src)
1345 {
1346 	int i;
1347 	isl_size total = isl_basic_map_dim(src, isl_dim_all);
1348 
1349 	if (!dst || total < 0)
1350 		return isl_basic_map_free(dst);
1351 
1352 	for (i = 0; i < src->n_eq; ++i) {
1353 		int j = isl_basic_map_alloc_equality(dst);
1354 		if (j < 0)
1355 			return isl_basic_map_free(dst);
1356 		isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1357 	}
1358 
1359 	for (i = 0; i < src->n_ineq; ++i) {
1360 		int j = isl_basic_map_alloc_inequality(dst);
1361 		if (j < 0)
1362 			return isl_basic_map_free(dst);
1363 		isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1364 	}
1365 
1366 	for (i = 0; i < src->n_div; ++i) {
1367 		int j = isl_basic_map_alloc_div(dst);
1368 		if (j < 0)
1369 			return isl_basic_map_free(dst);
1370 		isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1371 	}
1372 	ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1373 	return dst;
1374 }
1375 
isl_basic_map_dup(__isl_keep isl_basic_map * bmap)1376 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1377 {
1378 	struct isl_basic_map *dup;
1379 
1380 	if (!bmap)
1381 		return NULL;
1382 	dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1383 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
1384 	dup = dup_constraints(dup, bmap);
1385 	if (!dup)
1386 		return NULL;
1387 	dup->flags = bmap->flags;
1388 	dup->sample = isl_vec_copy(bmap->sample);
1389 	return dup;
1390 }
1391 
isl_basic_set_dup(__isl_keep isl_basic_set * bset)1392 __isl_give isl_basic_set *isl_basic_set_dup(__isl_keep isl_basic_set *bset)
1393 {
1394 	struct isl_basic_map *dup;
1395 
1396 	dup = isl_basic_map_dup(bset_to_bmap(bset));
1397 	return bset_from_bmap(dup);
1398 }
1399 
isl_basic_set_copy(__isl_keep isl_basic_set * bset)1400 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1401 {
1402 	if (!bset)
1403 		return NULL;
1404 
1405 	if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1406 		bset->ref++;
1407 		return bset;
1408 	}
1409 	return isl_basic_set_dup(bset);
1410 }
1411 
isl_set_copy(__isl_keep isl_set * set)1412 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1413 {
1414 	if (!set)
1415 		return NULL;
1416 
1417 	set->ref++;
1418 	return set;
1419 }
1420 
isl_basic_map_copy(__isl_keep isl_basic_map * bmap)1421 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1422 {
1423 	if (!bmap)
1424 		return NULL;
1425 
1426 	if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1427 		bmap->ref++;
1428 		return bmap;
1429 	}
1430 	bmap = isl_basic_map_dup(bmap);
1431 	if (bmap)
1432 		ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1433 	return bmap;
1434 }
1435 
isl_map_copy(__isl_keep isl_map * map)1436 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1437 {
1438 	if (!map)
1439 		return NULL;
1440 
1441 	map->ref++;
1442 	return map;
1443 }
1444 
isl_basic_map_free(__isl_take isl_basic_map * bmap)1445 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1446 {
1447 	if (!bmap)
1448 		return NULL;
1449 
1450 	if (--bmap->ref > 0)
1451 		return NULL;
1452 
1453 	isl_ctx_deref(bmap->ctx);
1454 	free(bmap->div);
1455 	isl_blk_free(bmap->ctx, bmap->block2);
1456 	free(bmap->ineq);
1457 	isl_blk_free(bmap->ctx, bmap->block);
1458 	isl_vec_free(bmap->sample);
1459 	isl_space_free(bmap->dim);
1460 	free(bmap);
1461 
1462 	return NULL;
1463 }
1464 
isl_basic_set_free(__isl_take isl_basic_set * bset)1465 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1466 {
1467 	return isl_basic_map_free(bset_to_bmap(bset));
1468 }
1469 
room_for_con(__isl_keep isl_basic_map * bmap,unsigned n)1470 static int room_for_con(__isl_keep isl_basic_map *bmap, unsigned n)
1471 {
1472 	return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1473 }
1474 
1475 /* Check that "bset" does not involve any parameters.
1476  */
isl_basic_set_check_no_params(__isl_keep isl_basic_set * bset)1477 isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1478 {
1479 	isl_size nparam;
1480 
1481 	nparam = isl_basic_set_dim(bset, isl_dim_param);
1482 	if (nparam < 0)
1483 		return isl_stat_error;
1484 	if (nparam != 0)
1485 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1486 			"basic set should not have any parameters",
1487 			return isl_stat_error);
1488 	return isl_stat_ok;
1489 }
1490 
1491 /* Check that "bset" does not involve any local variables.
1492  */
isl_basic_set_check_no_locals(__isl_keep isl_basic_set * bset)1493 isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1494 {
1495 	isl_size n_div;
1496 
1497 	n_div = isl_basic_set_dim(bset, isl_dim_div);
1498 	if (n_div < 0)
1499 		return isl_stat_error;
1500 	if (n_div != 0)
1501 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1502 			"basic set should not have any local variables",
1503 			return isl_stat_error);
1504 	return isl_stat_ok;
1505 }
1506 
1507 #undef TYPE
1508 #define TYPE isl_map
1509 
1510 #include "isl_check_named_params_templ.c"
1511 
1512 #undef TYPE
1513 #define TYPE isl_basic_map
1514 
1515 static
1516 #include "isl_check_named_params_templ.c"
1517 
1518 /* Check that "bmap1" and "bmap2" have the same parameters,
1519  * reporting an error if they do not.
1520  */
isl_basic_map_check_equal_params(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)1521 static isl_stat isl_basic_map_check_equal_params(
1522 	__isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1523 {
1524 	isl_bool match;
1525 
1526 	match = isl_basic_map_has_equal_params(bmap1, bmap2);
1527 	if (match < 0)
1528 		return isl_stat_error;
1529 	if (!match)
1530 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1531 			"parameters don't match", return isl_stat_error);
1532 	return isl_stat_ok;
1533 }
1534 
1535 #undef TYPE
1536 #define TYPE	isl_map
1537 
1538 #include "isl_align_params_bin_templ.c"
1539 
1540 #undef SUFFIX
1541 #define SUFFIX	set
1542 #undef ARG1
1543 #define ARG1	isl_map
1544 #undef ARG2
1545 #define ARG2	isl_set
1546 
1547 #include "isl_align_params_templ.c"
1548 
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))1549 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1550 	__isl_keep isl_map *map2,
1551 	isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1552 {
1553 	isl_bool r;
1554 
1555 	if (!map1 || !map2)
1556 		return isl_bool_error;
1557 	if (isl_map_has_equal_params(map1, map2))
1558 		return fn(map1, map2);
1559 	if (isl_map_check_named_params(map1) < 0)
1560 		return isl_bool_error;
1561 	if (isl_map_check_named_params(map2) < 0)
1562 		return isl_bool_error;
1563 	map1 = isl_map_copy(map1);
1564 	map2 = isl_map_copy(map2);
1565 	map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1566 	map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1567 	r = fn(map1, map2);
1568 	isl_map_free(map1);
1569 	isl_map_free(map2);
1570 	return r;
1571 }
1572 
isl_basic_map_alloc_equality(__isl_keep isl_basic_map * bmap)1573 int isl_basic_map_alloc_equality(__isl_keep isl_basic_map *bmap)
1574 {
1575 	isl_size total;
1576 	struct isl_ctx *ctx;
1577 
1578 	total = isl_basic_map_dim(bmap, isl_dim_all);
1579 	if (total < 0)
1580 		return -1;
1581 	ctx = bmap->ctx;
1582 	isl_assert(ctx, room_for_con(bmap, 1), return -1);
1583 	isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1584 			return -1);
1585 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1586 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1587 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1588 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1589 	if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1590 		isl_int *t;
1591 		int j = isl_basic_map_alloc_inequality(bmap);
1592 		if (j < 0)
1593 			return -1;
1594 		t = bmap->ineq[j];
1595 		bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1596 		bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1597 		bmap->eq[-1] = t;
1598 		bmap->n_eq++;
1599 		bmap->n_ineq--;
1600 		bmap->eq--;
1601 		return 0;
1602 	}
1603 	isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + total,
1604 		      bmap->extra - bmap->n_div);
1605 	return bmap->n_eq++;
1606 }
1607 
isl_basic_set_alloc_equality(__isl_keep isl_basic_set * bset)1608 int isl_basic_set_alloc_equality(__isl_keep isl_basic_set *bset)
1609 {
1610 	return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1611 }
1612 
isl_basic_map_free_equality(__isl_take isl_basic_map * bmap,unsigned n)1613 __isl_give isl_basic_map *isl_basic_map_free_equality(
1614 	__isl_take isl_basic_map *bmap, unsigned n)
1615 {
1616 	if (!bmap)
1617 		return NULL;
1618 	if (n > bmap->n_eq)
1619 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1620 			"invalid number of equalities",
1621 			isl_basic_map_free(bmap));
1622 	bmap->n_eq -= n;
1623 	return bmap;
1624 }
1625 
isl_basic_set_free_equality(__isl_take isl_basic_set * bset,unsigned n)1626 __isl_give isl_basic_set *isl_basic_set_free_equality(
1627 	__isl_take isl_basic_set *bset, unsigned n)
1628 {
1629 	return bset_from_bmap(isl_basic_map_free_equality(bset_to_bmap(bset),
1630 							    n));
1631 }
1632 
1633 /* Drop the equality constraint at position "pos",
1634  * preserving the order of the other equality constraints.
1635  */
isl_basic_map_drop_equality(__isl_keep isl_basic_map * bmap,unsigned pos)1636 int isl_basic_map_drop_equality(__isl_keep isl_basic_map *bmap, unsigned pos)
1637 {
1638 	isl_int *t;
1639 	int r;
1640 
1641 	if (!bmap)
1642 		return -1;
1643 	isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1644 
1645 	t = bmap->eq[pos];
1646 	bmap->n_eq--;
1647 	for (r = pos; r < bmap->n_eq; ++r)
1648 		bmap->eq[r] = bmap->eq[r + 1];
1649 	bmap->eq[bmap->n_eq] = t;
1650 
1651 	return 0;
1652 }
1653 
1654 /* Turn inequality "pos" of "bmap" into an equality.
1655  *
1656  * In particular, we move the inequality in front of the equalities
1657  * and move the last inequality in the position of the moved inequality.
1658  * Note that isl_tab_make_equalities_explicit depends on this particular
1659  * change in the ordering of the constraints.
1660  */
isl_basic_map_inequality_to_equality(__isl_keep isl_basic_map * bmap,unsigned pos)1661 void isl_basic_map_inequality_to_equality(
1662 		__isl_keep isl_basic_map *bmap, unsigned pos)
1663 {
1664 	isl_int *t;
1665 
1666 	t = bmap->ineq[pos];
1667 	bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1668 	bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1669 	bmap->eq[-1] = t;
1670 	bmap->n_eq++;
1671 	bmap->n_ineq--;
1672 	bmap->eq--;
1673 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1674 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1675 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1676 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1677 }
1678 
room_for_ineq(__isl_keep isl_basic_map * bmap,unsigned n)1679 static int room_for_ineq(__isl_keep isl_basic_map *bmap, unsigned n)
1680 {
1681 	return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1682 }
1683 
isl_basic_map_alloc_inequality(__isl_keep isl_basic_map * bmap)1684 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1685 {
1686 	isl_size total;
1687 	struct isl_ctx *ctx;
1688 
1689 	total = isl_basic_map_dim(bmap, isl_dim_all);
1690 	if (total < 0)
1691 		return -1;
1692 	ctx = bmap->ctx;
1693 	isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1694 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1695 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1696 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1697 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1698 	isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1 + total,
1699 		      bmap->extra - bmap->n_div);
1700 	return bmap->n_ineq++;
1701 }
1702 
isl_basic_set_alloc_inequality(__isl_keep isl_basic_set * bset)1703 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1704 {
1705 	return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1706 }
1707 
isl_basic_map_free_inequality(__isl_take isl_basic_map * bmap,unsigned n)1708 __isl_give isl_basic_map *isl_basic_map_free_inequality(
1709 	__isl_take isl_basic_map *bmap, unsigned n)
1710 {
1711 	if (!bmap)
1712 		return NULL;
1713 	if (n > bmap->n_ineq)
1714 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1715 			"invalid number of inequalities",
1716 			return isl_basic_map_free(bmap));
1717 	bmap->n_ineq -= n;
1718 	return bmap;
1719 }
1720 
isl_basic_set_free_inequality(__isl_take isl_basic_set * bset,unsigned n)1721 __isl_give isl_basic_set *isl_basic_set_free_inequality(
1722 	__isl_take isl_basic_set *bset, unsigned n)
1723 {
1724 	return bset_from_bmap(isl_basic_map_free_inequality(bset_to_bmap(bset),
1725 							    n));
1726 }
1727 
isl_basic_map_drop_inequality(__isl_keep isl_basic_map * bmap,unsigned pos)1728 int isl_basic_map_drop_inequality(__isl_keep isl_basic_map *bmap, unsigned pos)
1729 {
1730 	isl_int *t;
1731 	if (!bmap)
1732 		return -1;
1733 	isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1734 
1735 	if (pos != bmap->n_ineq - 1) {
1736 		t = bmap->ineq[pos];
1737 		bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1738 		bmap->ineq[bmap->n_ineq - 1] = t;
1739 		ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1740 	}
1741 	bmap->n_ineq--;
1742 	return 0;
1743 }
1744 
isl_basic_set_drop_inequality(__isl_keep isl_basic_set * bset,unsigned pos)1745 int isl_basic_set_drop_inequality(__isl_keep isl_basic_set *bset, unsigned pos)
1746 {
1747 	return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1748 }
1749 
isl_basic_map_add_eq(__isl_take isl_basic_map * bmap,isl_int * eq)1750 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1751 	isl_int *eq)
1752 {
1753 	isl_bool empty;
1754 	isl_size total;
1755 	int k;
1756 
1757 	empty = isl_basic_map_plain_is_empty(bmap);
1758 	if (empty < 0)
1759 		return isl_basic_map_free(bmap);
1760 	if (empty)
1761 		return bmap;
1762 
1763 	bmap = isl_basic_map_cow(bmap);
1764 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1765 	total = isl_basic_map_dim(bmap, isl_dim_all);
1766 	if (total < 0)
1767 		return isl_basic_map_free(bmap);
1768 	k = isl_basic_map_alloc_equality(bmap);
1769 	if (k < 0)
1770 		goto error;
1771 	isl_seq_cpy(bmap->eq[k], eq, 1 + total);
1772 	return bmap;
1773 error:
1774 	isl_basic_map_free(bmap);
1775 	return NULL;
1776 }
1777 
isl_basic_set_add_eq(__isl_take isl_basic_set * bset,isl_int * eq)1778 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1779 	isl_int *eq)
1780 {
1781 	return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1782 }
1783 
isl_basic_map_add_ineq(__isl_take isl_basic_map * bmap,isl_int * ineq)1784 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1785 	isl_int *ineq)
1786 {
1787 	isl_size total;
1788 	int k;
1789 
1790 	bmap = isl_basic_map_cow(bmap);
1791 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1792 	total = isl_basic_map_dim(bmap, isl_dim_all);
1793 	if (total < 0)
1794 		return isl_basic_map_free(bmap);
1795 	k = isl_basic_map_alloc_inequality(bmap);
1796 	if (k < 0)
1797 		goto error;
1798 	isl_seq_cpy(bmap->ineq[k], ineq, 1 + total);
1799 	return bmap;
1800 error:
1801 	isl_basic_map_free(bmap);
1802 	return NULL;
1803 }
1804 
isl_basic_set_add_ineq(__isl_take isl_basic_set * bset,isl_int * ineq)1805 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1806 	isl_int *ineq)
1807 {
1808 	return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1809 }
1810 
isl_basic_map_alloc_div(__isl_keep isl_basic_map * bmap)1811 int isl_basic_map_alloc_div(__isl_keep isl_basic_map *bmap)
1812 {
1813 	isl_size total;
1814 
1815 	total = isl_basic_map_dim(bmap, isl_dim_all);
1816 	if (total < 0)
1817 		return -1;
1818 	isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1819 	isl_seq_clr(bmap->div[bmap->n_div] + 1 + 1 + total,
1820 		      bmap->extra - bmap->n_div);
1821 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1822 	return bmap->n_div++;
1823 }
1824 
isl_basic_set_alloc_div(__isl_keep isl_basic_set * bset)1825 int isl_basic_set_alloc_div(__isl_keep isl_basic_set *bset)
1826 {
1827 	return isl_basic_map_alloc_div(bset_to_bmap(bset));
1828 }
1829 
1830 #undef TYPE
1831 #define TYPE	isl_basic_map
1832 #include "check_type_range_templ.c"
1833 
1834 /* Check that there are "n" dimensions of type "type" starting at "first"
1835  * in "bset".
1836  */
isl_basic_set_check_range(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)1837 isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1838 	enum isl_dim_type type, unsigned first, unsigned n)
1839 {
1840 	return isl_basic_map_check_range(bset_to_bmap(bset),
1841 					type, first, n);
1842 }
1843 
1844 /* Insert an extra integer division, prescribed by "div", to "bmap"
1845  * at (integer division) position "pos".
1846  *
1847  * The integer division is first added at the end and then moved
1848  * into the right position.
1849  */
isl_basic_map_insert_div(__isl_take isl_basic_map * bmap,int pos,__isl_keep isl_vec * div)1850 __isl_give isl_basic_map *isl_basic_map_insert_div(
1851 	__isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1852 {
1853 	int i, k;
1854 	isl_size total;
1855 
1856 	bmap = isl_basic_map_cow(bmap);
1857 	total = isl_basic_map_dim(bmap, isl_dim_all);
1858 	if (total < 0 || !div)
1859 		return isl_basic_map_free(bmap);
1860 
1861 	if (div->size != 1 + 1 + total)
1862 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1863 			"unexpected size", return isl_basic_map_free(bmap));
1864 	if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1865 		return isl_basic_map_free(bmap);
1866 
1867 	bmap = isl_basic_map_extend(bmap, 1, 0, 2);
1868 	k = isl_basic_map_alloc_div(bmap);
1869 	if (k < 0)
1870 		return isl_basic_map_free(bmap);
1871 	isl_seq_cpy(bmap->div[k], div->el, div->size);
1872 	isl_int_set_si(bmap->div[k][div->size], 0);
1873 
1874 	for (i = k; i > pos; --i)
1875 		bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1876 
1877 	return bmap;
1878 }
1879 
isl_basic_map_free_div(__isl_keep isl_basic_map * bmap,unsigned n)1880 isl_stat isl_basic_map_free_div(__isl_keep isl_basic_map *bmap, unsigned n)
1881 {
1882 	if (!bmap)
1883 		return isl_stat_error;
1884 	isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1885 	bmap->n_div -= n;
1886 	return isl_stat_ok;
1887 }
1888 
add_constraints(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2,unsigned i_pos,unsigned o_pos)1889 static __isl_give isl_basic_map *add_constraints(
1890 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1891 	unsigned i_pos, unsigned o_pos)
1892 {
1893 	isl_size total, n_param, n_in, n_out, n_div;
1894 	unsigned o_in, o_out;
1895 	isl_ctx *ctx;
1896 	isl_space *space;
1897 	struct isl_dim_map *dim_map;
1898 
1899 	space = isl_basic_map_peek_space(bmap2);
1900 	if (!bmap1 || !space)
1901 		goto error;
1902 
1903 	total = isl_basic_map_dim(bmap1, isl_dim_all);
1904 	n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1905 	n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1906 	o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1907 	n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1908 	o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1909 	n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1910 	if (total < 0 || n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
1911 		goto error;
1912 	ctx = isl_basic_map_get_ctx(bmap1);
1913 	dim_map = isl_dim_map_alloc(ctx, total + n_div);
1914 	isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1915 	isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1916 	isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1917 	isl_dim_map_div(dim_map, bmap2, total);
1918 
1919 	return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1920 error:
1921 	isl_basic_map_free(bmap1);
1922 	isl_basic_map_free(bmap2);
1923 	return NULL;
1924 }
1925 
isl_basic_map_extend(__isl_take isl_basic_map * base,unsigned extra,unsigned n_eq,unsigned n_ineq)1926 __isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
1927 	unsigned extra, unsigned n_eq, unsigned n_ineq)
1928 {
1929 	isl_space *space;
1930 	struct isl_basic_map *ext;
1931 	unsigned flags;
1932 	int dims_ok;
1933 
1934 	if (!base)
1935 		goto error;
1936 
1937 	dims_ok = base->extra >= base->n_div + extra;
1938 
1939 	if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1940 		       room_for_ineq(base, n_ineq))
1941 		return base;
1942 
1943 	extra += base->extra;
1944 	n_eq += base->n_eq;
1945 	n_ineq += base->n_ineq;
1946 
1947 	space = isl_basic_map_get_space(base);
1948 	ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1949 	if (!ext)
1950 		goto error;
1951 
1952 	if (dims_ok)
1953 		ext->sample = isl_vec_copy(base->sample);
1954 	flags = base->flags;
1955 	ext = add_constraints(ext, base, 0, 0);
1956 	if (ext) {
1957 		ext->flags = flags;
1958 		ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1959 	}
1960 
1961 	return ext;
1962 
1963 error:
1964 	isl_basic_map_free(base);
1965 	return NULL;
1966 }
1967 
isl_basic_set_extend(__isl_take isl_basic_set * base,unsigned extra,unsigned n_eq,unsigned n_ineq)1968 __isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,
1969 	unsigned extra, unsigned n_eq, unsigned n_ineq)
1970 {
1971 	return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
1972 						    extra, n_eq, n_ineq));
1973 }
1974 
isl_basic_map_extend_constraints(__isl_take isl_basic_map * base,unsigned n_eq,unsigned n_ineq)1975 __isl_give isl_basic_map *isl_basic_map_extend_constraints(
1976 	__isl_take isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1977 {
1978 	return isl_basic_map_extend(base, 0, n_eq, n_ineq);
1979 }
1980 
isl_basic_set_extend_constraints(__isl_take isl_basic_set * base,unsigned n_eq,unsigned n_ineq)1981 __isl_give isl_basic_set *isl_basic_set_extend_constraints(
1982 	__isl_take isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1983 {
1984 	isl_basic_map *bmap = bset_to_bmap(base);
1985 	bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1986 	return bset_from_bmap(bmap);
1987 }
1988 
isl_basic_set_cow(__isl_take isl_basic_set * bset)1989 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1990 {
1991 	return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1992 }
1993 
isl_basic_map_cow(__isl_take isl_basic_map * bmap)1994 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1995 {
1996 	if (!bmap)
1997 		return NULL;
1998 
1999 	if (bmap->ref > 1) {
2000 		bmap->ref--;
2001 		bmap = isl_basic_map_dup(bmap);
2002 	}
2003 	if (bmap) {
2004 		ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
2005 		ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
2006 	}
2007 	return bmap;
2008 }
2009 
2010 /* Clear all cached information in "map", either because it is about
2011  * to be modified or because it is being freed.
2012  * Always return the same pointer that is passed in.
2013  * This is needed for the use in isl_map_free.
2014  */
clear_caches(__isl_take isl_map * map)2015 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
2016 {
2017 	isl_basic_map_free(map->cached_simple_hull[0]);
2018 	isl_basic_map_free(map->cached_simple_hull[1]);
2019 	map->cached_simple_hull[0] = NULL;
2020 	map->cached_simple_hull[1] = NULL;
2021 	return map;
2022 }
2023 
isl_set_cow(__isl_take isl_set * set)2024 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
2025 {
2026 	return isl_map_cow(set);
2027 }
2028 
2029 /* Return an isl_map that is equal to "map" and that has only
2030  * a single reference.
2031  *
2032  * If the original input already has only one reference, then
2033  * simply return it, but clear all cached information, since
2034  * it may be rendered invalid by the operations that will be
2035  * performed on the result.
2036  *
2037  * Otherwise, create a duplicate (without any cached information).
2038  */
isl_map_cow(__isl_take isl_map * map)2039 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
2040 {
2041 	if (!map)
2042 		return NULL;
2043 
2044 	if (map->ref == 1)
2045 		return clear_caches(map);
2046 	map->ref--;
2047 	return isl_map_dup(map);
2048 }
2049 
swap_vars(struct isl_blk blk,isl_int * a,unsigned a_len,unsigned b_len)2050 static void swap_vars(struct isl_blk blk, isl_int *a,
2051 			unsigned a_len, unsigned b_len)
2052 {
2053 	isl_seq_cpy(blk.data, a+a_len, b_len);
2054 	isl_seq_cpy(blk.data+b_len, a, a_len);
2055 	isl_seq_cpy(a, blk.data, b_len+a_len);
2056 }
2057 
isl_basic_map_swap_vars(__isl_take isl_basic_map * bmap,unsigned pos,unsigned n1,unsigned n2)2058 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
2059 	__isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
2060 {
2061 	int i;
2062 	struct isl_blk blk;
2063 
2064 	if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
2065 		goto error;
2066 
2067 	if (n1 == 0 || n2 == 0)
2068 		return bmap;
2069 
2070 	bmap = isl_basic_map_cow(bmap);
2071 	if (!bmap)
2072 		return NULL;
2073 
2074 	blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2075 	if (isl_blk_is_error(blk))
2076 		goto error;
2077 
2078 	for (i = 0; i < bmap->n_eq; ++i)
2079 		swap_vars(blk,
2080 			  bmap->eq[i] + pos, n1, n2);
2081 
2082 	for (i = 0; i < bmap->n_ineq; ++i)
2083 		swap_vars(blk,
2084 			  bmap->ineq[i] + pos, n1, n2);
2085 
2086 	for (i = 0; i < bmap->n_div; ++i)
2087 		swap_vars(blk,
2088 			  bmap->div[i]+1 + pos, n1, n2);
2089 
2090 	isl_blk_free(bmap->ctx, blk);
2091 
2092 	ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2093 	bmap = isl_basic_map_gauss(bmap, NULL);
2094 	return isl_basic_map_finalize(bmap);
2095 error:
2096 	isl_basic_map_free(bmap);
2097 	return NULL;
2098 }
2099 
2100 /* The given basic map has turned out to be empty.
2101  * Explicitly mark it as such and change the representation
2102  * to a canonical representation of the empty basic map.
2103  * Since the basic map has conflicting constraints,
2104  * it must have at least one constraint, except perhaps
2105  * if it was already explicitly marked as being empty.
2106  * Do nothing in the latter case.
2107  */
isl_basic_map_set_to_empty(__isl_take isl_basic_map * bmap)2108 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2109 	__isl_take isl_basic_map *bmap)
2110 {
2111 	int i = 0;
2112 	isl_bool empty;
2113 	isl_size total;
2114 
2115 	empty = isl_basic_map_plain_is_empty(bmap);
2116 	if (empty < 0)
2117 		return isl_basic_map_free(bmap);
2118 	if (empty)
2119 		return bmap;
2120 	total = isl_basic_map_dim(bmap, isl_dim_all);
2121 	if (total < 0)
2122 		return isl_basic_map_free(bmap);
2123 	if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2124 		return isl_basic_map_free(bmap);
2125 	bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2126 	if (!bmap)
2127 		return NULL;
2128 	if (bmap->n_eq > 0) {
2129 		bmap = isl_basic_map_free_equality(bmap, bmap->n_eq - 1);
2130 		if (!bmap)
2131 			return NULL;
2132 	} else {
2133 		i = isl_basic_map_alloc_equality(bmap);
2134 		if (i < 0)
2135 			goto error;
2136 	}
2137 	isl_int_set_si(bmap->eq[i][0], 1);
2138 	isl_seq_clr(bmap->eq[i]+1, total);
2139 	ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2140 	isl_vec_free(bmap->sample);
2141 	bmap->sample = NULL;
2142 	return isl_basic_map_finalize(bmap);
2143 error:
2144 	isl_basic_map_free(bmap);
2145 	return NULL;
2146 }
2147 
isl_basic_set_set_to_empty(__isl_take isl_basic_set * bset)2148 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2149 	__isl_take isl_basic_set *bset)
2150 {
2151 	return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2152 }
2153 
isl_basic_map_set_rational(__isl_take isl_basic_map * bmap)2154 __isl_give isl_basic_map *isl_basic_map_set_rational(
2155 	__isl_take isl_basic_map *bmap)
2156 {
2157 	if (!bmap)
2158 		return NULL;
2159 
2160 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2161 		return bmap;
2162 
2163 	bmap = isl_basic_map_cow(bmap);
2164 	if (!bmap)
2165 		return NULL;
2166 
2167 	ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2168 
2169 	return isl_basic_map_finalize(bmap);
2170 }
2171 
isl_basic_set_set_rational(__isl_take isl_basic_set * bset)2172 __isl_give isl_basic_set *isl_basic_set_set_rational(
2173 	__isl_take isl_basic_set *bset)
2174 {
2175 	return isl_basic_map_set_rational(bset);
2176 }
2177 
isl_basic_set_set_integral(__isl_take isl_basic_set * bset)2178 __isl_give isl_basic_set *isl_basic_set_set_integral(
2179 	__isl_take isl_basic_set *bset)
2180 {
2181 	if (!bset)
2182 		return NULL;
2183 
2184 	if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2185 		return bset;
2186 
2187 	bset = isl_basic_set_cow(bset);
2188 	if (!bset)
2189 		return NULL;
2190 
2191 	ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2192 
2193 	return isl_basic_set_finalize(bset);
2194 }
2195 
isl_map_set_rational(__isl_take isl_map * map)2196 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2197 {
2198 	int i;
2199 
2200 	map = isl_map_cow(map);
2201 	if (!map)
2202 		return NULL;
2203 	for (i = 0; i < map->n; ++i) {
2204 		map->p[i] = isl_basic_map_set_rational(map->p[i]);
2205 		if (!map->p[i])
2206 			goto error;
2207 	}
2208 	return map;
2209 error:
2210 	isl_map_free(map);
2211 	return NULL;
2212 }
2213 
isl_set_set_rational(__isl_take isl_set * set)2214 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2215 {
2216 	return isl_map_set_rational(set);
2217 }
2218 
2219 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2220  * of "bmap").
2221  */
swap_div(__isl_keep isl_basic_map * bmap,int a,int b)2222 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2223 {
2224 	isl_int *t = bmap->div[a];
2225 	bmap->div[a] = bmap->div[b];
2226 	bmap->div[b] = t;
2227 }
2228 
2229 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2230  * div definitions accordingly.
2231  */
isl_basic_map_swap_div(__isl_take isl_basic_map * bmap,int a,int b)2232 __isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2233 	int a, int b)
2234 {
2235 	int i;
2236 	isl_size off;
2237 
2238 	off = isl_basic_map_var_offset(bmap, isl_dim_div);
2239 	if (off < 0)
2240 		return isl_basic_map_free(bmap);
2241 
2242 	swap_div(bmap, a, b);
2243 
2244 	for (i = 0; i < bmap->n_eq; ++i)
2245 		isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2246 
2247 	for (i = 0; i < bmap->n_ineq; ++i)
2248 		isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2249 
2250 	for (i = 0; i < bmap->n_div; ++i)
2251 		isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2252 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2253 
2254 	return bmap;
2255 }
2256 
constraint_drop_vars(isl_int * c,unsigned n,unsigned rem)2257 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2258 {
2259 	isl_seq_cpy(c, c + n, rem);
2260 	isl_seq_clr(c + rem, n);
2261 }
2262 
2263 /* Drop n dimensions starting at first.
2264  *
2265  * In principle, this frees up some extra variables as the number
2266  * of columns remains constant, but we would have to extend
2267  * the div array too as the number of rows in this array is assumed
2268  * to be equal to extra.
2269  */
isl_basic_set_drop_dims(__isl_take isl_basic_set * bset,unsigned first,unsigned n)2270 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2271 	__isl_take isl_basic_set *bset, unsigned first, unsigned n)
2272 {
2273 	return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2274 }
2275 
2276 /* Move "n" divs starting at "first" to the end of the list of divs.
2277  */
move_divs_last(__isl_take isl_basic_map * bmap,unsigned first,unsigned n)2278 static __isl_give isl_basic_map *move_divs_last(__isl_take isl_basic_map *bmap,
2279 	unsigned first, unsigned n)
2280 {
2281 	isl_int **div;
2282 	int i;
2283 
2284 	if (first + n == bmap->n_div)
2285 		return bmap;
2286 
2287 	div = isl_alloc_array(bmap->ctx, isl_int *, n);
2288 	if (!div)
2289 		goto error;
2290 	for (i = 0; i < n; ++i)
2291 		div[i] = bmap->div[first + i];
2292 	for (i = 0; i < bmap->n_div - first - n; ++i)
2293 		bmap->div[first + i] = bmap->div[first + n + i];
2294 	for (i = 0; i < n; ++i)
2295 		bmap->div[bmap->n_div - n + i] = div[i];
2296 	free(div);
2297 	return bmap;
2298 error:
2299 	isl_basic_map_free(bmap);
2300 	return NULL;
2301 }
2302 
2303 #undef TYPE
2304 #define TYPE	isl_map
2305 static
2306 #include "check_type_range_templ.c"
2307 
2308 /* Check that there are "n" dimensions of type "type" starting at "first"
2309  * in "set".
2310  */
isl_set_check_range(__isl_keep isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2311 isl_stat isl_set_check_range(__isl_keep isl_set *set,
2312 	enum isl_dim_type type, unsigned first, unsigned n)
2313 {
2314 	return isl_map_check_range(set_to_map(set), type, first, n);
2315 }
2316 
2317 /* Drop "n" dimensions of type "type" starting at "first".
2318  * Perform the core computation, without cowing or
2319  * simplifying and finalizing the result.
2320  *
2321  * In principle, this frees up some extra variables as the number
2322  * of columns remains constant, but we would have to extend
2323  * the div array too as the number of rows in this array is assumed
2324  * to be equal to extra.
2325  */
isl_basic_map_drop_core(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2326 __isl_give isl_basic_map *isl_basic_map_drop_core(
2327 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
2328 	unsigned first, unsigned n)
2329 {
2330 	int i;
2331 	unsigned offset;
2332 	unsigned left;
2333 	isl_size total;
2334 
2335 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2336 		return isl_basic_map_free(bmap);
2337 
2338 	total = isl_basic_map_dim(bmap, isl_dim_all);
2339 	if (total < 0)
2340 		return isl_basic_map_free(bmap);
2341 
2342 	offset = isl_basic_map_offset(bmap, type) + first;
2343 	left = total - (offset - 1) - n;
2344 	for (i = 0; i < bmap->n_eq; ++i)
2345 		constraint_drop_vars(bmap->eq[i]+offset, n, left);
2346 
2347 	for (i = 0; i < bmap->n_ineq; ++i)
2348 		constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2349 
2350 	for (i = 0; i < bmap->n_div; ++i)
2351 		constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2352 
2353 	if (type == isl_dim_div) {
2354 		bmap = move_divs_last(bmap, first, n);
2355 		if (!bmap)
2356 			return NULL;
2357 		if (isl_basic_map_free_div(bmap, n) < 0)
2358 			return isl_basic_map_free(bmap);
2359 	} else
2360 		bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2361 	if (!bmap->dim)
2362 		return isl_basic_map_free(bmap);
2363 
2364 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2365 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2366 	return bmap;
2367 }
2368 
2369 /* Drop "n" dimensions of type "type" starting at "first".
2370  *
2371  * In principle, this frees up some extra variables as the number
2372  * of columns remains constant, but we would have to extend
2373  * the div array too as the number of rows in this array is assumed
2374  * to be equal to extra.
2375  */
isl_basic_map_drop(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2376 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2377 	enum isl_dim_type type, unsigned first, unsigned n)
2378 {
2379 	if (!bmap)
2380 		return NULL;
2381 	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2382 		return bmap;
2383 
2384 	bmap = isl_basic_map_cow(bmap);
2385 	if (!bmap)
2386 		return NULL;
2387 
2388 	bmap = isl_basic_map_drop_core(bmap, type, first, n);
2389 
2390 	bmap = isl_basic_map_simplify(bmap);
2391 	return isl_basic_map_finalize(bmap);
2392 }
2393 
isl_basic_set_drop(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2394 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2395 	enum isl_dim_type type, unsigned first, unsigned n)
2396 {
2397 	return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2398 							type, first, n));
2399 }
2400 
2401 /* No longer consider "map" to be normalized.
2402  */
isl_map_unmark_normalized(__isl_take isl_map * map)2403 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2404 {
2405 	if (!map)
2406 		return NULL;
2407 	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2408 	return map;
2409 }
2410 
isl_map_drop(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2411 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2412 	enum isl_dim_type type, unsigned first, unsigned n)
2413 {
2414 	int i;
2415 	isl_space *space;
2416 
2417 	if (isl_map_check_range(map, type, first, n) < 0)
2418 		return isl_map_free(map);
2419 
2420 	if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2421 		return map;
2422 	map = isl_map_cow(map);
2423 	if (!map)
2424 		goto error;
2425 
2426 	for (i = 0; i < map->n; ++i) {
2427 		map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2428 		if (!map->p[i])
2429 			goto error;
2430 	}
2431 	map = isl_map_unmark_normalized(map);
2432 
2433 	space = isl_map_take_space(map);
2434 	space = isl_space_drop_dims(space, type, first, n);
2435 	map = isl_map_restore_space(map, space);
2436 
2437 	return map;
2438 error:
2439 	isl_map_free(map);
2440 	return NULL;
2441 }
2442 
isl_set_drop(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2443 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2444 	enum isl_dim_type type, unsigned first, unsigned n)
2445 {
2446 	return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2447 }
2448 
2449 /* Drop the integer division at position "div", which is assumed
2450  * not to appear in any of the constraints or
2451  * in any of the other integer divisions.
2452  *
2453  * Since the integer division is redundant, there is no need to cow.
2454  */
isl_basic_map_drop_div(__isl_take isl_basic_map * bmap,unsigned div)2455 __isl_give isl_basic_map *isl_basic_map_drop_div(
2456 	__isl_take isl_basic_map *bmap, unsigned div)
2457 {
2458 	return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2459 }
2460 
2461 /* Eliminate the specified n dimensions starting at first from the
2462  * constraints, without removing the dimensions from the space.
2463  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2464  */
isl_map_eliminate(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2465 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2466 	enum isl_dim_type type, unsigned first, unsigned n)
2467 {
2468 	int i;
2469 
2470 	if (n == 0)
2471 		return map;
2472 
2473 	if (isl_map_check_range(map, type, first, n) < 0)
2474 		return isl_map_free(map);
2475 
2476 	map = isl_map_cow(map);
2477 	if (!map)
2478 		return NULL;
2479 
2480 	for (i = 0; i < map->n; ++i) {
2481 		map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2482 		if (!map->p[i])
2483 			goto error;
2484 	}
2485 	return map;
2486 error:
2487 	isl_map_free(map);
2488 	return NULL;
2489 }
2490 
2491 /* Eliminate the specified n dimensions starting at first from the
2492  * constraints, without removing the dimensions from the space.
2493  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2494  */
isl_set_eliminate(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2495 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2496 	enum isl_dim_type type, unsigned first, unsigned n)
2497 {
2498 	return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2499 }
2500 
2501 /* Eliminate the specified n dimensions starting at first from the
2502  * constraints, without removing the dimensions from the space.
2503  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2504  */
isl_set_eliminate_dims(__isl_take isl_set * set,unsigned first,unsigned n)2505 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2506 	unsigned first, unsigned n)
2507 {
2508 	return isl_set_eliminate(set, isl_dim_set, first, n);
2509 }
2510 
isl_basic_map_remove_divs(__isl_take isl_basic_map * bmap)2511 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2512 	__isl_take isl_basic_map *bmap)
2513 {
2514 	isl_size v_div;
2515 
2516 	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2517 	if (v_div < 0)
2518 		return isl_basic_map_free(bmap);
2519 	bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);
2520 	if (!bmap)
2521 		return NULL;
2522 	bmap->n_div = 0;
2523 	return isl_basic_map_finalize(bmap);
2524 }
2525 
isl_basic_set_remove_divs(__isl_take isl_basic_set * bset)2526 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2527 	__isl_take isl_basic_set *bset)
2528 {
2529 	return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2530 }
2531 
isl_map_remove_divs(__isl_take isl_map * map)2532 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2533 {
2534 	int i;
2535 
2536 	if (!map)
2537 		return NULL;
2538 	if (map->n == 0)
2539 		return map;
2540 
2541 	map = isl_map_cow(map);
2542 	if (!map)
2543 		return NULL;
2544 
2545 	for (i = 0; i < map->n; ++i) {
2546 		map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2547 		if (!map->p[i])
2548 			goto error;
2549 	}
2550 	return map;
2551 error:
2552 	isl_map_free(map);
2553 	return NULL;
2554 }
2555 
isl_set_remove_divs(__isl_take isl_set * set)2556 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2557 {
2558 	return isl_map_remove_divs(set);
2559 }
2560 
isl_basic_map_remove_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2561 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2562 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
2563 	unsigned first, unsigned n)
2564 {
2565 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2566 		return isl_basic_map_free(bmap);
2567 	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2568 		return bmap;
2569 	bmap = isl_basic_map_eliminate_vars(bmap,
2570 			isl_basic_map_offset(bmap, type) - 1 + first, n);
2571 	if (!bmap)
2572 		return bmap;
2573 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2574 		return bmap;
2575 	bmap = isl_basic_map_drop(bmap, type, first, n);
2576 	return bmap;
2577 }
2578 
2579 /* Return true if the definition of the given div (recursively) involves
2580  * any of the given variables.
2581  */
div_involves_vars(__isl_keep isl_basic_map * bmap,int div,unsigned first,unsigned n)2582 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2583 	unsigned first, unsigned n)
2584 {
2585 	int i;
2586 	unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2587 
2588 	if (isl_int_is_zero(bmap->div[div][0]))
2589 		return isl_bool_false;
2590 	if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2591 		return isl_bool_true;
2592 
2593 	for (i = bmap->n_div - 1; i >= 0; --i) {
2594 		isl_bool involves;
2595 
2596 		if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2597 			continue;
2598 		involves = div_involves_vars(bmap, i, first, n);
2599 		if (involves < 0 || involves)
2600 			return involves;
2601 	}
2602 
2603 	return isl_bool_false;
2604 }
2605 
2606 /* Try and add a lower and/or upper bound on "div" to "bmap"
2607  * based on inequality "i".
2608  * "total" is the total number of variables (excluding the divs).
2609  * "v" is a temporary object that can be used during the calculations.
2610  * If "lb" is set, then a lower bound should be constructed.
2611  * If "ub" is set, then an upper bound should be constructed.
2612  *
2613  * The calling function has already checked that the inequality does not
2614  * reference "div", but we still need to check that the inequality is
2615  * of the right form.  We'll consider the case where we want to construct
2616  * a lower bound.  The construction of upper bounds is similar.
2617  *
2618  * Let "div" be of the form
2619  *
2620  *	q = floor((a + f(x))/d)
2621  *
2622  * We essentially check if constraint "i" is of the form
2623  *
2624  *	b + f(x) >= 0
2625  *
2626  * so that we can use it to derive a lower bound on "div".
2627  * However, we allow a slightly more general form
2628  *
2629  *	b + g(x) >= 0
2630  *
2631  * with the condition that the coefficients of g(x) - f(x) are all
2632  * divisible by d.
2633  * Rewriting this constraint as
2634  *
2635  *	0 >= -b - g(x)
2636  *
2637  * adding a + f(x) to both sides and dividing by d, we obtain
2638  *
2639  *	(a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2640  *
2641  * Taking the floor on both sides, we obtain
2642  *
2643  *	q >= floor((a-b)/d) + (f(x)-g(x))/d
2644  *
2645  * or
2646  *
2647  *	(g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2648  *
2649  * In the case of an upper bound, we construct the constraint
2650  *
2651  *	(g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2652  *
2653  */
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)2654 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2655 	__isl_take isl_basic_map *bmap, int div, int i,
2656 	unsigned total, isl_int v, int lb, int ub)
2657 {
2658 	int j;
2659 
2660 	for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2661 		if (lb) {
2662 			isl_int_sub(v, bmap->ineq[i][1 + j],
2663 					bmap->div[div][1 + 1 + j]);
2664 			lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2665 		}
2666 		if (ub) {
2667 			isl_int_add(v, bmap->ineq[i][1 + j],
2668 					bmap->div[div][1 + 1 + j]);
2669 			ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2670 		}
2671 	}
2672 	if (!lb && !ub)
2673 		return bmap;
2674 
2675 	bmap = isl_basic_map_cow(bmap);
2676 	bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2677 	if (lb) {
2678 		int k = isl_basic_map_alloc_inequality(bmap);
2679 		if (k < 0)
2680 			goto error;
2681 		for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2682 			isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2683 					bmap->div[div][1 + j]);
2684 			isl_int_cdiv_q(bmap->ineq[k][j],
2685 					bmap->ineq[k][j], bmap->div[div][0]);
2686 		}
2687 		isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2688 	}
2689 	if (ub) {
2690 		int k = isl_basic_map_alloc_inequality(bmap);
2691 		if (k < 0)
2692 			goto error;
2693 		for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2694 			isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2695 					bmap->div[div][1 + j]);
2696 			isl_int_fdiv_q(bmap->ineq[k][j],
2697 					bmap->ineq[k][j], bmap->div[div][0]);
2698 		}
2699 		isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2700 	}
2701 
2702 	return bmap;
2703 error:
2704 	isl_basic_map_free(bmap);
2705 	return NULL;
2706 }
2707 
2708 /* This function is called right before "div" is eliminated from "bmap"
2709  * using Fourier-Motzkin.
2710  * Look through the constraints of "bmap" for constraints on the argument
2711  * of the integer division and use them to construct constraints on the
2712  * integer division itself.  These constraints can then be combined
2713  * during the Fourier-Motzkin elimination.
2714  * Note that it is only useful to introduce lower bounds on "div"
2715  * if "bmap" already contains upper bounds on "div" as the newly
2716  * introduce lower bounds can then be combined with the pre-existing
2717  * upper bounds.  Similarly for upper bounds.
2718  * We therefore first check if "bmap" contains any lower and/or upper bounds
2719  * on "div".
2720  *
2721  * It is interesting to note that the introduction of these constraints
2722  * can indeed lead to more accurate results, even when compared to
2723  * deriving constraints on the argument of "div" from constraints on "div".
2724  * Consider, for example, the set
2725  *
2726  *	{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2727  *
2728  * The second constraint can be rewritten as
2729  *
2730  *	2 * [(-i-2j+3)/4] + k >= 0
2731  *
2732  * from which we can derive
2733  *
2734  *	-i - 2j + 3 >= -2k
2735  *
2736  * or
2737  *
2738  *	i + 2j <= 3 + 2k
2739  *
2740  * Combined with the first constraint, we obtain
2741  *
2742  *	-3 <= 3 + 2k	or	k >= -3
2743  *
2744  * If, on the other hand we derive a constraint on [(i+2j)/4] from
2745  * the first constraint, we obtain
2746  *
2747  *	[(i + 2j)/4] >= [-3/4] = -1
2748  *
2749  * Combining this constraint with the second constraint, we obtain
2750  *
2751  *	k >= -2
2752  */
insert_bounds_on_div(__isl_take isl_basic_map * bmap,int div)2753 static __isl_give isl_basic_map *insert_bounds_on_div(
2754 	__isl_take isl_basic_map *bmap, int div)
2755 {
2756 	int i;
2757 	int check_lb, check_ub;
2758 	isl_int v;
2759 	isl_size v_div;
2760 
2761 	if (!bmap)
2762 		return NULL;
2763 
2764 	if (isl_int_is_zero(bmap->div[div][0]))
2765 		return bmap;
2766 
2767 	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2768 	if (v_div < 0)
2769 		return isl_basic_map_free(bmap);
2770 
2771 	check_lb = 0;
2772 	check_ub = 0;
2773 	for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2774 		int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);
2775 		if (s > 0)
2776 			check_ub = 1;
2777 		if (s < 0)
2778 			check_lb = 1;
2779 	}
2780 
2781 	if (!check_lb && !check_ub)
2782 		return bmap;
2783 
2784 	isl_int_init(v);
2785 
2786 	for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2787 		if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))
2788 			continue;
2789 
2790 		bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,
2791 							check_lb, check_ub);
2792 	}
2793 
2794 	isl_int_clear(v);
2795 
2796 	return bmap;
2797 }
2798 
2799 /* Remove all divs (recursively) involving any of the given dimensions
2800  * in their definitions.
2801  */
isl_basic_map_remove_divs_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2802 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2803 	__isl_take isl_basic_map *bmap,
2804 	enum isl_dim_type type, unsigned first, unsigned n)
2805 {
2806 	int i;
2807 
2808 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2809 		return isl_basic_map_free(bmap);
2810 	first += isl_basic_map_offset(bmap, type);
2811 
2812 	for (i = bmap->n_div - 1; i >= 0; --i) {
2813 		isl_bool involves;
2814 
2815 		involves = div_involves_vars(bmap, i, first, n);
2816 		if (involves < 0)
2817 			return isl_basic_map_free(bmap);
2818 		if (!involves)
2819 			continue;
2820 		bmap = insert_bounds_on_div(bmap, i);
2821 		bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2822 		if (!bmap)
2823 			return NULL;
2824 		i = bmap->n_div;
2825 	}
2826 
2827 	return bmap;
2828 }
2829 
isl_basic_set_remove_divs_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2830 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2831 	__isl_take isl_basic_set *bset,
2832 	enum isl_dim_type type, unsigned first, unsigned n)
2833 {
2834 	return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2835 }
2836 
isl_map_remove_divs_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2837 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2838 	enum isl_dim_type type, unsigned first, unsigned n)
2839 {
2840 	int i;
2841 
2842 	if (!map)
2843 		return NULL;
2844 	if (map->n == 0)
2845 		return map;
2846 
2847 	map = isl_map_cow(map);
2848 	if (!map)
2849 		return NULL;
2850 
2851 	for (i = 0; i < map->n; ++i) {
2852 		map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2853 								type, first, n);
2854 		if (!map->p[i])
2855 			goto error;
2856 	}
2857 	return map;
2858 error:
2859 	isl_map_free(map);
2860 	return NULL;
2861 }
2862 
isl_set_remove_divs_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2863 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2864 	enum isl_dim_type type, unsigned first, unsigned n)
2865 {
2866 	return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2867 							      type, first, n));
2868 }
2869 
2870 /* Does the description of "bmap" depend on the specified dimensions?
2871  * We also check whether the dimensions appear in any of the div definitions.
2872  * In principle there is no need for this check.  If the dimensions appear
2873  * in a div definition, they also appear in the defining constraints of that
2874  * div.
2875  */
isl_basic_map_involves_dims(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2876 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2877 	enum isl_dim_type type, unsigned first, unsigned n)
2878 {
2879 	int i;
2880 
2881 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2882 		return isl_bool_error;
2883 
2884 	first += isl_basic_map_offset(bmap, type);
2885 	for (i = 0; i < bmap->n_eq; ++i)
2886 		if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2887 			return isl_bool_true;
2888 	for (i = 0; i < bmap->n_ineq; ++i)
2889 		if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2890 			return isl_bool_true;
2891 	for (i = 0; i < bmap->n_div; ++i) {
2892 		if (isl_int_is_zero(bmap->div[i][0]))
2893 			continue;
2894 		if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2895 			return isl_bool_true;
2896 	}
2897 
2898 	return isl_bool_false;
2899 }
2900 
isl_map_involves_dims(__isl_keep isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2901 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2902 	enum isl_dim_type type, unsigned first, unsigned n)
2903 {
2904 	int i;
2905 
2906 	if (isl_map_check_range(map, type, first, n) < 0)
2907 		return isl_bool_error;
2908 
2909 	for (i = 0; i < map->n; ++i) {
2910 		isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2911 							    type, first, n);
2912 		if (involves < 0 || involves)
2913 			return involves;
2914 	}
2915 
2916 	return isl_bool_false;
2917 }
2918 
isl_basic_set_involves_dims(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2919 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2920 	enum isl_dim_type type, unsigned first, unsigned n)
2921 {
2922 	return isl_basic_map_involves_dims(bset, type, first, n);
2923 }
2924 
isl_set_involves_dims(__isl_keep isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2925 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2926 	enum isl_dim_type type, unsigned first, unsigned n)
2927 {
2928 	return isl_map_involves_dims(set, type, first, n);
2929 }
2930 
2931 /* Does "bset" involve any local variables, i.e., integer divisions?
2932  */
isl_basic_set_involves_locals(__isl_keep isl_basic_set * bset)2933 static isl_bool isl_basic_set_involves_locals(__isl_keep isl_basic_set *bset)
2934 {
2935 	isl_size n;
2936 
2937 	n = isl_basic_set_dim(bset, isl_dim_div);
2938 	if (n < 0)
2939 		return isl_bool_error;
2940 	return isl_bool_ok(n > 0);
2941 }
2942 
2943 /* isl_set_every_basic_set callback that checks whether "bset"
2944  * is free of local variables.
2945  */
basic_set_no_locals(__isl_keep isl_basic_set * bset,void * user)2946 static isl_bool basic_set_no_locals(__isl_keep isl_basic_set *bset, void *user)
2947 {
2948 	return isl_bool_not(isl_basic_set_involves_locals(bset));
2949 }
2950 
2951 /* Does "set" involve any local variables, i.e., integer divisions?
2952  */
isl_set_involves_locals(__isl_keep isl_set * set)2953 isl_bool isl_set_involves_locals(__isl_keep isl_set *set)
2954 {
2955 	isl_bool no_locals;
2956 
2957 	no_locals = isl_set_every_basic_set(set, &basic_set_no_locals, NULL);
2958 	return isl_bool_not(no_locals);
2959 }
2960 
2961 /* Drop all constraints in bmap that involve any of the dimensions
2962  * first to first+n-1.
2963  * This function only performs the actual removal of constraints.
2964  *
2965  * This function should not call finalize since it is used by
2966  * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
2967  */
isl_basic_map_drop_constraints_involving(__isl_take isl_basic_map * bmap,unsigned first,unsigned n)2968 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2969 	__isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2970 {
2971 	int i;
2972 
2973 	if (n == 0)
2974 		return bmap;
2975 
2976 	bmap = isl_basic_map_cow(bmap);
2977 
2978 	if (!bmap)
2979 		return NULL;
2980 
2981 	for (i = bmap->n_eq - 1; i >= 0; --i) {
2982 		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2983 			continue;
2984 		if (isl_basic_map_drop_equality(bmap, i) < 0)
2985 			return isl_basic_map_free(bmap);
2986 	}
2987 
2988 	for (i = bmap->n_ineq - 1; i >= 0; --i) {
2989 		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2990 			continue;
2991 		if (isl_basic_map_drop_inequality(bmap, i) < 0)
2992 			return isl_basic_map_free(bmap);
2993 	}
2994 
2995 	return bmap;
2996 }
2997 
2998 /* Drop all constraints in bset that involve any of the dimensions
2999  * first to first+n-1.
3000  * This function only performs the actual removal of constraints.
3001  */
isl_basic_set_drop_constraints_involving(__isl_take isl_basic_set * bset,unsigned first,unsigned n)3002 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
3003 	__isl_take isl_basic_set *bset, unsigned first, unsigned n)
3004 {
3005 	return isl_basic_map_drop_constraints_involving(bset, first, n);
3006 }
3007 
3008 /* Drop all constraints in bmap that do not involve any of the dimensions
3009  * first to first + n - 1 of the given type.
3010  */
isl_basic_map_drop_constraints_not_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)3011 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
3012 	__isl_take isl_basic_map *bmap,
3013 	enum isl_dim_type type, unsigned first, unsigned n)
3014 {
3015 	int i;
3016 
3017 	if (n == 0) {
3018 		isl_space *space = isl_basic_map_get_space(bmap);
3019 		isl_basic_map_free(bmap);
3020 		return isl_basic_map_universe(space);
3021 	}
3022 	bmap = isl_basic_map_cow(bmap);
3023 	if (!bmap)
3024 		return NULL;
3025 
3026 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3027 		return isl_basic_map_free(bmap);
3028 
3029 	first += isl_basic_map_offset(bmap, type) - 1;
3030 
3031 	for (i = bmap->n_eq - 1; i >= 0; --i) {
3032 		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
3033 			continue;
3034 		if (isl_basic_map_drop_equality(bmap, i) < 0)
3035 			return isl_basic_map_free(bmap);
3036 	}
3037 
3038 	for (i = bmap->n_ineq - 1; i >= 0; --i) {
3039 		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
3040 			continue;
3041 		if (isl_basic_map_drop_inequality(bmap, i) < 0)
3042 			return isl_basic_map_free(bmap);
3043 	}
3044 
3045 	bmap = isl_basic_map_add_known_div_constraints(bmap);
3046 	return bmap;
3047 }
3048 
3049 /* Drop all constraints in bset that do not involve any of the dimensions
3050  * first to first + n - 1 of the given type.
3051  */
isl_basic_set_drop_constraints_not_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3052 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
3053 	__isl_take isl_basic_set *bset,
3054 	enum isl_dim_type type, unsigned first, unsigned n)
3055 {
3056 	return isl_basic_map_drop_constraints_not_involving_dims(bset,
3057 							    type, first, n);
3058 }
3059 
3060 /* Drop all constraints in bmap that involve any of the dimensions
3061  * first to first + n - 1 of the given type.
3062  */
isl_basic_map_drop_constraints_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)3063 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
3064 	__isl_take isl_basic_map *bmap,
3065 	enum isl_dim_type type, unsigned first, unsigned n)
3066 {
3067 	if (!bmap)
3068 		return NULL;
3069 	if (n == 0)
3070 		return bmap;
3071 
3072 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3073 		return isl_basic_map_free(bmap);
3074 
3075 	bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
3076 	first += isl_basic_map_offset(bmap, type) - 1;
3077 	bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
3078 	bmap = isl_basic_map_add_known_div_constraints(bmap);
3079 	return bmap;
3080 }
3081 
3082 /* Drop all constraints in bset that involve any of the dimensions
3083  * first to first + n - 1 of the given type.
3084  */
isl_basic_set_drop_constraints_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3085 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
3086 	__isl_take isl_basic_set *bset,
3087 	enum isl_dim_type type, unsigned first, unsigned n)
3088 {
3089 	return isl_basic_map_drop_constraints_involving_dims(bset,
3090 							    type, first, n);
3091 }
3092 
3093 /* Drop constraints from "map" by applying "drop" to each basic map.
3094  */
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))3095 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
3096 	enum isl_dim_type type, unsigned first, unsigned n,
3097 	__isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
3098 		enum isl_dim_type type, unsigned first, unsigned n))
3099 {
3100 	int i;
3101 
3102 	if (isl_map_check_range(map, type, first, n) < 0)
3103 		return isl_map_free(map);
3104 
3105 	map = isl_map_cow(map);
3106 	if (!map)
3107 		return NULL;
3108 
3109 	for (i = 0; i < map->n; ++i) {
3110 		map->p[i] = drop(map->p[i], type, first, n);
3111 		if (!map->p[i])
3112 			return isl_map_free(map);
3113 	}
3114 
3115 	if (map->n > 1)
3116 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
3117 
3118 	return map;
3119 }
3120 
3121 /* Drop all constraints in map that involve any of the dimensions
3122  * first to first + n - 1 of the given type.
3123  */
isl_map_drop_constraints_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3124 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
3125 	__isl_take isl_map *map,
3126 	enum isl_dim_type type, unsigned first, unsigned n)
3127 {
3128 	if (n == 0)
3129 		return map;
3130 	return drop_constraints(map, type, first, n,
3131 				&isl_basic_map_drop_constraints_involving_dims);
3132 }
3133 
3134 /* Drop all constraints in "map" that do not involve any of the dimensions
3135  * first to first + n - 1 of the given type.
3136  */
isl_map_drop_constraints_not_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3137 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3138 	__isl_take isl_map *map,
3139 	enum isl_dim_type type, unsigned first, unsigned n)
3140 {
3141 	if (n == 0) {
3142 		isl_space *space = isl_map_get_space(map);
3143 		isl_map_free(map);
3144 		return isl_map_universe(space);
3145 	}
3146 	return drop_constraints(map, type, first, n,
3147 			    &isl_basic_map_drop_constraints_not_involving_dims);
3148 }
3149 
3150 /* Drop all constraints in set that involve any of the dimensions
3151  * first to first + n - 1 of the given type.
3152  */
isl_set_drop_constraints_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)3153 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3154 	__isl_take isl_set *set,
3155 	enum isl_dim_type type, unsigned first, unsigned n)
3156 {
3157 	return isl_map_drop_constraints_involving_dims(set, type, first, n);
3158 }
3159 
3160 /* Drop all constraints in "set" that do not involve any of the dimensions
3161  * first to first + n - 1 of the given type.
3162  */
isl_set_drop_constraints_not_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)3163 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3164 	__isl_take isl_set *set,
3165 	enum isl_dim_type type, unsigned first, unsigned n)
3166 {
3167 	return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3168 }
3169 
3170 /* Does local variable "div" of "bmap" have a complete explicit representation?
3171  * Having a complete explicit representation requires not only
3172  * an explicit representation, but also that all local variables
3173  * that appear in this explicit representation in turn have
3174  * a complete explicit representation.
3175  */
isl_basic_map_div_is_known(__isl_keep isl_basic_map * bmap,int div)3176 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3177 {
3178 	int i;
3179 	unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3180 	isl_bool marked;
3181 
3182 	marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3183 	if (marked < 0 || marked)
3184 		return isl_bool_not(marked);
3185 
3186 	for (i = bmap->n_div - 1; i >= 0; --i) {
3187 		isl_bool known;
3188 
3189 		if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3190 			continue;
3191 		known = isl_basic_map_div_is_known(bmap, i);
3192 		if (known < 0 || !known)
3193 			return known;
3194 	}
3195 
3196 	return isl_bool_true;
3197 }
3198 
3199 /* Remove all divs that are unknown or defined in terms of unknown divs.
3200  */
isl_basic_map_remove_unknown_divs(__isl_take isl_basic_map * bmap)3201 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3202 	__isl_take isl_basic_map *bmap)
3203 {
3204 	int i;
3205 
3206 	if (!bmap)
3207 		return NULL;
3208 
3209 	for (i = bmap->n_div - 1; i >= 0; --i) {
3210 		if (isl_basic_map_div_is_known(bmap, i))
3211 			continue;
3212 		bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3213 		if (!bmap)
3214 			return NULL;
3215 		i = bmap->n_div;
3216 	}
3217 
3218 	return bmap;
3219 }
3220 
3221 /* Remove all divs that are unknown or defined in terms of unknown divs.
3222  */
isl_basic_set_remove_unknown_divs(__isl_take isl_basic_set * bset)3223 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3224 	__isl_take isl_basic_set *bset)
3225 {
3226 	return isl_basic_map_remove_unknown_divs(bset);
3227 }
3228 
isl_map_remove_unknown_divs(__isl_take isl_map * map)3229 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3230 {
3231 	int i;
3232 
3233 	if (!map)
3234 		return NULL;
3235 	if (map->n == 0)
3236 		return map;
3237 
3238 	map = isl_map_cow(map);
3239 	if (!map)
3240 		return NULL;
3241 
3242 	for (i = 0; i < map->n; ++i) {
3243 		map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3244 		if (!map->p[i])
3245 			goto error;
3246 	}
3247 	return map;
3248 error:
3249 	isl_map_free(map);
3250 	return NULL;
3251 }
3252 
isl_set_remove_unknown_divs(__isl_take isl_set * set)3253 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3254 {
3255 	return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3256 }
3257 
isl_basic_set_remove_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3258 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3259 	__isl_take isl_basic_set *bset,
3260 	enum isl_dim_type type, unsigned first, unsigned n)
3261 {
3262 	isl_basic_map *bmap = bset_to_bmap(bset);
3263 	bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3264 	return bset_from_bmap(bmap);
3265 }
3266 
isl_map_remove_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3267 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3268 	enum isl_dim_type type, unsigned first, unsigned n)
3269 {
3270 	int i;
3271 
3272 	if (n == 0)
3273 		return map;
3274 
3275 	map = isl_map_cow(map);
3276 	if (isl_map_check_range(map, type, first, n) < 0)
3277 		return isl_map_free(map);
3278 
3279 	for (i = 0; i < map->n; ++i) {
3280 		map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3281 			isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3282 		if (!map->p[i])
3283 			goto error;
3284 	}
3285 	map = isl_map_drop(map, type, first, n);
3286 	return map;
3287 error:
3288 	isl_map_free(map);
3289 	return NULL;
3290 }
3291 
isl_set_remove_dims(__isl_take isl_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3292 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3293 	enum isl_dim_type type, unsigned first, unsigned n)
3294 {
3295 	return set_from_map(isl_map_remove_dims(set_to_map(bset),
3296 						type, first, n));
3297 }
3298 
3299 /* Project out n inputs starting at first using Fourier-Motzkin */
isl_map_remove_inputs(__isl_take isl_map * map,unsigned first,unsigned n)3300 __isl_give isl_map *isl_map_remove_inputs(__isl_take isl_map *map,
3301 	unsigned first, unsigned n)
3302 {
3303 	return isl_map_remove_dims(map, isl_dim_in, first, n);
3304 }
3305 
isl_basic_set_print_internal(__isl_keep isl_basic_set * bset,FILE * out,int indent)3306 void isl_basic_set_print_internal(__isl_keep isl_basic_set *bset,
3307 	FILE *out, int indent)
3308 {
3309 	isl_printer *p;
3310 
3311 	if (!bset) {
3312 		fprintf(out, "null basic set\n");
3313 		return;
3314 	}
3315 
3316 	fprintf(out, "%*s", indent, "");
3317 	fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3318 			bset->ref, bset->dim->nparam, bset->dim->n_out,
3319 			bset->extra, bset->flags);
3320 
3321 	p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
3322 	p = isl_printer_set_dump(p, 1);
3323 	p = isl_printer_set_indent(p, indent);
3324 	p = isl_printer_start_line(p);
3325 	p = isl_printer_print_basic_set(p, bset);
3326 	p = isl_printer_end_line(p);
3327 	isl_printer_free(p);
3328 }
3329 
isl_basic_map_print_internal(__isl_keep isl_basic_map * bmap,FILE * out,int indent)3330 void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,
3331 	FILE *out, int indent)
3332 {
3333 	isl_printer *p;
3334 
3335 	if (!bmap) {
3336 		fprintf(out, "null basic map\n");
3337 		return;
3338 	}
3339 
3340 	fprintf(out, "%*s", indent, "");
3341 	fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3342 			"flags: %x, n_name: %d\n",
3343 		bmap->ref,
3344 		bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3345 		bmap->extra, bmap->flags, bmap->dim->n_id);
3346 
3347 	p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
3348 	p = isl_printer_set_dump(p, 1);
3349 	p = isl_printer_set_indent(p, indent);
3350 	p = isl_printer_start_line(p);
3351 	p = isl_printer_print_basic_map(p, bmap);
3352 	p = isl_printer_end_line(p);
3353 	isl_printer_free(p);
3354 }
3355 
isl_inequality_negate(__isl_take isl_basic_map * bmap,unsigned pos)3356 __isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3357 	unsigned pos)
3358 {
3359 	isl_size total;
3360 
3361 	total = isl_basic_map_dim(bmap, isl_dim_all);
3362 	if (total < 0)
3363 		return isl_basic_map_free(bmap);
3364 	if (pos >= bmap->n_ineq)
3365 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3366 			"invalid position", return isl_basic_map_free(bmap));
3367 	isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3368 	isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3369 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3370 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3371 	return bmap;
3372 }
3373 
isl_set_alloc_space(__isl_take isl_space * space,int n,unsigned flags)3374 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3375 	unsigned flags)
3376 {
3377 	if (isl_space_check_is_set(space) < 0)
3378 		goto error;
3379 	return isl_map_alloc_space(space, n, flags);
3380 error:
3381 	isl_space_free(space);
3382 	return NULL;
3383 }
3384 
3385 /* Make sure "map" has room for at least "n" more basic maps.
3386  */
isl_map_grow(__isl_take isl_map * map,int n)3387 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3388 {
3389 	int i;
3390 	struct isl_map *grown = NULL;
3391 
3392 	if (!map)
3393 		return NULL;
3394 	isl_assert(map->ctx, n >= 0, goto error);
3395 	if (map->n + n <= map->size)
3396 		return map;
3397 	grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3398 	if (!grown)
3399 		goto error;
3400 	for (i = 0; i < map->n; ++i) {
3401 		grown->p[i] = isl_basic_map_copy(map->p[i]);
3402 		if (!grown->p[i])
3403 			goto error;
3404 		grown->n++;
3405 	}
3406 	isl_map_free(map);
3407 	return grown;
3408 error:
3409 	isl_map_free(grown);
3410 	isl_map_free(map);
3411 	return NULL;
3412 }
3413 
3414 /* Make sure "set" has room for at least "n" more basic sets.
3415  */
isl_set_grow(__isl_take isl_set * set,int n)3416 __isl_give isl_set *isl_set_grow(__isl_take isl_set *set, int n)
3417 {
3418 	return set_from_map(isl_map_grow(set_to_map(set), n));
3419 }
3420 
isl_set_from_basic_set(__isl_take isl_basic_set * bset)3421 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3422 {
3423 	return isl_map_from_basic_map(bset);
3424 }
3425 
isl_map_from_basic_map(__isl_take isl_basic_map * bmap)3426 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3427 {
3428 	struct isl_map *map;
3429 
3430 	if (!bmap)
3431 		return NULL;
3432 
3433 	map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3434 	return isl_map_add_basic_map(map, bmap);
3435 }
3436 
isl_set_add_basic_set(__isl_take isl_set * set,__isl_take isl_basic_set * bset)3437 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3438 						__isl_take isl_basic_set *bset)
3439 {
3440 	return set_from_map(isl_map_add_basic_map(set_to_map(set),
3441 						bset_to_bmap(bset)));
3442 }
3443 
isl_set_free(__isl_take isl_set * set)3444 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3445 {
3446 	return isl_map_free(set);
3447 }
3448 
isl_set_print_internal(__isl_keep isl_set * set,FILE * out,int indent)3449 void isl_set_print_internal(__isl_keep isl_set *set, FILE *out, int indent)
3450 {
3451 	int i;
3452 
3453 	if (!set) {
3454 		fprintf(out, "null set\n");
3455 		return;
3456 	}
3457 
3458 	fprintf(out, "%*s", indent, "");
3459 	fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3460 			set->ref, set->n, set->dim->nparam, set->dim->n_out,
3461 			set->flags);
3462 	for (i = 0; i < set->n; ++i) {
3463 		fprintf(out, "%*s", indent, "");
3464 		fprintf(out, "basic set %d:\n", i);
3465 		isl_basic_set_print_internal(set->p[i], out, indent+4);
3466 	}
3467 }
3468 
isl_map_print_internal(__isl_keep isl_map * map,FILE * out,int indent)3469 void isl_map_print_internal(__isl_keep isl_map *map, FILE *out, int indent)
3470 {
3471 	int i;
3472 
3473 	if (!map) {
3474 		fprintf(out, "null map\n");
3475 		return;
3476 	}
3477 
3478 	fprintf(out, "%*s", indent, "");
3479 	fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3480 		     "flags: %x, n_name: %d\n",
3481 			map->ref, map->n, map->dim->nparam, map->dim->n_in,
3482 			map->dim->n_out, map->flags, map->dim->n_id);
3483 	for (i = 0; i < map->n; ++i) {
3484 		fprintf(out, "%*s", indent, "");
3485 		fprintf(out, "basic map %d:\n", i);
3486 		isl_basic_map_print_internal(map->p[i], out, indent+4);
3487 	}
3488 }
3489 
3490 /* Check that the space of "bset" is the same as that of the domain of "bmap".
3491  */
isl_basic_map_check_compatible_domain(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)3492 static isl_stat isl_basic_map_check_compatible_domain(
3493 	__isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3494 {
3495 	isl_bool ok;
3496 
3497 	ok = isl_basic_map_compatible_domain(bmap, bset);
3498 	if (ok < 0)
3499 		return isl_stat_error;
3500 	if (!ok)
3501 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3502 			"incompatible spaces", return isl_stat_error);
3503 
3504 	return isl_stat_ok;
3505 }
3506 
isl_basic_map_intersect_domain(__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset)3507 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3508 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3509 {
3510 	struct isl_basic_map *bmap_domain;
3511 	isl_size dim;
3512 
3513 	if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3514 		goto error;
3515 
3516 	dim = isl_basic_set_dim(bset, isl_dim_set);
3517 	if (dim < 0)
3518 		goto error;
3519 	if (dim != 0 &&
3520 	    isl_basic_map_check_compatible_domain(bmap, bset) < 0)
3521 		goto error;
3522 
3523 	bmap = isl_basic_map_cow(bmap);
3524 	if (!bmap)
3525 		goto error;
3526 	bmap = isl_basic_map_extend(bmap,
3527 			bset->n_div, bset->n_eq, bset->n_ineq);
3528 	bmap_domain = isl_basic_map_from_domain(bset);
3529 	bmap = add_constraints(bmap, bmap_domain, 0, 0);
3530 
3531 	bmap = isl_basic_map_simplify(bmap);
3532 	return isl_basic_map_finalize(bmap);
3533 error:
3534 	isl_basic_map_free(bmap);
3535 	isl_basic_set_free(bset);
3536 	return NULL;
3537 }
3538 
3539 /* Check that the space of "bset" is the same as that of the range of "bmap".
3540  */
isl_basic_map_check_compatible_range(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)3541 static isl_stat isl_basic_map_check_compatible_range(
3542 	__isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3543 {
3544 	isl_bool ok;
3545 
3546 	ok = isl_basic_map_compatible_range(bmap, bset);
3547 	if (ok < 0)
3548 		return isl_stat_error;
3549 	if (!ok)
3550 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3551 			"incompatible spaces", return isl_stat_error);
3552 
3553 	return isl_stat_ok;
3554 }
3555 
isl_basic_map_intersect_range(__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset)3556 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3557 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3558 {
3559 	struct isl_basic_map *bmap_range;
3560 	isl_size dim;
3561 
3562 	if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3563 		goto error;
3564 
3565 	dim = isl_basic_set_dim(bset, isl_dim_set);
3566 	if (dim < 0)
3567 		goto error;
3568 	if (dim != 0 && isl_basic_map_check_compatible_range(bmap, bset) < 0)
3569 		goto error;
3570 
3571 	if (isl_basic_set_plain_is_universe(bset)) {
3572 		isl_basic_set_free(bset);
3573 		return bmap;
3574 	}
3575 
3576 	bmap = isl_basic_map_cow(bmap);
3577 	if (!bmap)
3578 		goto error;
3579 	bmap = isl_basic_map_extend(bmap,
3580 			bset->n_div, bset->n_eq, bset->n_ineq);
3581 	bmap_range = bset_to_bmap(bset);
3582 	bmap = add_constraints(bmap, bmap_range, 0, 0);
3583 
3584 	bmap = isl_basic_map_simplify(bmap);
3585 	return isl_basic_map_finalize(bmap);
3586 error:
3587 	isl_basic_map_free(bmap);
3588 	isl_basic_set_free(bset);
3589 	return NULL;
3590 }
3591 
isl_basic_map_contains(__isl_keep isl_basic_map * bmap,__isl_keep isl_vec * vec)3592 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3593 	__isl_keep isl_vec *vec)
3594 {
3595 	int i;
3596 	isl_size total;
3597 	isl_int s;
3598 
3599 	total = isl_basic_map_dim(bmap, isl_dim_all);
3600 	if (total < 0 || !vec)
3601 		return isl_bool_error;
3602 
3603 	if (1 + total != vec->size)
3604 		return isl_bool_false;
3605 
3606 	isl_int_init(s);
3607 
3608 	for (i = 0; i < bmap->n_eq; ++i) {
3609 		isl_seq_inner_product(vec->el, bmap->eq[i], 1 + total, &s);
3610 		if (!isl_int_is_zero(s)) {
3611 			isl_int_clear(s);
3612 			return isl_bool_false;
3613 		}
3614 	}
3615 
3616 	for (i = 0; i < bmap->n_ineq; ++i) {
3617 		isl_seq_inner_product(vec->el, bmap->ineq[i], 1 + total, &s);
3618 		if (isl_int_is_neg(s)) {
3619 			isl_int_clear(s);
3620 			return isl_bool_false;
3621 		}
3622 	}
3623 
3624 	isl_int_clear(s);
3625 
3626 	return isl_bool_true;
3627 }
3628 
isl_basic_set_contains(__isl_keep isl_basic_set * bset,__isl_keep isl_vec * vec)3629 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3630 	__isl_keep isl_vec *vec)
3631 {
3632 	return isl_basic_map_contains(bset_to_bmap(bset), vec);
3633 }
3634 
isl_basic_map_intersect(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)3635 __isl_give isl_basic_map *isl_basic_map_intersect(
3636 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3637 {
3638 	struct isl_vec *sample = NULL;
3639 	isl_space *space1, *space2;
3640 	isl_size dim1, dim2, nparam1, nparam2;
3641 
3642 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3643 		goto error;
3644 	space1 = isl_basic_map_peek_space(bmap1);
3645 	space2 = isl_basic_map_peek_space(bmap2);
3646 	dim1 = isl_space_dim(space1, isl_dim_all);
3647 	dim2 = isl_space_dim(space2, isl_dim_all);
3648 	nparam1 = isl_space_dim(space1, isl_dim_param);
3649 	nparam2 = isl_space_dim(space2, isl_dim_param);
3650 	if (dim1 < 0 || dim2 < 0 || nparam1 < 0 || nparam2 < 0)
3651 		goto error;
3652 	if (dim1 == nparam1 && dim2 != nparam2)
3653 		return isl_basic_map_intersect(bmap2, bmap1);
3654 
3655 	if (dim2 != nparam2 &&
3656 	    isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
3657 		goto error;
3658 
3659 	if (isl_basic_map_plain_is_empty(bmap1)) {
3660 		isl_basic_map_free(bmap2);
3661 		return bmap1;
3662 	}
3663 	if (isl_basic_map_plain_is_empty(bmap2)) {
3664 		isl_basic_map_free(bmap1);
3665 		return bmap2;
3666 	}
3667 
3668 	if (bmap1->sample &&
3669 	    isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3670 	    isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3671 		sample = isl_vec_copy(bmap1->sample);
3672 	else if (bmap2->sample &&
3673 	    isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3674 	    isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3675 		sample = isl_vec_copy(bmap2->sample);
3676 
3677 	bmap1 = isl_basic_map_cow(bmap1);
3678 	if (!bmap1)
3679 		goto error;
3680 	bmap1 = isl_basic_map_extend(bmap1,
3681 			bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3682 	bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3683 
3684 	if (!bmap1)
3685 		isl_vec_free(sample);
3686 	else if (sample) {
3687 		isl_vec_free(bmap1->sample);
3688 		bmap1->sample = sample;
3689 	}
3690 
3691 	bmap1 = isl_basic_map_simplify(bmap1);
3692 	return isl_basic_map_finalize(bmap1);
3693 error:
3694 	if (sample)
3695 		isl_vec_free(sample);
3696 	isl_basic_map_free(bmap1);
3697 	isl_basic_map_free(bmap2);
3698 	return NULL;
3699 }
3700 
isl_basic_set_intersect(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)3701 __isl_give isl_basic_set *isl_basic_set_intersect(
3702 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3703 {
3704 	return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3705 							bset_to_bmap(bset2)));
3706 }
3707 
isl_basic_set_intersect_params(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)3708 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3709 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3710 {
3711 	return isl_basic_set_intersect(bset1, bset2);
3712 }
3713 
3714 /* Special case of isl_map_intersect, where both map1 and map2
3715  * are convex, without any divs and such that either map1 or map2
3716  * contains a single constraint.  This constraint is then simply
3717  * added to the other map.
3718  */
map_intersect_add_constraint(__isl_take isl_map * map1,__isl_take isl_map * map2)3719 static __isl_give isl_map *map_intersect_add_constraint(
3720 	__isl_take isl_map *map1, __isl_take isl_map *map2)
3721 {
3722 	isl_assert(map1->ctx, map1->n == 1, goto error);
3723 	isl_assert(map2->ctx, map1->n == 1, goto error);
3724 	isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3725 	isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3726 
3727 	if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3728 		return isl_map_intersect(map2, map1);
3729 
3730 	map1 = isl_map_cow(map1);
3731 	if (!map1)
3732 		goto error;
3733 	if (isl_map_plain_is_empty(map1)) {
3734 		isl_map_free(map2);
3735 		return map1;
3736 	}
3737 	if (map2->p[0]->n_eq == 1)
3738 		map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3739 	else
3740 		map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3741 							map2->p[0]->ineq[0]);
3742 
3743 	map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3744 	map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3745 	if (!map1->p[0])
3746 		goto error;
3747 
3748 	if (isl_basic_map_plain_is_empty(map1->p[0])) {
3749 		isl_basic_map_free(map1->p[0]);
3750 		map1->n = 0;
3751 	}
3752 
3753 	isl_map_free(map2);
3754 
3755 	map1 = isl_map_unmark_normalized(map1);
3756 	return map1;
3757 error:
3758 	isl_map_free(map1);
3759 	isl_map_free(map2);
3760 	return NULL;
3761 }
3762 
3763 /* map2 may be either a parameter domain or a map living in the same
3764  * space as map1.
3765  */
map_intersect_internal(__isl_take isl_map * map1,__isl_take isl_map * map2)3766 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3767 	__isl_take isl_map *map2)
3768 {
3769 	unsigned flags = 0;
3770 	isl_bool equal;
3771 	isl_map *result;
3772 	int i, j;
3773 	isl_size dim2, nparam2;
3774 
3775 	if (!map1 || !map2)
3776 		goto error;
3777 
3778 	if ((isl_map_plain_is_empty(map1) ||
3779 	     isl_map_plain_is_universe(map2)) &&
3780 	    isl_space_is_equal(map1->dim, map2->dim)) {
3781 		isl_map_free(map2);
3782 		return map1;
3783 	}
3784 	if ((isl_map_plain_is_empty(map2) ||
3785 	     isl_map_plain_is_universe(map1)) &&
3786 	    isl_space_is_equal(map1->dim, map2->dim)) {
3787 		isl_map_free(map1);
3788 		return map2;
3789 	}
3790 
3791 	if (map1->n == 1 && map2->n == 1 &&
3792 	    map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3793 	    isl_space_is_equal(map1->dim, map2->dim) &&
3794 	    (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3795 	     map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3796 		return map_intersect_add_constraint(map1, map2);
3797 
3798 	equal = isl_map_plain_is_equal(map1, map2);
3799 	if (equal < 0)
3800 		goto error;
3801 	if (equal) {
3802 		isl_map_free(map2);
3803 		return map1;
3804 	}
3805 
3806 	dim2 = isl_map_dim(map2, isl_dim_all);
3807 	nparam2 = isl_map_dim(map2, isl_dim_param);
3808 	if (dim2 < 0 || nparam2 < 0)
3809 		goto error;
3810 	if (dim2 != nparam2)
3811 		isl_assert(map1->ctx,
3812 			    isl_space_is_equal(map1->dim, map2->dim), goto error);
3813 
3814 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3815 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3816 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3817 
3818 	result = isl_map_alloc_space(isl_space_copy(map1->dim),
3819 				map1->n * map2->n, flags);
3820 	if (!result)
3821 		goto error;
3822 	for (i = 0; i < map1->n; ++i)
3823 		for (j = 0; j < map2->n; ++j) {
3824 			struct isl_basic_map *part;
3825 			part = isl_basic_map_intersect(
3826 				    isl_basic_map_copy(map1->p[i]),
3827 				    isl_basic_map_copy(map2->p[j]));
3828 			if (isl_basic_map_is_empty(part) < 0)
3829 				part = isl_basic_map_free(part);
3830 			result = isl_map_add_basic_map(result, part);
3831 			if (!result)
3832 				goto error;
3833 		}
3834 	isl_map_free(map1);
3835 	isl_map_free(map2);
3836 	return result;
3837 error:
3838 	isl_map_free(map1);
3839 	isl_map_free(map2);
3840 	return NULL;
3841 }
3842 
map_intersect(__isl_take isl_map * map1,__isl_take isl_map * map2)3843 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3844 	__isl_take isl_map *map2)
3845 {
3846 	if (isl_map_check_equal_space(map1, map2) < 0)
3847 		goto error;
3848 	return map_intersect_internal(map1, map2);
3849 error:
3850 	isl_map_free(map1);
3851 	isl_map_free(map2);
3852 	return NULL;
3853 }
3854 
isl_map_intersect(__isl_take isl_map * map1,__isl_take isl_map * map2)3855 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3856 	__isl_take isl_map *map2)
3857 {
3858 	isl_map_align_params_bin(&map1, &map2);
3859 	return map_intersect(map1, map2);
3860 }
3861 
isl_set_intersect(__isl_take isl_set * set1,__isl_take isl_set * set2)3862 __isl_give isl_set *isl_set_intersect(__isl_take isl_set *set1,
3863 	__isl_take isl_set *set2)
3864 {
3865 	return set_from_map(isl_map_intersect(set_to_map(set1),
3866 					      set_to_map(set2)));
3867 }
3868 
3869 /* map_intersect_internal accepts intersections
3870  * with parameter domains, so we can just call that function.
3871  */
isl_map_intersect_params(__isl_take isl_map * map,__isl_take isl_set * params)3872 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
3873 	__isl_take isl_set *params)
3874 {
3875 	isl_map_align_params_set(&map, &params);
3876 	return map_intersect_internal(map, params);
3877 }
3878 
isl_set_intersect_params(__isl_take isl_set * set,__isl_take isl_set * params)3879 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3880 		__isl_take isl_set *params)
3881 {
3882 	return isl_map_intersect_params(set, params);
3883 }
3884 
isl_basic_map_reverse(__isl_take isl_basic_map * bmap)3885 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3886 {
3887 	isl_space *space;
3888 	unsigned pos;
3889 	isl_size n1, n2;
3890 
3891 	if (!bmap)
3892 		return NULL;
3893 	bmap = isl_basic_map_cow(bmap);
3894 	if (!bmap)
3895 		return NULL;
3896 	space = isl_space_reverse(isl_space_copy(bmap->dim));
3897 	pos = isl_basic_map_offset(bmap, isl_dim_in);
3898 	n1 = isl_basic_map_dim(bmap, isl_dim_in);
3899 	n2 = isl_basic_map_dim(bmap, isl_dim_out);
3900 	if (n1 < 0 || n2 < 0)
3901 		bmap = isl_basic_map_free(bmap);
3902 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3903 	return isl_basic_map_reset_space(bmap, space);
3904 }
3905 
3906 /* Given a basic map A -> (B -> C), return the corresponding basic map
3907  * A -> (C -> B).
3908  */
isl_basic_map_range_reverse(__isl_take isl_basic_map * bmap)3909 static __isl_give isl_basic_map *isl_basic_map_range_reverse(
3910 	__isl_take isl_basic_map *bmap)
3911 {
3912 	isl_space *space;
3913 	isl_size offset, n1, n2;
3914 
3915 	space = isl_basic_map_peek_space(bmap);
3916 	if (isl_space_check_range_is_wrapping(space) < 0)
3917 		return isl_basic_map_free(bmap);
3918 	offset = isl_basic_map_var_offset(bmap, isl_dim_out);
3919 	n1 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_in);
3920 	n2 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_out);
3921 	if (offset < 0 || n1 < 0 || n2 < 0)
3922 		return isl_basic_map_free(bmap);
3923 
3924 	bmap = isl_basic_map_swap_vars(bmap, 1 + offset, n1, n2);
3925 
3926 	space = isl_basic_map_take_space(bmap);
3927 	space = isl_space_range_reverse(space);
3928 	bmap = isl_basic_map_restore_space(bmap, space);
3929 
3930 	return bmap;
3931 }
3932 
basic_map_space_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)3933 static __isl_give isl_basic_map *basic_map_space_reset(
3934 	__isl_take isl_basic_map *bmap, enum isl_dim_type type)
3935 {
3936 	isl_space *space;
3937 
3938 	if (!bmap)
3939 		return NULL;
3940 	if (!isl_space_is_named_or_nested(bmap->dim, type))
3941 		return bmap;
3942 
3943 	space = isl_basic_map_get_space(bmap);
3944 	space = isl_space_reset(space, type);
3945 	bmap = isl_basic_map_reset_space(bmap, space);
3946 	return bmap;
3947 }
3948 
isl_basic_map_insert_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,unsigned n)3949 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3950 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
3951 	unsigned pos, unsigned n)
3952 {
3953 	isl_bool rational, is_empty;
3954 	isl_space *res_space;
3955 	struct isl_basic_map *res;
3956 	struct isl_dim_map *dim_map;
3957 	isl_size total;
3958 	unsigned off;
3959 	enum isl_dim_type t;
3960 
3961 	if (n == 0)
3962 		return basic_map_space_reset(bmap, type);
3963 
3964 	is_empty = isl_basic_map_plain_is_empty(bmap);
3965 	total = isl_basic_map_dim(bmap, isl_dim_all);
3966 	if (is_empty < 0 || total < 0)
3967 		return isl_basic_map_free(bmap);
3968 	res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3969 					type, pos, n);
3970 	if (!res_space)
3971 		return isl_basic_map_free(bmap);
3972 	if (is_empty) {
3973 		isl_basic_map_free(bmap);
3974 		return isl_basic_map_empty(res_space);
3975 	}
3976 
3977 	dim_map = isl_dim_map_alloc(bmap->ctx, total + n);
3978 	off = 0;
3979 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3980 		isl_size dim;
3981 
3982 		if (t != type) {
3983 			isl_dim_map_dim(dim_map, bmap->dim, t, off);
3984 		} else {
3985 			isl_size size = isl_basic_map_dim(bmap, t);
3986 			if (size < 0)
3987 				dim_map = isl_dim_map_free(dim_map);
3988 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3989 						0, pos, off);
3990 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
3991 						pos, size - pos, off + pos + n);
3992 		}
3993 		dim = isl_space_dim(res_space, t);
3994 		if (dim < 0)
3995 			dim_map = isl_dim_map_free(dim_map);
3996 		off += dim;
3997 	}
3998 	isl_dim_map_div(dim_map, bmap, off);
3999 
4000 	res = isl_basic_map_alloc_space(res_space,
4001 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
4002 	rational = isl_basic_map_is_rational(bmap);
4003 	if (rational < 0)
4004 		res = isl_basic_map_free(res);
4005 	if (rational)
4006 		res = isl_basic_map_set_rational(res);
4007 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4008 	return isl_basic_map_finalize(res);
4009 }
4010 
isl_basic_set_insert_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,unsigned n)4011 __isl_give isl_basic_set *isl_basic_set_insert_dims(
4012 	__isl_take isl_basic_set *bset,
4013 	enum isl_dim_type type, unsigned pos, unsigned n)
4014 {
4015 	return isl_basic_map_insert_dims(bset, type, pos, n);
4016 }
4017 
isl_basic_map_add_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned n)4018 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
4019 		enum isl_dim_type type, unsigned n)
4020 {
4021 	isl_size dim;
4022 
4023 	dim = isl_basic_map_dim(bmap, type);
4024 	if (dim < 0)
4025 		return isl_basic_map_free(bmap);
4026 	return isl_basic_map_insert_dims(bmap, type, dim, n);
4027 }
4028 
isl_basic_set_add_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned n)4029 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
4030 		enum isl_dim_type type, unsigned n)
4031 {
4032 	if (!bset)
4033 		return NULL;
4034 	isl_assert(bset->ctx, type != isl_dim_in, goto error);
4035 	return isl_basic_map_add_dims(bset, type, n);
4036 error:
4037 	isl_basic_set_free(bset);
4038 	return NULL;
4039 }
4040 
map_space_reset(__isl_take isl_map * map,enum isl_dim_type type)4041 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
4042 	enum isl_dim_type type)
4043 {
4044 	isl_space *space;
4045 
4046 	if (!map || !isl_space_is_named_or_nested(map->dim, type))
4047 		return map;
4048 
4049 	space = isl_map_get_space(map);
4050 	space = isl_space_reset(space, type);
4051 	map = isl_map_reset_space(map, space);
4052 	return map;
4053 }
4054 
isl_map_insert_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,unsigned n)4055 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
4056 		enum isl_dim_type type, unsigned pos, unsigned n)
4057 {
4058 	int i;
4059 	isl_space *space;
4060 
4061 	if (n == 0)
4062 		return map_space_reset(map, type);
4063 
4064 	map = isl_map_cow(map);
4065 	if (!map)
4066 		return NULL;
4067 
4068 	for (i = 0; i < map->n; ++i) {
4069 		map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
4070 		if (!map->p[i])
4071 			goto error;
4072 	}
4073 
4074 	space = isl_map_take_space(map);
4075 	space = isl_space_insert_dims(space, type, pos, n);
4076 	map = isl_map_restore_space(map, space);
4077 
4078 	return map;
4079 error:
4080 	isl_map_free(map);
4081 	return NULL;
4082 }
4083 
isl_set_insert_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,unsigned n)4084 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
4085 		enum isl_dim_type type, unsigned pos, unsigned n)
4086 {
4087 	return isl_map_insert_dims(set, type, pos, n);
4088 }
4089 
isl_map_add_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned n)4090 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
4091 		enum isl_dim_type type, unsigned n)
4092 {
4093 	isl_size dim;
4094 
4095 	dim = isl_map_dim(map, type);
4096 	if (dim < 0)
4097 		return isl_map_free(map);
4098 	return isl_map_insert_dims(map, type, dim, n);
4099 }
4100 
isl_set_add_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned n)4101 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
4102 		enum isl_dim_type type, unsigned n)
4103 {
4104 	if (!set)
4105 		return NULL;
4106 	isl_assert(set->ctx, type != isl_dim_in, goto error);
4107 	return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
4108 error:
4109 	isl_set_free(set);
4110 	return NULL;
4111 }
4112 
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)4113 __isl_give isl_basic_map *isl_basic_map_move_dims(
4114 	__isl_take isl_basic_map *bmap,
4115 	enum isl_dim_type dst_type, unsigned dst_pos,
4116 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4117 {
4118 	isl_space *space;
4119 	struct isl_dim_map *dim_map;
4120 	struct isl_basic_map *res;
4121 	enum isl_dim_type t;
4122 	isl_size total;
4123 	unsigned off;
4124 
4125 	if (!bmap)
4126 		return NULL;
4127 	if (n == 0) {
4128 		bmap = isl_basic_map_reset(bmap, src_type);
4129 		bmap = isl_basic_map_reset(bmap, dst_type);
4130 		return bmap;
4131 	}
4132 
4133 	if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
4134 		return isl_basic_map_free(bmap);
4135 
4136 	if (dst_type == src_type && dst_pos == src_pos)
4137 		return bmap;
4138 
4139 	isl_assert(bmap->ctx, dst_type != src_type, goto error);
4140 
4141 	if (pos(bmap->dim, dst_type) + dst_pos ==
4142 	    pos(bmap->dim, src_type) + src_pos +
4143 					    ((src_type < dst_type) ? n : 0)) {
4144 		space = isl_basic_map_take_space(bmap);
4145 		space = isl_space_move_dims(space, dst_type, dst_pos,
4146 						src_type, src_pos, n);
4147 		bmap = isl_basic_map_restore_space(bmap, space);
4148 		bmap = isl_basic_map_finalize(bmap);
4149 
4150 		return bmap;
4151 	}
4152 
4153 	total = isl_basic_map_dim(bmap, isl_dim_all);
4154 	if (total < 0)
4155 		return isl_basic_map_free(bmap);
4156 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
4157 
4158 	off = 0;
4159 	space = isl_basic_map_peek_space(bmap);
4160 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4161 		isl_size size = isl_space_dim(space, t);
4162 		if (size < 0)
4163 			dim_map = isl_dim_map_free(dim_map);
4164 		if (t == dst_type) {
4165 			isl_dim_map_dim_range(dim_map, space, t,
4166 					    0, dst_pos, off);
4167 			off += dst_pos;
4168 			isl_dim_map_dim_range(dim_map, space, src_type,
4169 					    src_pos, n, off);
4170 			off += n;
4171 			isl_dim_map_dim_range(dim_map, space, t,
4172 					    dst_pos, size - dst_pos, off);
4173 			off += size - dst_pos;
4174 		} else if (t == src_type) {
4175 			isl_dim_map_dim_range(dim_map, space, t,
4176 					    0, src_pos, off);
4177 			off += src_pos;
4178 			isl_dim_map_dim_range(dim_map, space, t,
4179 					src_pos + n, size - src_pos - n, off);
4180 			off += size - src_pos - n;
4181 		} else {
4182 			isl_dim_map_dim(dim_map, space, t, off);
4183 			off += size;
4184 		}
4185 	}
4186 	isl_dim_map_div(dim_map, bmap, off);
4187 
4188 	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4189 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
4190 	bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4191 	space = isl_basic_map_take_space(bmap);
4192 	space = isl_space_move_dims(space, dst_type, dst_pos,
4193 					src_type, src_pos, n);
4194 	bmap = isl_basic_map_restore_space(bmap, space);
4195 	if (!bmap)
4196 		goto error;
4197 
4198 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4199 	bmap = isl_basic_map_gauss(bmap, NULL);
4200 	bmap = isl_basic_map_finalize(bmap);
4201 
4202 	return bmap;
4203 error:
4204 	isl_basic_map_free(bmap);
4205 	return NULL;
4206 }
4207 
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)4208 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4209 	enum isl_dim_type dst_type, unsigned dst_pos,
4210 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4211 {
4212 	isl_basic_map *bmap = bset_to_bmap(bset);
4213 	bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4214 					src_type, src_pos, n);
4215 	return bset_from_bmap(bmap);
4216 }
4217 
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)4218 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4219 	enum isl_dim_type dst_type, unsigned dst_pos,
4220 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4221 {
4222 	if (!set)
4223 		return NULL;
4224 	isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4225 	return set_from_map(isl_map_move_dims(set_to_map(set),
4226 				    dst_type, dst_pos, src_type, src_pos, n));
4227 error:
4228 	isl_set_free(set);
4229 	return NULL;
4230 }
4231 
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)4232 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4233 	enum isl_dim_type dst_type, unsigned dst_pos,
4234 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4235 {
4236 	int i;
4237 	isl_space *space;
4238 
4239 	if (n == 0) {
4240 		map = isl_map_reset(map, src_type);
4241 		map = isl_map_reset(map, dst_type);
4242 		return map;
4243 	}
4244 
4245 	if (isl_map_check_range(map, src_type, src_pos, n))
4246 		return isl_map_free(map);
4247 
4248 	if (dst_type == src_type && dst_pos == src_pos)
4249 		return map;
4250 
4251 	isl_assert(map->ctx, dst_type != src_type, goto error);
4252 
4253 	map = isl_map_cow(map);
4254 	if (!map)
4255 		return NULL;
4256 
4257 	for (i = 0; i < map->n; ++i) {
4258 		map->p[i] = isl_basic_map_move_dims(map->p[i],
4259 						dst_type, dst_pos,
4260 						src_type, src_pos, n);
4261 		if (!map->p[i])
4262 			goto error;
4263 	}
4264 
4265 	space = isl_map_take_space(map);
4266 	space = isl_space_move_dims(space, dst_type, dst_pos,
4267 					    src_type, src_pos, n);
4268 	map = isl_map_restore_space(map, space);
4269 
4270 	return map;
4271 error:
4272 	isl_map_free(map);
4273 	return NULL;
4274 }
4275 
4276 /* Move the specified dimensions to the last columns right before
4277  * the divs.  Don't change the dimension specification of bmap.
4278  * That's the responsibility of the caller.
4279  */
move_last(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4280 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4281 	enum isl_dim_type type, unsigned first, unsigned n)
4282 {
4283 	isl_space *space;
4284 	struct isl_dim_map *dim_map;
4285 	struct isl_basic_map *res;
4286 	enum isl_dim_type t;
4287 	isl_size total;
4288 	unsigned off;
4289 
4290 	if (!bmap)
4291 		return NULL;
4292 	if (isl_basic_map_offset(bmap, type) + first + n ==
4293 				isl_basic_map_offset(bmap, isl_dim_div))
4294 		return bmap;
4295 
4296 	total = isl_basic_map_dim(bmap, isl_dim_all);
4297 	if (total < 0)
4298 		return isl_basic_map_free(bmap);
4299 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
4300 
4301 	off = 0;
4302 	space = isl_basic_map_peek_space(bmap);
4303 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4304 		isl_size size = isl_space_dim(space, t);
4305 		if (size < 0)
4306 			dim_map = isl_dim_map_free(dim_map);
4307 		if (t == type) {
4308 			isl_dim_map_dim_range(dim_map, space, t,
4309 					    0, first, off);
4310 			off += first;
4311 			isl_dim_map_dim_range(dim_map, space, t,
4312 					    first, n, total - bmap->n_div - n);
4313 			isl_dim_map_dim_range(dim_map, space, t,
4314 					    first + n, size - (first + n), off);
4315 			off += size - (first + n);
4316 		} else {
4317 			isl_dim_map_dim(dim_map, space, t, off);
4318 			off += size;
4319 		}
4320 	}
4321 	isl_dim_map_div(dim_map, bmap, off + n);
4322 
4323 	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4324 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
4325 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4326 	return res;
4327 }
4328 
4329 /* Insert "n" rows in the divs of "bmap".
4330  *
4331  * The number of columns is not changed, which means that the last
4332  * dimensions of "bmap" are being reintepreted as the new divs.
4333  * The space of "bmap" is not adjusted, however, which means
4334  * that "bmap" is left in an inconsistent state.  Removing "n" dimensions
4335  * from the space of "bmap" is the responsibility of the caller.
4336  */
insert_div_rows(__isl_take isl_basic_map * bmap,int n)4337 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4338 	int n)
4339 {
4340 	int i;
4341 	size_t row_size;
4342 	isl_int **new_div;
4343 	isl_int *old;
4344 
4345 	bmap = isl_basic_map_cow(bmap);
4346 	if (!bmap)
4347 		return NULL;
4348 
4349 	row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;
4350 	old = bmap->block2.data;
4351 	bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4352 					(bmap->extra + n) * (1 + row_size));
4353 	if (!bmap->block2.data)
4354 		return isl_basic_map_free(bmap);
4355 	new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4356 	if (!new_div)
4357 		return isl_basic_map_free(bmap);
4358 	for (i = 0; i < n; ++i) {
4359 		new_div[i] = bmap->block2.data +
4360 				(bmap->extra + i) * (1 + row_size);
4361 		isl_seq_clr(new_div[i], 1 + row_size);
4362 	}
4363 	for (i = 0; i < bmap->extra; ++i)
4364 		new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4365 	free(bmap->div);
4366 	bmap->div = new_div;
4367 	bmap->n_div += n;
4368 	bmap->extra += n;
4369 
4370 	return bmap;
4371 }
4372 
4373 /* Drop constraints from "bmap" that only involve the variables
4374  * of "type" in the range [first, first + n] that are not related
4375  * to any of the variables outside that interval.
4376  * These constraints cannot influence the values for the variables
4377  * outside the interval, except in case they cause "bmap" to be empty.
4378  * Only drop the constraints if "bmap" is known to be non-empty.
4379  */
drop_irrelevant_constraints(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4380 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4381 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
4382 	unsigned first, unsigned n)
4383 {
4384 	int i;
4385 	int *groups;
4386 	isl_size dim, n_div;
4387 	isl_bool non_empty;
4388 
4389 	non_empty = isl_basic_map_plain_is_non_empty(bmap);
4390 	if (non_empty < 0)
4391 		return isl_basic_map_free(bmap);
4392 	if (!non_empty)
4393 		return bmap;
4394 
4395 	dim = isl_basic_map_dim(bmap, isl_dim_all);
4396 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
4397 	if (dim < 0 || n_div < 0)
4398 		return isl_basic_map_free(bmap);
4399 	groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4400 	if (!groups)
4401 		return isl_basic_map_free(bmap);
4402 	first += isl_basic_map_offset(bmap, type) - 1;
4403 	for (i = 0; i < first; ++i)
4404 		groups[i] = -1;
4405 	for (i = first + n; i < dim - n_div; ++i)
4406 		groups[i] = -1;
4407 
4408 	bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4409 
4410 	return bmap;
4411 }
4412 
4413 /* Turn the n dimensions of type type, starting at first
4414  * into existentially quantified variables.
4415  *
4416  * If a subset of the projected out variables are unrelated
4417  * to any of the variables that remain, then the constraints
4418  * involving this subset are simply dropped first.
4419  */
isl_basic_map_project_out(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4420 __isl_give isl_basic_map *isl_basic_map_project_out(
4421 		__isl_take isl_basic_map *bmap,
4422 		enum isl_dim_type type, unsigned first, unsigned n)
4423 {
4424 	isl_bool empty;
4425 	isl_space *space;
4426 
4427 	if (n == 0)
4428 		return basic_map_space_reset(bmap, type);
4429 	if (type == isl_dim_div)
4430 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4431 			"cannot project out existentially quantified variables",
4432 			return isl_basic_map_free(bmap));
4433 
4434 	empty = isl_basic_map_plain_is_empty(bmap);
4435 	if (empty < 0)
4436 		return isl_basic_map_free(bmap);
4437 	if (empty)
4438 		bmap = isl_basic_map_set_to_empty(bmap);
4439 
4440 	bmap = drop_irrelevant_constraints(bmap, type, first, n);
4441 	if (!bmap)
4442 		return NULL;
4443 
4444 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4445 		return isl_basic_map_remove_dims(bmap, type, first, n);
4446 
4447 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4448 		return isl_basic_map_free(bmap);
4449 
4450 	bmap = move_last(bmap, type, first, n);
4451 	bmap = isl_basic_map_cow(bmap);
4452 	bmap = insert_div_rows(bmap, n);
4453 
4454 	space = isl_basic_map_take_space(bmap);
4455 	space = isl_space_drop_dims(space, type, first, n);
4456 	bmap = isl_basic_map_restore_space(bmap, space);
4457 	bmap = isl_basic_map_simplify(bmap);
4458 	bmap = isl_basic_map_drop_redundant_divs(bmap);
4459 	return isl_basic_map_finalize(bmap);
4460 }
4461 
4462 /* Turn the n dimensions of type type, starting at first
4463  * into existentially quantified variables.
4464  */
isl_basic_set_project_out(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)4465 __isl_give isl_basic_set *isl_basic_set_project_out(
4466 	__isl_take isl_basic_set *bset, enum isl_dim_type type,
4467 	unsigned first, unsigned n)
4468 {
4469 	return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4470 							type, first, n));
4471 }
4472 
4473 /* Turn the n dimensions of type type, starting at first
4474  * into existentially quantified variables.
4475  */
isl_map_project_out(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)4476 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4477 		enum isl_dim_type type, unsigned first, unsigned n)
4478 {
4479 	int i;
4480 	isl_space *space;
4481 
4482 	if (n == 0)
4483 		return map_space_reset(map, type);
4484 
4485 	if (isl_map_check_range(map, type, first, n) < 0)
4486 		return isl_map_free(map);
4487 
4488 	map = isl_map_cow(map);
4489 	if (!map)
4490 		return NULL;
4491 
4492 	for (i = 0; i < map->n; ++i) {
4493 		map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4494 		if (!map->p[i])
4495 			goto error;
4496 	}
4497 
4498 	if (map->n > 1)
4499 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
4500 	map = isl_map_unmark_normalized(map);
4501 
4502 	space = isl_map_take_space(map);
4503 	space = isl_space_drop_dims(space, type, first, n);
4504 	map = isl_map_restore_space(map, space);
4505 
4506 	return map;
4507 error:
4508 	isl_map_free(map);
4509 	return NULL;
4510 }
4511 
4512 #undef TYPE
4513 #define TYPE	isl_map
4514 #include "isl_project_out_all_params_templ.c"
4515 
4516 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4517  * into existentially quantified variables.
4518  */
isl_map_project_onto(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)4519 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4520 	enum isl_dim_type type, unsigned first, unsigned n)
4521 {
4522 	isl_size dim;
4523 
4524 	dim = isl_map_dim(map, type);
4525 	if (isl_map_check_range(map, type, first, n) < 0 || dim < 0)
4526 		return isl_map_free(map);
4527 	map = isl_map_project_out(map, type, first + n, dim - (first + n));
4528 	map = isl_map_project_out(map, type, 0, first);
4529 	return map;
4530 }
4531 
4532 /* Turn the n dimensions of type type, starting at first
4533  * into existentially quantified variables.
4534  */
isl_set_project_out(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)4535 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4536 		enum isl_dim_type type, unsigned first, unsigned n)
4537 {
4538 	return set_from_map(isl_map_project_out(set_to_map(set),
4539 						type, first, n));
4540 }
4541 
4542 /* If "set" involves a parameter with identifier "id",
4543  * then turn it into an existentially quantified variable.
4544  */
isl_set_project_out_param_id(__isl_take isl_set * set,__isl_take isl_id * id)4545 __isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,
4546 	__isl_take isl_id *id)
4547 {
4548 	int pos;
4549 
4550 	if (!set || !id)
4551 		goto error;
4552 	pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
4553 	isl_id_free(id);
4554 	if (pos < 0)
4555 		return set;
4556 	return isl_set_project_out(set, isl_dim_param, pos, 1);
4557 error:
4558 	isl_set_free(set);
4559 	isl_id_free(id);
4560 	return NULL;
4561 }
4562 
4563 /* If "set" involves any of the parameters with identifiers in "list",
4564  * then turn them into existentially quantified variables.
4565  */
isl_set_project_out_param_id_list(__isl_take isl_set * set,__isl_take isl_id_list * list)4566 __isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,
4567 	__isl_take isl_id_list *list)
4568 {
4569 	int i;
4570 	isl_size n;
4571 
4572 	n = isl_id_list_size(list);
4573 	if (n < 0)
4574 		goto error;
4575 	for (i = 0; i < n; ++i) {
4576 		isl_id *id;
4577 
4578 		id = isl_id_list_get_at(list, i);
4579 		set = isl_set_project_out_param_id(set, id);
4580 	}
4581 
4582 	isl_id_list_free(list);
4583 	return set;
4584 error:
4585 	isl_id_list_free(list);
4586 	isl_set_free(set);
4587 	return NULL;
4588 }
4589 
4590 /* Project out all parameters from "set" by existentially quantifying
4591  * over them.
4592  */
isl_set_project_out_all_params(__isl_take isl_set * set)4593 __isl_give isl_set *isl_set_project_out_all_params(__isl_take isl_set *set)
4594 {
4595 	return set_from_map(isl_map_project_out_all_params(set_to_map(set)));
4596 }
4597 
4598 /* Return a map that projects the elements in "set" onto their
4599  * "n" set dimensions starting at "first".
4600  * "type" should be equal to isl_dim_set.
4601  */
isl_set_project_onto_map(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)4602 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4603 	enum isl_dim_type type, unsigned first, unsigned n)
4604 {
4605 	int i;
4606 	isl_map *map;
4607 
4608 	if (type != isl_dim_set)
4609 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
4610 			"only set dimensions can be projected out", goto error);
4611 	if (isl_set_check_range(set, type, first, n) < 0)
4612 		return isl_set_free(set);
4613 
4614 	map = isl_map_from_domain(set);
4615 	map = isl_map_add_dims(map, isl_dim_out, n);
4616 	for (i = 0; i < n; ++i)
4617 		map = isl_map_equate(map, isl_dim_in, first + i,
4618 					isl_dim_out, i);
4619 	return map;
4620 error:
4621 	isl_set_free(set);
4622 	return NULL;
4623 }
4624 
add_divs(__isl_take isl_basic_map * bmap,unsigned n)4625 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4626 	unsigned n)
4627 {
4628 	int i, j;
4629 	isl_size total;
4630 
4631 	total = isl_basic_map_dim(bmap, isl_dim_all);
4632 	if (total < 0)
4633 		return isl_basic_map_free(bmap);
4634 	for (i = 0; i < n; ++i) {
4635 		j = isl_basic_map_alloc_div(bmap);
4636 		if (j < 0)
4637 			goto error;
4638 		isl_seq_clr(bmap->div[j], 1 + 1 + total);
4639 	}
4640 	return bmap;
4641 error:
4642 	isl_basic_map_free(bmap);
4643 	return NULL;
4644 }
4645 
4646 /* Does "bmap2" apply to the range of "bmap1" (ignoring parameters)?
4647  */
isl_basic_map_applies_range(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)4648 isl_bool isl_basic_map_applies_range(__isl_keep isl_basic_map *bmap1,
4649 	__isl_keep isl_basic_map *bmap2)
4650 {
4651 	isl_space *space1, *space2;
4652 
4653 	space1 = isl_basic_map_peek_space(bmap1);
4654 	space2 = isl_basic_map_peek_space(bmap2);
4655 	return isl_space_tuple_is_equal(space1, isl_dim_out,
4656 					space2, isl_dim_in);
4657 }
4658 
4659 /* Check that "bmap2" applies to the range of "bmap1" (ignoring parameters).
4660  */
isl_basic_map_check_applies_range(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)4661 static isl_stat isl_basic_map_check_applies_range(
4662 	__isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
4663 {
4664 	isl_bool equal;
4665 
4666 	equal = isl_basic_map_applies_range(bmap1, bmap2);
4667 	if (equal < 0)
4668 		return isl_stat_error;
4669 	if (!equal)
4670 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4671 			"spaces don't match", return isl_stat_error);
4672 	return isl_stat_ok;
4673 }
4674 
isl_basic_map_apply_range(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4675 __isl_give isl_basic_map *isl_basic_map_apply_range(
4676 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
4677 {
4678 	isl_space *space_result = NULL;
4679 	struct isl_basic_map *bmap;
4680 	isl_size n_in, n_out, n, nparam;
4681 	unsigned total, pos;
4682 	struct isl_dim_map *dim_map1, *dim_map2;
4683 
4684 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4685 		goto error;
4686 	if (isl_basic_map_check_applies_range(bmap1, bmap2) < 0)
4687 		goto error;
4688 
4689 	n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4690 	n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4691 	n = isl_basic_map_dim(bmap1, isl_dim_out);
4692 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4693 	if (n_in < 0 || n_out < 0 || n < 0 || nparam < 0)
4694 		goto error;
4695 
4696 	space_result = isl_space_join(isl_basic_map_get_space(bmap1),
4697 				  isl_basic_map_get_space(bmap2));
4698 
4699 	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4700 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4701 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4702 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4703 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4704 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4705 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4706 	isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4707 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4708 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4709 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4710 
4711 	bmap = isl_basic_map_alloc_space(space_result,
4712 			bmap1->n_div + bmap2->n_div + n,
4713 			bmap1->n_eq + bmap2->n_eq,
4714 			bmap1->n_ineq + bmap2->n_ineq);
4715 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4716 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4717 	bmap = add_divs(bmap, n);
4718 	bmap = isl_basic_map_simplify(bmap);
4719 	bmap = isl_basic_map_drop_redundant_divs(bmap);
4720 	return isl_basic_map_finalize(bmap);
4721 error:
4722 	isl_basic_map_free(bmap1);
4723 	isl_basic_map_free(bmap2);
4724 	return NULL;
4725 }
4726 
isl_basic_set_apply(__isl_take isl_basic_set * bset,__isl_take isl_basic_map * bmap)4727 __isl_give isl_basic_set *isl_basic_set_apply(__isl_take isl_basic_set *bset,
4728 	__isl_take isl_basic_map *bmap)
4729 {
4730 	if (isl_basic_map_check_compatible_domain(bmap, bset) < 0)
4731 		goto error;
4732 
4733 	return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4734 							bmap));
4735 error:
4736 	isl_basic_set_free(bset);
4737 	isl_basic_map_free(bmap);
4738 	return NULL;
4739 }
4740 
isl_basic_map_apply_domain(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4741 __isl_give isl_basic_map *isl_basic_map_apply_domain(
4742 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
4743 {
4744 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4745 		goto error;
4746 	if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4747 					bmap2->dim, isl_dim_in))
4748 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4749 			"spaces don't match", goto error);
4750 
4751 	bmap1 = isl_basic_map_reverse(bmap1);
4752 	bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4753 	return isl_basic_map_reverse(bmap1);
4754 error:
4755 	isl_basic_map_free(bmap1);
4756 	isl_basic_map_free(bmap2);
4757 	return NULL;
4758 }
4759 
4760 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4761  * A \cap B -> f(A) + f(B)
4762  */
isl_basic_map_sum(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4763 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4764 	__isl_take isl_basic_map *bmap2)
4765 {
4766 	isl_size n_in, n_out, nparam;
4767 	unsigned total, pos;
4768 	struct isl_basic_map *bmap = NULL;
4769 	struct isl_dim_map *dim_map1, *dim_map2;
4770 	int i;
4771 
4772 	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
4773 		goto error;
4774 
4775 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4776 	n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4777 	n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4778 	if (nparam < 0 || n_in < 0 || n_out < 0)
4779 		goto error;
4780 
4781 	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4782 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4783 	dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4784 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4785 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4786 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4787 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4788 	isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4789 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4790 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4791 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4792 
4793 	bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4794 			bmap1->n_div + bmap2->n_div + 2 * n_out,
4795 			bmap1->n_eq + bmap2->n_eq + n_out,
4796 			bmap1->n_ineq + bmap2->n_ineq);
4797 	for (i = 0; i < n_out; ++i) {
4798 		int j = isl_basic_map_alloc_equality(bmap);
4799 		if (j < 0)
4800 			goto error;
4801 		isl_seq_clr(bmap->eq[j], 1+total);
4802 		isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4803 		isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4804 		isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4805 	}
4806 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4807 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4808 	bmap = add_divs(bmap, 2 * n_out);
4809 
4810 	bmap = isl_basic_map_simplify(bmap);
4811 	return isl_basic_map_finalize(bmap);
4812 error:
4813 	isl_basic_map_free(bmap);
4814 	isl_basic_map_free(bmap1);
4815 	isl_basic_map_free(bmap2);
4816 	return NULL;
4817 }
4818 
4819 /* Given two maps A -> f(A) and B -> g(B), construct a map
4820  * A \cap B -> f(A) + f(B)
4821  */
isl_map_sum(__isl_take isl_map * map1,__isl_take isl_map * map2)4822 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4823 	__isl_take isl_map *map2)
4824 {
4825 	struct isl_map *result;
4826 	int i, j;
4827 
4828 	if (isl_map_check_equal_space(map1, map2) < 0)
4829 		goto error;
4830 
4831 	result = isl_map_alloc_space(isl_space_copy(map1->dim),
4832 				map1->n * map2->n, 0);
4833 	if (!result)
4834 		goto error;
4835 	for (i = 0; i < map1->n; ++i)
4836 		for (j = 0; j < map2->n; ++j) {
4837 			struct isl_basic_map *part;
4838 			part = isl_basic_map_sum(
4839 				    isl_basic_map_copy(map1->p[i]),
4840 				    isl_basic_map_copy(map2->p[j]));
4841 			if (isl_basic_map_is_empty(part))
4842 				isl_basic_map_free(part);
4843 			else
4844 				result = isl_map_add_basic_map(result, part);
4845 			if (!result)
4846 				goto error;
4847 		}
4848 	isl_map_free(map1);
4849 	isl_map_free(map2);
4850 	return result;
4851 error:
4852 	isl_map_free(map1);
4853 	isl_map_free(map2);
4854 	return NULL;
4855 }
4856 
isl_set_sum(__isl_take isl_set * set1,__isl_take isl_set * set2)4857 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4858 	__isl_take isl_set *set2)
4859 {
4860 	return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4861 }
4862 
4863 /* Given a basic map A -> f(A), construct A -> -f(A).
4864  */
isl_basic_map_neg(__isl_take isl_basic_map * bmap)4865 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4866 {
4867 	int i, j;
4868 	unsigned off;
4869 	isl_size n;
4870 
4871 	bmap = isl_basic_map_cow(bmap);
4872 	n = isl_basic_map_dim(bmap, isl_dim_out);
4873 	if (n < 0)
4874 		return isl_basic_map_free(bmap);
4875 
4876 	off = isl_basic_map_offset(bmap, isl_dim_out);
4877 	for (i = 0; i < bmap->n_eq; ++i)
4878 		for (j = 0; j < n; ++j)
4879 			isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4880 	for (i = 0; i < bmap->n_ineq; ++i)
4881 		for (j = 0; j < n; ++j)
4882 			isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4883 	for (i = 0; i < bmap->n_div; ++i)
4884 		for (j = 0; j < n; ++j)
4885 			isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4886 	bmap = isl_basic_map_gauss(bmap, NULL);
4887 	return isl_basic_map_finalize(bmap);
4888 }
4889 
isl_basic_set_neg(__isl_take isl_basic_set * bset)4890 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4891 {
4892 	return isl_basic_map_neg(bset);
4893 }
4894 
4895 /* Given a map A -> f(A), construct A -> -f(A).
4896  */
isl_map_neg(__isl_take isl_map * map)4897 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4898 {
4899 	int i;
4900 
4901 	map = isl_map_cow(map);
4902 	if (!map)
4903 		return NULL;
4904 
4905 	for (i = 0; i < map->n; ++i) {
4906 		map->p[i] = isl_basic_map_neg(map->p[i]);
4907 		if (!map->p[i])
4908 			goto error;
4909 	}
4910 
4911 	return map;
4912 error:
4913 	isl_map_free(map);
4914 	return NULL;
4915 }
4916 
isl_set_neg(__isl_take isl_set * set)4917 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4918 {
4919 	return set_from_map(isl_map_neg(set_to_map(set)));
4920 }
4921 
4922 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4923  * A -> floor(f(A)/d).
4924  */
isl_basic_map_floordiv(__isl_take isl_basic_map * bmap,isl_int d)4925 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4926 		isl_int d)
4927 {
4928 	isl_size n_in, n_out, nparam;
4929 	unsigned total, pos;
4930 	struct isl_basic_map *result = NULL;
4931 	struct isl_dim_map *dim_map;
4932 	int i;
4933 
4934 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
4935 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
4936 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
4937 	if (nparam < 0 || n_in < 0 || n_out < 0)
4938 		return isl_basic_map_free(bmap);
4939 
4940 	total = nparam + n_in + n_out + bmap->n_div + n_out;
4941 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
4942 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4943 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4944 	isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4945 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4946 
4947 	result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4948 			bmap->n_div + n_out,
4949 			bmap->n_eq, bmap->n_ineq + 2 * n_out);
4950 	result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4951 	result = add_divs(result, n_out);
4952 	for (i = 0; i < n_out; ++i) {
4953 		int j;
4954 		j = isl_basic_map_alloc_inequality(result);
4955 		if (j < 0)
4956 			goto error;
4957 		isl_seq_clr(result->ineq[j], 1+total);
4958 		isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4959 		isl_int_set_si(result->ineq[j][1+pos+i], 1);
4960 		j = isl_basic_map_alloc_inequality(result);
4961 		if (j < 0)
4962 			goto error;
4963 		isl_seq_clr(result->ineq[j], 1+total);
4964 		isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4965 		isl_int_set_si(result->ineq[j][1+pos+i], -1);
4966 		isl_int_sub_ui(result->ineq[j][0], d, 1);
4967 	}
4968 
4969 	result = isl_basic_map_simplify(result);
4970 	return isl_basic_map_finalize(result);
4971 error:
4972 	isl_basic_map_free(result);
4973 	return NULL;
4974 }
4975 
4976 /* Given a map A -> f(A) and an integer d, construct a map
4977  * A -> floor(f(A)/d).
4978  */
isl_map_floordiv(__isl_take isl_map * map,isl_int d)4979 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4980 {
4981 	int i;
4982 
4983 	map = isl_map_cow(map);
4984 	if (!map)
4985 		return NULL;
4986 
4987 	ISL_F_CLR(map, ISL_MAP_DISJOINT);
4988 	for (i = 0; i < map->n; ++i) {
4989 		map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4990 		if (!map->p[i])
4991 			goto error;
4992 	}
4993 	map = isl_map_unmark_normalized(map);
4994 
4995 	return map;
4996 error:
4997 	isl_map_free(map);
4998 	return NULL;
4999 }
5000 
5001 /* Given a map A -> f(A) and an integer d, construct a map
5002  * A -> floor(f(A)/d).
5003  */
isl_map_floordiv_val(__isl_take isl_map * map,__isl_take isl_val * d)5004 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
5005 	__isl_take isl_val *d)
5006 {
5007 	if (!map || !d)
5008 		goto error;
5009 	if (!isl_val_is_int(d))
5010 		isl_die(isl_val_get_ctx(d), isl_error_invalid,
5011 			"expecting integer denominator", goto error);
5012 	map = isl_map_floordiv(map, d->n);
5013 	isl_val_free(d);
5014 	return map;
5015 error:
5016 	isl_map_free(map);
5017 	isl_val_free(d);
5018 	return NULL;
5019 }
5020 
var_equal(__isl_take isl_basic_map * bmap,unsigned pos)5021 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
5022 	unsigned pos)
5023 {
5024 	int i;
5025 	isl_size nparam;
5026 	isl_size n_in;
5027 	isl_size total;
5028 
5029 	total = isl_basic_map_dim(bmap, isl_dim_all);
5030 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5031 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5032 	if (total < 0 || nparam < 0 || n_in < 0)
5033 		return isl_basic_map_free(bmap);
5034 	i = isl_basic_map_alloc_equality(bmap);
5035 	if (i < 0)
5036 		goto error;
5037 	isl_seq_clr(bmap->eq[i], 1 + total);
5038 	isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
5039 	isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
5040 	return isl_basic_map_finalize(bmap);
5041 error:
5042 	isl_basic_map_free(bmap);
5043 	return NULL;
5044 }
5045 
5046 /* Add a constraint to "bmap" expressing i_pos < o_pos
5047  */
var_less(__isl_take isl_basic_map * bmap,unsigned pos)5048 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
5049 	unsigned pos)
5050 {
5051 	int i;
5052 	isl_size nparam;
5053 	isl_size n_in;
5054 	isl_size total;
5055 
5056 	total = isl_basic_map_dim(bmap, isl_dim_all);
5057 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5058 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5059 	if (total < 0 || nparam < 0 || n_in < 0)
5060 		return isl_basic_map_free(bmap);
5061 	i = isl_basic_map_alloc_inequality(bmap);
5062 	if (i < 0)
5063 		goto error;
5064 	isl_seq_clr(bmap->ineq[i], 1 + total);
5065 	isl_int_set_si(bmap->ineq[i][0], -1);
5066 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5067 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5068 	return isl_basic_map_finalize(bmap);
5069 error:
5070 	isl_basic_map_free(bmap);
5071 	return NULL;
5072 }
5073 
5074 /* Add a constraint to "bmap" expressing i_pos <= o_pos
5075  */
var_less_or_equal(__isl_take isl_basic_map * bmap,unsigned pos)5076 static __isl_give isl_basic_map *var_less_or_equal(
5077 	__isl_take isl_basic_map *bmap, unsigned pos)
5078 {
5079 	int i;
5080 	isl_size nparam;
5081 	isl_size n_in;
5082 	isl_size total;
5083 
5084 	total = isl_basic_map_dim(bmap, isl_dim_all);
5085 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5086 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5087 	if (total < 0 || nparam < 0 || n_in < 0)
5088 		return isl_basic_map_free(bmap);
5089 	i = isl_basic_map_alloc_inequality(bmap);
5090 	if (i < 0)
5091 		goto error;
5092 	isl_seq_clr(bmap->ineq[i], 1 + total);
5093 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5094 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5095 	return isl_basic_map_finalize(bmap);
5096 error:
5097 	isl_basic_map_free(bmap);
5098 	return NULL;
5099 }
5100 
5101 /* Add a constraint to "bmap" expressing i_pos > o_pos
5102  */
var_more(__isl_take isl_basic_map * bmap,unsigned pos)5103 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
5104 	unsigned pos)
5105 {
5106 	int i;
5107 	isl_size nparam;
5108 	isl_size n_in;
5109 	isl_size total;
5110 
5111 	total = isl_basic_map_dim(bmap, isl_dim_all);
5112 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5113 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5114 	if (total < 0 || nparam < 0 || n_in < 0)
5115 		return isl_basic_map_free(bmap);
5116 	i = isl_basic_map_alloc_inequality(bmap);
5117 	if (i < 0)
5118 		goto error;
5119 	isl_seq_clr(bmap->ineq[i], 1 + total);
5120 	isl_int_set_si(bmap->ineq[i][0], -1);
5121 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5122 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5123 	return isl_basic_map_finalize(bmap);
5124 error:
5125 	isl_basic_map_free(bmap);
5126 	return NULL;
5127 }
5128 
5129 /* Add a constraint to "bmap" expressing i_pos >= o_pos
5130  */
var_more_or_equal(__isl_take isl_basic_map * bmap,unsigned pos)5131 static __isl_give isl_basic_map *var_more_or_equal(
5132 	__isl_take isl_basic_map *bmap, unsigned pos)
5133 {
5134 	int i;
5135 	isl_size nparam;
5136 	isl_size n_in;
5137 	isl_size total;
5138 
5139 	total = isl_basic_map_dim(bmap, isl_dim_all);
5140 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5141 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5142 	if (total < 0 || nparam < 0 || n_in < 0)
5143 		return isl_basic_map_free(bmap);
5144 	i = isl_basic_map_alloc_inequality(bmap);
5145 	if (i < 0)
5146 		goto error;
5147 	isl_seq_clr(bmap->ineq[i], 1 + total);
5148 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5149 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5150 	return isl_basic_map_finalize(bmap);
5151 error:
5152 	isl_basic_map_free(bmap);
5153 	return NULL;
5154 }
5155 
isl_basic_map_equal(__isl_take isl_space * space,unsigned n_equal)5156 __isl_give isl_basic_map *isl_basic_map_equal(
5157 	__isl_take isl_space *space, unsigned n_equal)
5158 {
5159 	int i;
5160 	struct isl_basic_map *bmap;
5161 	bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
5162 	if (!bmap)
5163 		return NULL;
5164 	for (i = 0; i < n_equal && bmap; ++i)
5165 		bmap = var_equal(bmap, i);
5166 	return isl_basic_map_finalize(bmap);
5167 }
5168 
5169 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
5170  */
isl_basic_map_less_at(__isl_take isl_space * space,unsigned pos)5171 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
5172 	unsigned pos)
5173 {
5174 	int i;
5175 	struct isl_basic_map *bmap;
5176 	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5177 	if (!bmap)
5178 		return NULL;
5179 	for (i = 0; i < pos && bmap; ++i)
5180 		bmap = var_equal(bmap, i);
5181 	if (bmap)
5182 		bmap = var_less(bmap, pos);
5183 	return isl_basic_map_finalize(bmap);
5184 }
5185 
5186 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
5187  */
isl_basic_map_less_or_equal_at(__isl_take isl_space * space,unsigned pos)5188 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
5189 	__isl_take isl_space *space, unsigned pos)
5190 {
5191 	int i;
5192 	isl_basic_map *bmap;
5193 
5194 	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5195 	for (i = 0; i < pos; ++i)
5196 		bmap = var_equal(bmap, i);
5197 	bmap = var_less_or_equal(bmap, pos);
5198 	return isl_basic_map_finalize(bmap);
5199 }
5200 
5201 /* Return a relation on "space" expressing i_pos > o_pos
5202  */
isl_basic_map_more_at(__isl_take isl_space * space,unsigned pos)5203 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
5204 	unsigned pos)
5205 {
5206 	int i;
5207 	struct isl_basic_map *bmap;
5208 	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5209 	if (!bmap)
5210 		return NULL;
5211 	for (i = 0; i < pos && bmap; ++i)
5212 		bmap = var_equal(bmap, i);
5213 	if (bmap)
5214 		bmap = var_more(bmap, pos);
5215 	return isl_basic_map_finalize(bmap);
5216 }
5217 
5218 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
5219  */
isl_basic_map_more_or_equal_at(__isl_take isl_space * space,unsigned pos)5220 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
5221 	__isl_take isl_space *space, unsigned pos)
5222 {
5223 	int i;
5224 	isl_basic_map *bmap;
5225 
5226 	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5227 	for (i = 0; i < pos; ++i)
5228 		bmap = var_equal(bmap, i);
5229 	bmap = var_more_or_equal(bmap, pos);
5230 	return isl_basic_map_finalize(bmap);
5231 }
5232 
map_lex_lte_first(__isl_take isl_space * space,unsigned n,int equal)5233 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
5234 	unsigned n, int equal)
5235 {
5236 	struct isl_map *map;
5237 	int i;
5238 
5239 	if (n == 0 && equal)
5240 		return isl_map_universe(space);
5241 
5242 	map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5243 
5244 	for (i = 0; i + 1 < n; ++i)
5245 		map = isl_map_add_basic_map(map,
5246 				  isl_basic_map_less_at(isl_space_copy(space), i));
5247 	if (n > 0) {
5248 		if (equal)
5249 			map = isl_map_add_basic_map(map,
5250 			      isl_basic_map_less_or_equal_at(space, n - 1));
5251 		else
5252 			map = isl_map_add_basic_map(map,
5253 			      isl_basic_map_less_at(space, n - 1));
5254 	} else
5255 		isl_space_free(space);
5256 
5257 	return map;
5258 }
5259 
map_lex_lte(__isl_take isl_space * space,int equal)5260 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
5261 {
5262 	if (!space)
5263 		return NULL;
5264 	return map_lex_lte_first(space, space->n_out, equal);
5265 }
5266 
isl_map_lex_lt_first(__isl_take isl_space * space,unsigned n)5267 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *space,
5268 	unsigned n)
5269 {
5270 	return map_lex_lte_first(space, n, 0);
5271 }
5272 
isl_map_lex_le_first(__isl_take isl_space * space,unsigned n)5273 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *space,
5274 	unsigned n)
5275 {
5276 	return map_lex_lte_first(space, n, 1);
5277 }
5278 
isl_map_lex_lt(__isl_take isl_space * set_space)5279 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_space)
5280 {
5281 	return map_lex_lte(isl_space_map_from_set(set_space), 0);
5282 }
5283 
isl_map_lex_le(__isl_take isl_space * set_space)5284 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_space)
5285 {
5286 	return map_lex_lte(isl_space_map_from_set(set_space), 1);
5287 }
5288 
map_lex_gte_first(__isl_take isl_space * space,unsigned n,int equal)5289 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5290 	unsigned n, int equal)
5291 {
5292 	struct isl_map *map;
5293 	int i;
5294 
5295 	if (n == 0 && equal)
5296 		return isl_map_universe(space);
5297 
5298 	map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5299 
5300 	for (i = 0; i + 1 < n; ++i)
5301 		map = isl_map_add_basic_map(map,
5302 				  isl_basic_map_more_at(isl_space_copy(space), i));
5303 	if (n > 0) {
5304 		if (equal)
5305 			map = isl_map_add_basic_map(map,
5306 			      isl_basic_map_more_or_equal_at(space, n - 1));
5307 		else
5308 			map = isl_map_add_basic_map(map,
5309 			      isl_basic_map_more_at(space, n - 1));
5310 	} else
5311 		isl_space_free(space);
5312 
5313 	return map;
5314 }
5315 
map_lex_gte(__isl_take isl_space * space,int equal)5316 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5317 {
5318 	if (!space)
5319 		return NULL;
5320 	return map_lex_gte_first(space, space->n_out, equal);
5321 }
5322 
isl_map_lex_gt_first(__isl_take isl_space * space,unsigned n)5323 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *space,
5324 	unsigned n)
5325 {
5326 	return map_lex_gte_first(space, n, 0);
5327 }
5328 
isl_map_lex_ge_first(__isl_take isl_space * space,unsigned n)5329 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *space,
5330 	unsigned n)
5331 {
5332 	return map_lex_gte_first(space, n, 1);
5333 }
5334 
isl_map_lex_gt(__isl_take isl_space * set_space)5335 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_space)
5336 {
5337 	return map_lex_gte(isl_space_map_from_set(set_space), 0);
5338 }
5339 
isl_map_lex_ge(__isl_take isl_space * set_space)5340 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_space)
5341 {
5342 	return map_lex_gte(isl_space_map_from_set(set_space), 1);
5343 }
5344 
isl_set_lex_le_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5345 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5346 	__isl_take isl_set *set2)
5347 {
5348 	isl_map *map;
5349 	map = isl_map_lex_le(isl_set_get_space(set1));
5350 	map = isl_map_intersect_domain(map, set1);
5351 	map = isl_map_intersect_range(map, set2);
5352 	return map;
5353 }
5354 
isl_set_lex_lt_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5355 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5356 	__isl_take isl_set *set2)
5357 {
5358 	isl_map *map;
5359 	map = isl_map_lex_lt(isl_set_get_space(set1));
5360 	map = isl_map_intersect_domain(map, set1);
5361 	map = isl_map_intersect_range(map, set2);
5362 	return map;
5363 }
5364 
isl_set_lex_ge_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5365 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5366 	__isl_take isl_set *set2)
5367 {
5368 	isl_map *map;
5369 	map = isl_map_lex_ge(isl_set_get_space(set1));
5370 	map = isl_map_intersect_domain(map, set1);
5371 	map = isl_map_intersect_range(map, set2);
5372 	return map;
5373 }
5374 
isl_set_lex_gt_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5375 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5376 	__isl_take isl_set *set2)
5377 {
5378 	isl_map *map;
5379 	map = isl_map_lex_gt(isl_set_get_space(set1));
5380 	map = isl_map_intersect_domain(map, set1);
5381 	map = isl_map_intersect_range(map, set2);
5382 	return map;
5383 }
5384 
isl_map_lex_le_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5385 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5386 	__isl_take isl_map *map2)
5387 {
5388 	isl_map *map;
5389 	map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5390 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5391 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5392 	return map;
5393 }
5394 
isl_map_lex_lt_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5395 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5396 	__isl_take isl_map *map2)
5397 {
5398 	isl_map *map;
5399 	map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5400 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5401 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5402 	return map;
5403 }
5404 
isl_map_lex_ge_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5405 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5406 	__isl_take isl_map *map2)
5407 {
5408 	isl_map *map;
5409 	map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5410 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5411 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5412 	return map;
5413 }
5414 
isl_map_lex_gt_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5415 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5416 	__isl_take isl_map *map2)
5417 {
5418 	isl_map *map;
5419 	map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5420 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5421 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5422 	return map;
5423 }
5424 
5425 /* For the div d = floor(f/m) at position "div", add the constraint
5426  *
5427  *		f - m d >= 0
5428  */
add_upper_div_constraint(__isl_take isl_basic_map * bmap,unsigned div)5429 static __isl_give isl_basic_map *add_upper_div_constraint(
5430 	__isl_take isl_basic_map *bmap, unsigned div)
5431 {
5432 	int i;
5433 	isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5434 	isl_size n_div;
5435 	unsigned pos;
5436 
5437 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
5438 	if (v_div < 0 || n_div < 0)
5439 		return isl_basic_map_free(bmap);
5440 	pos = v_div + div;
5441 	i = isl_basic_map_alloc_inequality(bmap);
5442 	if (i < 0)
5443 		return isl_basic_map_free(bmap);
5444 	isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5445 	isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5446 
5447 	return bmap;
5448 }
5449 
5450 /* For the div d = floor(f/m) at position "div", add the constraint
5451  *
5452  *		-(f-(m-1)) + m d >= 0
5453  */
add_lower_div_constraint(__isl_take isl_basic_map * bmap,unsigned div)5454 static __isl_give isl_basic_map *add_lower_div_constraint(
5455 	__isl_take isl_basic_map *bmap, unsigned div)
5456 {
5457 	int i;
5458 	isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5459 	isl_size n_div;
5460 	unsigned pos;
5461 
5462 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
5463 	if (v_div < 0 || n_div < 0)
5464 		return isl_basic_map_free(bmap);
5465 	pos = v_div + div;
5466 	i = isl_basic_map_alloc_inequality(bmap);
5467 	if (i < 0)
5468 		return isl_basic_map_free(bmap);
5469 	isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5470 	isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5471 	isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5472 	isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5473 
5474 	return bmap;
5475 }
5476 
5477 /* For the div d = floor(f/m) at position "pos", add the constraints
5478  *
5479  *		f - m d >= 0
5480  *		-(f-(m-1)) + m d >= 0
5481  *
5482  * Note that the second constraint is the negation of
5483  *
5484  *		f - m d >= m
5485  */
isl_basic_map_add_div_constraints(__isl_take isl_basic_map * bmap,unsigned pos)5486 __isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5487 	__isl_take isl_basic_map *bmap, unsigned pos)
5488 {
5489 	bmap = add_upper_div_constraint(bmap, pos);
5490 	bmap = add_lower_div_constraint(bmap, pos);
5491 	return bmap;
5492 }
5493 
5494 /* For each known div d = floor(f/m), add the constraints
5495  *
5496  *		f - m d >= 0
5497  *		-(f-(m-1)) + m d >= 0
5498  *
5499  * Remove duplicate constraints in case of some these div constraints
5500  * already appear in "bmap".
5501  */
isl_basic_map_add_known_div_constraints(__isl_take isl_basic_map * bmap)5502 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5503 	__isl_take isl_basic_map *bmap)
5504 {
5505 	isl_size n_div;
5506 
5507 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
5508 	if (n_div < 0)
5509 		return isl_basic_map_free(bmap);
5510 	if (n_div == 0)
5511 		return bmap;
5512 
5513 	bmap = add_known_div_constraints(bmap);
5514 	bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5515 	bmap = isl_basic_map_finalize(bmap);
5516 	return bmap;
5517 }
5518 
5519 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5520  *
5521  * In particular, if this div is of the form d = floor(f/m),
5522  * then add the constraint
5523  *
5524  *		f - m d >= 0
5525  *
5526  * if sign < 0 or the constraint
5527  *
5528  *		-(f-(m-1)) + m d >= 0
5529  *
5530  * if sign > 0.
5531  */
isl_basic_map_add_div_constraint(__isl_take isl_basic_map * bmap,unsigned div,int sign)5532 __isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5533 	__isl_take isl_basic_map *bmap, unsigned div, int sign)
5534 {
5535 	if (sign < 0)
5536 		return add_upper_div_constraint(bmap, div);
5537 	else
5538 		return add_lower_div_constraint(bmap, div);
5539 }
5540 
isl_basic_map_underlying_set(__isl_take isl_basic_map * bmap)5541 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5542 	__isl_take isl_basic_map *bmap)
5543 {
5544 	isl_space *space;
5545 
5546 	if (!bmap)
5547 		goto error;
5548 	if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5549 	    bmap->n_div == 0 &&
5550 	    !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5551 	    !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5552 		return bset_from_bmap(bmap);
5553 	bmap = isl_basic_map_cow(bmap);
5554 	if (!bmap)
5555 		return NULL;
5556 	space = isl_basic_map_take_space(bmap);
5557 	space = isl_space_underlying(space, bmap->n_div);
5558 	bmap = isl_basic_map_restore_space(bmap, space);
5559 	if (!bmap)
5560 		return NULL;
5561 	bmap->extra -= bmap->n_div;
5562 	bmap->n_div = 0;
5563 	bmap = isl_basic_map_finalize(bmap);
5564 	return bset_from_bmap(bmap);
5565 error:
5566 	isl_basic_map_free(bmap);
5567 	return NULL;
5568 }
5569 
isl_basic_set_underlying_set(__isl_take isl_basic_set * bset)5570 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5571 		__isl_take isl_basic_set *bset)
5572 {
5573 	return isl_basic_map_underlying_set(bset_to_bmap(bset));
5574 }
5575 
5576 /* Replace each element in "list" by the result of applying
5577  * isl_basic_map_underlying_set to the element.
5578  */
isl_basic_map_list_underlying_set(__isl_take isl_basic_map_list * list)5579 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5580 	__isl_take isl_basic_map_list *list)
5581 {
5582 	int i;
5583 	isl_size n;
5584 
5585 	n = isl_basic_map_list_n_basic_map(list);
5586 	if (n < 0)
5587 		goto error;
5588 
5589 	for (i = 0; i < n; ++i) {
5590 		isl_basic_map *bmap;
5591 		isl_basic_set *bset;
5592 
5593 		bmap = isl_basic_map_list_get_basic_map(list, i);
5594 		bset = isl_basic_set_underlying_set(bmap);
5595 		list = isl_basic_set_list_set_basic_set(list, i, bset);
5596 	}
5597 
5598 	return list;
5599 error:
5600 	isl_basic_map_list_free(list);
5601 	return NULL;
5602 }
5603 
isl_basic_map_overlying_set(__isl_take isl_basic_set * bset,__isl_take isl_basic_map * like)5604 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5605 	__isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5606 {
5607 	struct isl_basic_map *bmap;
5608 	struct isl_ctx *ctx;
5609 	isl_size dim, bmap_total;
5610 	unsigned total;
5611 	int i;
5612 
5613 	if (!bset || !like)
5614 		goto error;
5615 	ctx = bset->ctx;
5616 	if (isl_basic_set_check_no_params(bset) < 0 ||
5617 	    isl_basic_set_check_no_locals(bset) < 0)
5618 		goto error;
5619 	dim = isl_basic_set_dim(bset, isl_dim_set);
5620 	bmap_total = isl_basic_map_dim(like, isl_dim_all);
5621 	if (dim < 0 || bmap_total < 0)
5622 		goto error;
5623 	isl_assert(ctx, dim == bmap_total, goto error);
5624 	if (like->n_div == 0) {
5625 		isl_space *space = isl_basic_map_get_space(like);
5626 		isl_basic_map_free(like);
5627 		return isl_basic_map_reset_space(bset, space);
5628 	}
5629 	bset = isl_basic_set_cow(bset);
5630 	if (!bset)
5631 		goto error;
5632 	total = dim + bset->extra;
5633 	bmap = bset_to_bmap(bset);
5634 	isl_space_free(isl_basic_map_take_space(bmap));
5635 	bmap = isl_basic_map_restore_space(bmap, isl_basic_map_get_space(like));
5636 	if (!bmap)
5637 		goto error;
5638 	bmap->n_div = like->n_div;
5639 	bmap->extra += like->n_div;
5640 	if (bmap->extra) {
5641 		unsigned ltotal;
5642 		isl_int **div;
5643 		ltotal = total - bmap->extra + like->extra;
5644 		if (ltotal > total)
5645 			ltotal = total;
5646 		bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5647 					bmap->extra * (1 + 1 + total));
5648 		if (isl_blk_is_error(bmap->block2))
5649 			goto error;
5650 		div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5651 		if (!div)
5652 			goto error;
5653 		bmap->div = div;
5654 		for (i = 0; i < bmap->extra; ++i)
5655 			bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5656 		for (i = 0; i < like->n_div; ++i) {
5657 			isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5658 			isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5659 		}
5660 		bmap = isl_basic_map_add_known_div_constraints(bmap);
5661 	}
5662 	isl_basic_map_free(like);
5663 	bmap = isl_basic_map_simplify(bmap);
5664 	bmap = isl_basic_map_finalize(bmap);
5665 	return bmap;
5666 error:
5667 	isl_basic_map_free(like);
5668 	isl_basic_set_free(bset);
5669 	return NULL;
5670 }
5671 
isl_basic_set_from_underlying_set(__isl_take isl_basic_set * bset,__isl_take isl_basic_set * like)5672 __isl_give isl_basic_set *isl_basic_set_from_underlying_set(
5673 	__isl_take isl_basic_set *bset, __isl_take isl_basic_set *like)
5674 {
5675 	return bset_from_bmap(isl_basic_map_overlying_set(bset,
5676 							bset_to_bmap(like)));
5677 }
5678 
isl_map_underlying_set(__isl_take isl_map * map)5679 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5680 {
5681 	int i;
5682 
5683 	map = isl_map_cow(map);
5684 	if (!map)
5685 		return NULL;
5686 	map->dim = isl_space_cow(map->dim);
5687 	if (!map->dim)
5688 		goto error;
5689 
5690 	for (i = 1; i < map->n; ++i)
5691 		isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5692 				goto error);
5693 	for (i = 0; i < map->n; ++i) {
5694 		map->p[i] = bset_to_bmap(
5695 				isl_basic_map_underlying_set(map->p[i]));
5696 		if (!map->p[i])
5697 			goto error;
5698 	}
5699 	if (map->n == 0)
5700 		map->dim = isl_space_underlying(map->dim, 0);
5701 	else {
5702 		isl_space_free(map->dim);
5703 		map->dim = isl_space_copy(map->p[0]->dim);
5704 	}
5705 	if (!map->dim)
5706 		goto error;
5707 	return set_from_map(map);
5708 error:
5709 	isl_map_free(map);
5710 	return NULL;
5711 }
5712 
5713 /* Replace the space of "bmap" by "space".
5714  *
5715  * If the space of "bmap" is identical to "space" (including the identifiers
5716  * of the input and output dimensions), then simply return the original input.
5717  */
isl_basic_map_reset_space(__isl_take isl_basic_map * bmap,__isl_take isl_space * space)5718 __isl_give isl_basic_map *isl_basic_map_reset_space(
5719 	__isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5720 {
5721 	isl_bool equal;
5722 	isl_space *bmap_space;
5723 
5724 	bmap_space = isl_basic_map_peek_space(bmap);
5725 	equal = isl_space_is_equal(bmap_space, space);
5726 	if (equal >= 0 && equal)
5727 		equal = isl_space_has_equal_ids(bmap_space, space);
5728 	if (equal < 0)
5729 		goto error;
5730 	if (equal) {
5731 		isl_space_free(space);
5732 		return bmap;
5733 	}
5734 	isl_space_free(isl_basic_map_take_space(bmap));
5735 	bmap = isl_basic_map_restore_space(bmap, space);
5736 
5737 	bmap = isl_basic_map_finalize(bmap);
5738 
5739 	return bmap;
5740 error:
5741 	isl_basic_map_free(bmap);
5742 	isl_space_free(space);
5743 	return NULL;
5744 }
5745 
isl_basic_set_reset_space(__isl_take isl_basic_set * bset,__isl_take isl_space * space)5746 __isl_give isl_basic_set *isl_basic_set_reset_space(
5747 	__isl_take isl_basic_set *bset, __isl_take isl_space *space)
5748 {
5749 	return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5750 							space));
5751 }
5752 
5753 /* Check that the total dimensions of "map" and "space" are the same.
5754  */
check_map_space_equal_total_dim(__isl_keep isl_map * map,__isl_keep isl_space * space)5755 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5756 	__isl_keep isl_space *space)
5757 {
5758 	isl_size dim1, dim2;
5759 
5760 	dim1 = isl_map_dim(map, isl_dim_all);
5761 	dim2 = isl_space_dim(space, isl_dim_all);
5762 	if (dim1 < 0 || dim2 < 0)
5763 		return isl_stat_error;
5764 	if (dim1 == dim2)
5765 		return isl_stat_ok;
5766 	isl_die(isl_map_get_ctx(map), isl_error_invalid,
5767 		"total dimensions do not match", return isl_stat_error);
5768 }
5769 
isl_map_reset_space(__isl_take isl_map * map,__isl_take isl_space * space)5770 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5771 	__isl_take isl_space *space)
5772 {
5773 	int i;
5774 
5775 	map = isl_map_cow(map);
5776 	if (!map || !space)
5777 		goto error;
5778 
5779 	for (i = 0; i < map->n; ++i) {
5780 		map->p[i] = isl_basic_map_reset_space(map->p[i],
5781 						    isl_space_copy(space));
5782 		if (!map->p[i])
5783 			goto error;
5784 	}
5785 	isl_space_free(isl_map_take_space(map));
5786 	map = isl_map_restore_space(map, space);
5787 
5788 	return map;
5789 error:
5790 	isl_map_free(map);
5791 	isl_space_free(space);
5792 	return NULL;
5793 }
5794 
5795 /* Replace the space of "map" by "space", without modifying
5796  * the dimension of "map".
5797  *
5798  * If the space of "map" is identical to "space" (including the identifiers
5799  * of the input and output dimensions), then simply return the original input.
5800  */
isl_map_reset_equal_dim_space(__isl_take isl_map * map,__isl_take isl_space * space)5801 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5802 	__isl_take isl_space *space)
5803 {
5804 	isl_bool equal;
5805 	isl_space *map_space;
5806 
5807 	map_space = isl_map_peek_space(map);
5808 	equal = isl_space_is_equal(map_space, space);
5809 	if (equal >= 0 && equal)
5810 		equal = isl_space_has_equal_ids(map_space, space);
5811 	if (equal < 0)
5812 		goto error;
5813 	if (equal) {
5814 		isl_space_free(space);
5815 		return map;
5816 	}
5817 	if (check_map_space_equal_total_dim(map, space) < 0)
5818 		goto error;
5819 	return isl_map_reset_space(map, space);
5820 error:
5821 	isl_map_free(map);
5822 	isl_space_free(space);
5823 	return NULL;
5824 }
5825 
isl_set_reset_space(__isl_take isl_set * set,__isl_take isl_space * space)5826 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5827 	__isl_take isl_space *space)
5828 {
5829 	return set_from_map(isl_map_reset_space(set_to_map(set), space));
5830 }
5831 
5832 /* Compute the parameter domain of the given basic set.
5833  */
isl_basic_set_params(__isl_take isl_basic_set * bset)5834 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5835 {
5836 	isl_bool is_params;
5837 	isl_space *space;
5838 	isl_size n;
5839 
5840 	is_params = isl_basic_set_is_params(bset);
5841 	if (is_params < 0)
5842 		return isl_basic_set_free(bset);
5843 	if (is_params)
5844 		return bset;
5845 
5846 	n = isl_basic_set_dim(bset, isl_dim_set);
5847 	if (n < 0)
5848 		return isl_basic_set_free(bset);
5849 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5850 	space = isl_basic_set_get_space(bset);
5851 	space = isl_space_params(space);
5852 	bset = isl_basic_set_reset_space(bset, space);
5853 	return bset;
5854 }
5855 
5856 /* Construct a zero-dimensional basic set with the given parameter domain.
5857  */
isl_basic_set_from_params(__isl_take isl_basic_set * bset)5858 __isl_give isl_basic_set *isl_basic_set_from_params(
5859 	__isl_take isl_basic_set *bset)
5860 {
5861 	isl_space *space;
5862 	space = isl_basic_set_get_space(bset);
5863 	space = isl_space_set_from_params(space);
5864 	bset = isl_basic_set_reset_space(bset, space);
5865 	return bset;
5866 }
5867 
5868 /* Compute the parameter domain of the given set.
5869  */
isl_set_params(__isl_take isl_set * set)5870 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5871 {
5872 	return isl_map_params(set_to_map(set));
5873 }
5874 
5875 /* Construct a zero-dimensional set with the given parameter domain.
5876  */
isl_set_from_params(__isl_take isl_set * set)5877 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5878 {
5879 	isl_space *space;
5880 	space = isl_set_get_space(set);
5881 	space = isl_space_set_from_params(space);
5882 	set = isl_set_reset_space(set, space);
5883 	return set;
5884 }
5885 
5886 /* Compute the parameter domain of the given map.
5887  */
isl_map_params(__isl_take isl_map * map)5888 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5889 {
5890 	isl_space *space;
5891 	isl_size n_in, n_out;
5892 
5893 	n_in = isl_map_dim(map, isl_dim_in);
5894 	n_out = isl_map_dim(map, isl_dim_out);
5895 	if (n_in < 0 || n_out < 0)
5896 		return isl_map_free(map);
5897 	map = isl_map_project_out(map, isl_dim_in, 0, n_in);
5898 	map = isl_map_project_out(map, isl_dim_out, 0, n_out);
5899 	space = isl_map_get_space(map);
5900 	space = isl_space_params(space);
5901 	map = isl_map_reset_space(map, space);
5902 	return map;
5903 }
5904 
isl_basic_map_domain(__isl_take isl_basic_map * bmap)5905 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5906 {
5907 	isl_space *space;
5908 	isl_size n_out;
5909 
5910 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
5911 	if (n_out < 0)
5912 		return isl_basic_map_free(bmap);
5913 	space = isl_space_domain(isl_basic_map_get_space(bmap));
5914 
5915 	bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5916 
5917 	return isl_basic_map_reset_space(bmap, space);
5918 }
5919 
isl_basic_map_may_be_set(__isl_keep isl_basic_map * bmap)5920 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5921 {
5922 	if (!bmap)
5923 		return isl_bool_error;
5924 	return isl_space_may_be_set(bmap->dim);
5925 }
5926 
5927 /* Is this basic map actually a set?
5928  * Users should never call this function.  Outside of isl,
5929  * the type should indicate whether something is a set or a map.
5930  */
isl_basic_map_is_set(__isl_keep isl_basic_map * bmap)5931 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5932 {
5933 	if (!bmap)
5934 		return isl_bool_error;
5935 	return isl_space_is_set(bmap->dim);
5936 }
5937 
isl_basic_map_range(__isl_take isl_basic_map * bmap)5938 __isl_give isl_basic_set *isl_basic_map_range(__isl_take isl_basic_map *bmap)
5939 {
5940 	isl_bool is_set;
5941 
5942 	is_set = isl_basic_map_is_set(bmap);
5943 	if (is_set < 0)
5944 		goto error;
5945 	if (is_set)
5946 		return bmap;
5947 	return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5948 error:
5949 	isl_basic_map_free(bmap);
5950 	return NULL;
5951 }
5952 
isl_basic_map_domain_map(__isl_take isl_basic_map * bmap)5953 __isl_give isl_basic_map *isl_basic_map_domain_map(
5954 	__isl_take isl_basic_map *bmap)
5955 {
5956 	int i;
5957 	isl_space *space;
5958 	isl_basic_map *domain;
5959 	isl_size nparam, n_in, n_out;
5960 
5961 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5962 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5963 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
5964 	if (nparam < 0 || n_in < 0 || n_out < 0)
5965 		return isl_basic_map_free(bmap);
5966 
5967 	space = isl_basic_map_get_space(bmap);
5968 	space = isl_space_from_range(isl_space_domain(space));
5969 	domain = isl_basic_map_universe(space);
5970 
5971 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5972 	bmap = isl_basic_map_apply_range(bmap, domain);
5973 	bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5974 
5975 	for (i = 0; i < n_in; ++i)
5976 		bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5977 						    isl_dim_out, i);
5978 
5979 	bmap = isl_basic_map_gauss(bmap, NULL);
5980 	return isl_basic_map_finalize(bmap);
5981 }
5982 
isl_basic_map_range_map(__isl_take isl_basic_map * bmap)5983 __isl_give isl_basic_map *isl_basic_map_range_map(
5984 	__isl_take isl_basic_map *bmap)
5985 {
5986 	int i;
5987 	isl_space *space;
5988 	isl_basic_map *range;
5989 	isl_size nparam, n_in, n_out;
5990 
5991 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5992 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5993 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
5994 	if (nparam < 0 || n_in < 0 || n_out < 0)
5995 		return isl_basic_map_free(bmap);
5996 
5997 	space = isl_basic_map_get_space(bmap);
5998 	space = isl_space_from_range(isl_space_range(space));
5999 	range = isl_basic_map_universe(space);
6000 
6001 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
6002 	bmap = isl_basic_map_apply_range(bmap, range);
6003 	bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
6004 
6005 	for (i = 0; i < n_out; ++i)
6006 		bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
6007 						    isl_dim_out, i);
6008 
6009 	bmap = isl_basic_map_gauss(bmap, NULL);
6010 	return isl_basic_map_finalize(bmap);
6011 }
6012 
isl_map_may_be_set(__isl_keep isl_map * map)6013 int isl_map_may_be_set(__isl_keep isl_map *map)
6014 {
6015 	if (!map)
6016 		return -1;
6017 	return isl_space_may_be_set(map->dim);
6018 }
6019 
6020 /* Is this map actually a set?
6021  * Users should never call this function.  Outside of isl,
6022  * the type should indicate whether something is a set or a map.
6023  */
isl_map_is_set(__isl_keep isl_map * map)6024 isl_bool isl_map_is_set(__isl_keep isl_map *map)
6025 {
6026 	if (!map)
6027 		return isl_bool_error;
6028 	return isl_space_is_set(map->dim);
6029 }
6030 
isl_map_range(__isl_take isl_map * map)6031 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
6032 {
6033 	isl_space *space;
6034 	isl_size n_in;
6035 
6036 	n_in = isl_map_dim(map, isl_dim_in);
6037 	if (n_in < 0)
6038 		return set_from_map(isl_map_free(map));
6039 	space = isl_space_range(isl_map_get_space(map));
6040 
6041 	map = isl_map_project_out(map, isl_dim_in, 0, n_in);
6042 
6043 	return set_from_map(isl_map_reset_space(map, space));
6044 }
6045 
6046 /* Transform "map" by applying "fn_space" to its space and "fn_bmap"
6047  * to each of its basic maps.
6048  */
isl_map_transform(__isl_take isl_map * map,__isl_give isl_space * (* fn_space)(__isl_take isl_space * space),__isl_give isl_basic_map * (* fn_bmap)(__isl_take isl_basic_map * bmap))6049 static __isl_give isl_map *isl_map_transform(__isl_take isl_map *map,
6050 	__isl_give isl_space *(*fn_space)(__isl_take isl_space *space),
6051 	__isl_give isl_basic_map *(*fn_bmap)(__isl_take isl_basic_map *bmap))
6052 {
6053 	int i;
6054 	isl_space *space;
6055 
6056 	map = isl_map_cow(map);
6057 	if (!map)
6058 		return NULL;
6059 
6060 	for (i = 0; i < map->n; ++i) {
6061 		map->p[i] = fn_bmap(map->p[i]);
6062 		if (!map->p[i])
6063 			return isl_map_free(map);
6064 	}
6065 	map = isl_map_unmark_normalized(map);
6066 
6067 	space = isl_map_take_space(map);
6068 	space = fn_space(space);
6069 	map = isl_map_restore_space(map, space);
6070 
6071 	return map;
6072 }
6073 
isl_map_domain_map(__isl_take isl_map * map)6074 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
6075 {
6076 	return isl_map_transform(map, &isl_space_domain_map,
6077 					&isl_basic_map_domain_map);
6078 }
6079 
isl_map_range_map(__isl_take isl_map * map)6080 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
6081 {
6082 	return isl_map_transform(map, &isl_space_range_map,
6083 					&isl_basic_map_range_map);
6084 }
6085 
6086 /* Given a wrapped map of the form A[B -> C],
6087  * return the map A[B -> C] -> B.
6088  */
isl_set_wrapped_domain_map(__isl_take isl_set * set)6089 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
6090 {
6091 	isl_id *id;
6092 	isl_map *map;
6093 
6094 	if (!set)
6095 		return NULL;
6096 	if (!isl_set_has_tuple_id(set))
6097 		return isl_map_domain_map(isl_set_unwrap(set));
6098 
6099 	id = isl_set_get_tuple_id(set);
6100 	map = isl_map_domain_map(isl_set_unwrap(set));
6101 	map = isl_map_set_tuple_id(map, isl_dim_in, id);
6102 
6103 	return map;
6104 }
6105 
isl_basic_map_from_domain(__isl_take isl_basic_set * bset)6106 __isl_give isl_basic_map *isl_basic_map_from_domain(
6107 	__isl_take isl_basic_set *bset)
6108 {
6109 	return isl_basic_map_reverse(isl_basic_map_from_range(bset));
6110 }
6111 
isl_basic_map_from_range(__isl_take isl_basic_set * bset)6112 __isl_give isl_basic_map *isl_basic_map_from_range(
6113 	__isl_take isl_basic_set *bset)
6114 {
6115 	isl_space *space;
6116 	space = isl_basic_set_get_space(bset);
6117 	space = isl_space_from_range(space);
6118 	bset = isl_basic_set_reset_space(bset, space);
6119 	return bset_to_bmap(bset);
6120 }
6121 
6122 /* Create a relation with the given set as range.
6123  * The domain of the created relation is a zero-dimensional
6124  * flat anonymous space.
6125  */
isl_map_from_range(__isl_take isl_set * set)6126 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
6127 {
6128 	isl_space *space;
6129 	space = isl_set_get_space(set);
6130 	space = isl_space_from_range(space);
6131 	set = isl_set_reset_space(set, space);
6132 	return set_to_map(set);
6133 }
6134 
6135 /* Create a relation with the given set as domain.
6136  * The range of the created relation is a zero-dimensional
6137  * flat anonymous space.
6138  */
isl_map_from_domain(__isl_take isl_set * set)6139 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
6140 {
6141 	return isl_map_reverse(isl_map_from_range(set));
6142 }
6143 
isl_basic_map_from_domain_and_range(__isl_take isl_basic_set * domain,__isl_take isl_basic_set * range)6144 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
6145 	__isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
6146 {
6147 	return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
6148 }
6149 
isl_map_from_domain_and_range(__isl_take isl_set * domain,__isl_take isl_set * range)6150 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
6151 	__isl_take isl_set *range)
6152 {
6153 	return isl_map_apply_range(isl_map_reverse(domain), range);
6154 }
6155 
6156 /* Return a newly allocated isl_map with given space and flags and
6157  * room for "n" basic maps.
6158  * Make sure that all cached information is cleared.
6159  */
isl_map_alloc_space(__isl_take isl_space * space,int n,unsigned flags)6160 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
6161 	unsigned flags)
6162 {
6163 	struct isl_map *map;
6164 
6165 	if (!space)
6166 		return NULL;
6167 	if (n < 0)
6168 		isl_die(space->ctx, isl_error_internal,
6169 			"negative number of basic maps", goto error);
6170 	map = isl_calloc(space->ctx, struct isl_map,
6171 			sizeof(struct isl_map) +
6172 			(n - 1) * sizeof(struct isl_basic_map *));
6173 	if (!map)
6174 		goto error;
6175 
6176 	map->ctx = space->ctx;
6177 	isl_ctx_ref(map->ctx);
6178 	map->ref = 1;
6179 	map->size = n;
6180 	map->n = 0;
6181 	map->dim = space;
6182 	map->flags = flags;
6183 	return map;
6184 error:
6185 	isl_space_free(space);
6186 	return NULL;
6187 }
6188 
isl_basic_map_empty(__isl_take isl_space * space)6189 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
6190 {
6191 	struct isl_basic_map *bmap;
6192 	bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
6193 	bmap = isl_basic_map_set_to_empty(bmap);
6194 	return bmap;
6195 }
6196 
isl_basic_set_empty(__isl_take isl_space * space)6197 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
6198 {
6199 	struct isl_basic_set *bset;
6200 	bset = isl_basic_set_alloc_space(space, 0, 1, 0);
6201 	bset = isl_basic_set_set_to_empty(bset);
6202 	return bset;
6203 }
6204 
isl_basic_map_universe(__isl_take isl_space * space)6205 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6206 {
6207 	struct isl_basic_map *bmap;
6208 	bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6209 	bmap = isl_basic_map_finalize(bmap);
6210 	return bmap;
6211 }
6212 
isl_basic_set_universe(__isl_take isl_space * space)6213 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6214 {
6215 	struct isl_basic_set *bset;
6216 	bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6217 	bset = isl_basic_set_finalize(bset);
6218 	return bset;
6219 }
6220 
isl_basic_map_nat_universe(__isl_take isl_space * space)6221 __isl_give isl_basic_map *isl_basic_map_nat_universe(
6222 	__isl_take isl_space *space)
6223 {
6224 	int i;
6225 	isl_size total = isl_space_dim(space, isl_dim_all);
6226 	isl_basic_map *bmap;
6227 
6228 	if (total < 0)
6229 		space = isl_space_free(space);
6230 	bmap = isl_basic_map_alloc_space(space, 0, 0, total);
6231 	for (i = 0; i < total; ++i) {
6232 		int k = isl_basic_map_alloc_inequality(bmap);
6233 		if (k < 0)
6234 			goto error;
6235 		isl_seq_clr(bmap->ineq[k], 1 + total);
6236 		isl_int_set_si(bmap->ineq[k][1 + i], 1);
6237 	}
6238 	return bmap;
6239 error:
6240 	isl_basic_map_free(bmap);
6241 	return NULL;
6242 }
6243 
isl_basic_set_nat_universe(__isl_take isl_space * space)6244 __isl_give isl_basic_set *isl_basic_set_nat_universe(
6245 	__isl_take isl_space *space)
6246 {
6247 	return isl_basic_map_nat_universe(space);
6248 }
6249 
isl_map_nat_universe(__isl_take isl_space * space)6250 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *space)
6251 {
6252 	return isl_map_from_basic_map(isl_basic_map_nat_universe(space));
6253 }
6254 
isl_set_nat_universe(__isl_take isl_space * space)6255 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *space)
6256 {
6257 	return isl_map_nat_universe(space);
6258 }
6259 
isl_map_empty(__isl_take isl_space * space)6260 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6261 {
6262 	return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6263 }
6264 
isl_set_empty(__isl_take isl_space * space)6265 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6266 {
6267 	return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6268 }
6269 
isl_map_universe(__isl_take isl_space * space)6270 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6271 {
6272 	struct isl_map *map;
6273 	if (!space)
6274 		return NULL;
6275 	map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6276 	map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6277 	return map;
6278 }
6279 
isl_set_universe(__isl_take isl_space * space)6280 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6281 {
6282 	struct isl_set *set;
6283 	if (!space)
6284 		return NULL;
6285 	set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6286 	set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6287 	return set;
6288 }
6289 
isl_map_dup(__isl_keep isl_map * map)6290 __isl_give isl_map *isl_map_dup(__isl_keep isl_map *map)
6291 {
6292 	int i;
6293 	struct isl_map *dup;
6294 
6295 	if (!map)
6296 		return NULL;
6297 	dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6298 	for (i = 0; i < map->n; ++i)
6299 		dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6300 	return dup;
6301 }
6302 
isl_map_add_basic_map(__isl_take isl_map * map,__isl_take isl_basic_map * bmap)6303 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6304 						__isl_take isl_basic_map *bmap)
6305 {
6306 	if (!bmap || !map)
6307 		goto error;
6308 	if (isl_basic_map_plain_is_empty(bmap)) {
6309 		isl_basic_map_free(bmap);
6310 		return map;
6311 	}
6312 	if (isl_map_basic_map_check_equal_space(map, bmap) < 0)
6313 		goto error;
6314 	isl_assert(map->ctx, map->n < map->size, goto error);
6315 	map->p[map->n] = bmap;
6316 	map->n++;
6317 	map = isl_map_unmark_normalized(map);
6318 	return map;
6319 error:
6320 	if (map)
6321 		isl_map_free(map);
6322 	if (bmap)
6323 		isl_basic_map_free(bmap);
6324 	return NULL;
6325 }
6326 
isl_map_free(__isl_take isl_map * map)6327 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6328 {
6329 	int i;
6330 
6331 	if (!map)
6332 		return NULL;
6333 
6334 	if (--map->ref > 0)
6335 		return NULL;
6336 
6337 	clear_caches(map);
6338 	isl_ctx_deref(map->ctx);
6339 	for (i = 0; i < map->n; ++i)
6340 		isl_basic_map_free(map->p[i]);
6341 	isl_space_free(map->dim);
6342 	free(map);
6343 
6344 	return NULL;
6345 }
6346 
isl_basic_map_fix_pos_si(__isl_take isl_basic_map * bmap,unsigned pos,int value)6347 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6348 	__isl_take isl_basic_map *bmap, unsigned pos, int value)
6349 {
6350 	int j;
6351 	isl_size total;
6352 
6353 	total = isl_basic_map_dim(bmap, isl_dim_all);
6354 	if (total < 0)
6355 		return isl_basic_map_free(bmap);
6356 
6357 	bmap = isl_basic_map_cow(bmap);
6358 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6359 	j = isl_basic_map_alloc_equality(bmap);
6360 	if (j < 0)
6361 		goto error;
6362 	isl_seq_clr(bmap->eq[j] + 1, total);
6363 	isl_int_set_si(bmap->eq[j][pos], -1);
6364 	isl_int_set_si(bmap->eq[j][0], value);
6365 	bmap = isl_basic_map_simplify(bmap);
6366 	return isl_basic_map_finalize(bmap);
6367 error:
6368 	isl_basic_map_free(bmap);
6369 	return NULL;
6370 }
6371 
isl_basic_map_fix_pos(__isl_take isl_basic_map * bmap,unsigned pos,isl_int value)6372 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6373 	__isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6374 {
6375 	int j;
6376 	isl_size total;
6377 
6378 	total = isl_basic_map_dim(bmap, isl_dim_all);
6379 	if (total < 0)
6380 		return isl_basic_map_free(bmap);
6381 
6382 	bmap = isl_basic_map_cow(bmap);
6383 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6384 	j = isl_basic_map_alloc_equality(bmap);
6385 	if (j < 0)
6386 		goto error;
6387 	isl_seq_clr(bmap->eq[j] + 1, total);
6388 	isl_int_set_si(bmap->eq[j][pos], -1);
6389 	isl_int_set(bmap->eq[j][0], value);
6390 	bmap = isl_basic_map_simplify(bmap);
6391 	return isl_basic_map_finalize(bmap);
6392 error:
6393 	isl_basic_map_free(bmap);
6394 	return NULL;
6395 }
6396 
isl_basic_map_fix_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6397 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6398 		enum isl_dim_type type, unsigned pos, int value)
6399 {
6400 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6401 		return isl_basic_map_free(bmap);
6402 	return isl_basic_map_fix_pos_si(bmap,
6403 		isl_basic_map_offset(bmap, type) + pos, value);
6404 }
6405 
isl_basic_map_fix(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int value)6406 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6407 		enum isl_dim_type type, unsigned pos, isl_int value)
6408 {
6409 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6410 		return isl_basic_map_free(bmap);
6411 	return isl_basic_map_fix_pos(bmap,
6412 		isl_basic_map_offset(bmap, type) + pos, value);
6413 }
6414 
6415 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6416  * to be equal to "v".
6417  */
isl_basic_map_fix_val(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6418 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6419 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6420 {
6421 	if (!bmap || !v)
6422 		goto error;
6423 	if (!isl_val_is_int(v))
6424 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6425 			"expecting integer value", goto error);
6426 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6427 		goto error;
6428 	pos += isl_basic_map_offset(bmap, type);
6429 	bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6430 	isl_val_free(v);
6431 	return bmap;
6432 error:
6433 	isl_basic_map_free(bmap);
6434 	isl_val_free(v);
6435 	return NULL;
6436 }
6437 
6438 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6439  * to be equal to "v".
6440  */
isl_basic_set_fix_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6441 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6442 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6443 {
6444 	return isl_basic_map_fix_val(bset, type, pos, v);
6445 }
6446 
isl_basic_set_fix_si(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,int value)6447 __isl_give isl_basic_set *isl_basic_set_fix_si(__isl_take isl_basic_set *bset,
6448 		enum isl_dim_type type, unsigned pos, int value)
6449 {
6450 	return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6451 						    type, pos, value));
6452 }
6453 
isl_basic_set_fix(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value)6454 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6455 		enum isl_dim_type type, unsigned pos, isl_int value)
6456 {
6457 	return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6458 						    type, pos, value));
6459 }
6460 
6461 /* Remove the basic map at position "i" from "map" if this basic map
6462  * is (obviously) empty.
6463  */
remove_if_empty(__isl_take isl_map * map,int i)6464 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6465 {
6466 	isl_bool empty;
6467 
6468 	if (!map)
6469 		return NULL;
6470 
6471 	empty = isl_basic_map_plain_is_empty(map->p[i]);
6472 	if (empty < 0)
6473 		return isl_map_free(map);
6474 	if (!empty)
6475 		return map;
6476 
6477 	isl_basic_map_free(map->p[i]);
6478 	map->n--;
6479 	if (i != map->n) {
6480 		map->p[i] = map->p[map->n];
6481 		map = isl_map_unmark_normalized(map);
6482 
6483 	}
6484 
6485 	return map;
6486 }
6487 
6488 /* Perform "fn" on each basic map of "map", where we may not be holding
6489  * the only reference to "map".
6490  * In particular, "fn" should be a semantics preserving operation
6491  * that we want to apply to all copies of "map".  We therefore need
6492  * to be careful not to modify "map" in a way that breaks "map"
6493  * in case anything goes wrong.
6494  */
isl_map_inline_foreach_basic_map(__isl_take isl_map * map,__isl_give isl_basic_map * (* fn)(__isl_take isl_basic_map * bmap))6495 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6496 	__isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6497 {
6498 	struct isl_basic_map *bmap;
6499 	int i;
6500 
6501 	if (!map)
6502 		return NULL;
6503 
6504 	for (i = map->n - 1; i >= 0; --i) {
6505 		bmap = isl_basic_map_copy(map->p[i]);
6506 		bmap = fn(bmap);
6507 		if (!bmap)
6508 			goto error;
6509 		isl_basic_map_free(map->p[i]);
6510 		map->p[i] = bmap;
6511 		map = remove_if_empty(map, i);
6512 		if (!map)
6513 			return NULL;
6514 	}
6515 
6516 	return map;
6517 error:
6518 	isl_map_free(map);
6519 	return NULL;
6520 }
6521 
isl_map_fix_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6522 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6523 		enum isl_dim_type type, unsigned pos, int value)
6524 {
6525 	int i;
6526 
6527 	map = isl_map_cow(map);
6528 	if (isl_map_check_range(map, type, pos, 1) < 0)
6529 		return isl_map_free(map);
6530 	for (i = map->n - 1; i >= 0; --i) {
6531 		map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6532 		map = remove_if_empty(map, i);
6533 		if (!map)
6534 			return NULL;
6535 	}
6536 	map = isl_map_unmark_normalized(map);
6537 	return map;
6538 }
6539 
isl_set_fix_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6540 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6541 		enum isl_dim_type type, unsigned pos, int value)
6542 {
6543 	return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6544 }
6545 
isl_map_fix(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6546 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6547 		enum isl_dim_type type, unsigned pos, isl_int value)
6548 {
6549 	int i;
6550 
6551 	map = isl_map_cow(map);
6552 	if (isl_map_check_range(map, type, pos, 1) < 0)
6553 		return isl_map_free(map);
6554 	for (i = 0; i < map->n; ++i) {
6555 		map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6556 		if (!map->p[i])
6557 			goto error;
6558 	}
6559 	map = isl_map_unmark_normalized(map);
6560 	return map;
6561 error:
6562 	isl_map_free(map);
6563 	return NULL;
6564 }
6565 
isl_set_fix(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6566 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6567 		enum isl_dim_type type, unsigned pos, isl_int value)
6568 {
6569 	return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6570 }
6571 
6572 /* Fix the value of the variable at position "pos" of type "type" of "map"
6573  * to be equal to "v".
6574  */
isl_map_fix_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6575 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6576 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6577 {
6578 	int i;
6579 
6580 	map = isl_map_cow(map);
6581 	if (!map || !v)
6582 		goto error;
6583 
6584 	if (!isl_val_is_int(v))
6585 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
6586 			"expecting integer value", goto error);
6587 	if (isl_map_check_range(map, type, pos, 1) < 0)
6588 		goto error;
6589 	for (i = map->n - 1; i >= 0; --i) {
6590 		map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6591 							isl_val_copy(v));
6592 		map = remove_if_empty(map, i);
6593 		if (!map)
6594 			goto error;
6595 	}
6596 	map = isl_map_unmark_normalized(map);
6597 	isl_val_free(v);
6598 	return map;
6599 error:
6600 	isl_map_free(map);
6601 	isl_val_free(v);
6602 	return NULL;
6603 }
6604 
6605 /* Fix the value of the variable at position "pos" of type "type" of "set"
6606  * to be equal to "v".
6607  */
isl_set_fix_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6608 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6609 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6610 {
6611 	return isl_map_fix_val(set, type, pos, v);
6612 }
6613 
isl_map_fix_input_si(__isl_take isl_map * map,unsigned input,int value)6614 __isl_give isl_map *isl_map_fix_input_si(__isl_take isl_map *map,
6615 		unsigned input, int value)
6616 {
6617 	return isl_map_fix_si(map, isl_dim_in, input, value);
6618 }
6619 
isl_set_fix_dim_si(__isl_take isl_set * set,unsigned dim,int value)6620 __isl_give isl_set *isl_set_fix_dim_si(__isl_take isl_set *set, unsigned dim,
6621 	int value)
6622 {
6623 	return set_from_map(isl_map_fix_si(set_to_map(set),
6624 						isl_dim_set, dim, value));
6625 }
6626 
basic_map_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value,int upper)6627 static __isl_give isl_basic_map *basic_map_bound_si(
6628 	__isl_take isl_basic_map *bmap,
6629 	enum isl_dim_type type, unsigned pos, int value, int upper)
6630 {
6631 	int j;
6632 	isl_size total;
6633 
6634 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6635 		return isl_basic_map_free(bmap);
6636 	total = isl_basic_map_dim(bmap, isl_dim_all);
6637 	if (total < 0)
6638 		return isl_basic_map_free(bmap);
6639 	pos += isl_basic_map_offset(bmap, type);
6640 	bmap = isl_basic_map_cow(bmap);
6641 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6642 	j = isl_basic_map_alloc_inequality(bmap);
6643 	if (j < 0)
6644 		goto error;
6645 	isl_seq_clr(bmap->ineq[j], 1 + total);
6646 	if (upper) {
6647 		isl_int_set_si(bmap->ineq[j][pos], -1);
6648 		isl_int_set_si(bmap->ineq[j][0], value);
6649 	} else {
6650 		isl_int_set_si(bmap->ineq[j][pos], 1);
6651 		isl_int_set_si(bmap->ineq[j][0], -value);
6652 	}
6653 	bmap = isl_basic_map_simplify(bmap);
6654 	return isl_basic_map_finalize(bmap);
6655 error:
6656 	isl_basic_map_free(bmap);
6657 	return NULL;
6658 }
6659 
isl_basic_map_lower_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6660 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6661 	__isl_take isl_basic_map *bmap,
6662 	enum isl_dim_type type, unsigned pos, int value)
6663 {
6664 	return basic_map_bound_si(bmap, type, pos, value, 0);
6665 }
6666 
6667 /* Constrain the values of the given dimension to be no greater than "value".
6668  */
isl_basic_map_upper_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6669 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6670 	__isl_take isl_basic_map *bmap,
6671 	enum isl_dim_type type, unsigned pos, int value)
6672 {
6673 	return basic_map_bound_si(bmap, type, pos, value, 1);
6674 }
6675 
map_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value,int upper)6676 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6677 	enum isl_dim_type type, unsigned pos, int value, int upper)
6678 {
6679 	int i;
6680 
6681 	map = isl_map_cow(map);
6682 	if (isl_map_check_range(map, type, pos, 1) < 0)
6683 		return isl_map_free(map);
6684 	for (i = 0; i < map->n; ++i) {
6685 		map->p[i] = basic_map_bound_si(map->p[i],
6686 						 type, pos, value, upper);
6687 		if (!map->p[i])
6688 			goto error;
6689 	}
6690 	map = isl_map_unmark_normalized(map);
6691 	return map;
6692 error:
6693 	isl_map_free(map);
6694 	return NULL;
6695 }
6696 
isl_map_lower_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6697 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6698 	enum isl_dim_type type, unsigned pos, int value)
6699 {
6700 	return map_bound_si(map, type, pos, value, 0);
6701 }
6702 
isl_map_upper_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6703 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6704 	enum isl_dim_type type, unsigned pos, int value)
6705 {
6706 	return map_bound_si(map, type, pos, value, 1);
6707 }
6708 
isl_set_lower_bound_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6709 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6710 		enum isl_dim_type type, unsigned pos, int value)
6711 {
6712 	return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6713 							type, pos, value));
6714 }
6715 
isl_set_upper_bound_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6716 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6717 	enum isl_dim_type type, unsigned pos, int value)
6718 {
6719 	return isl_map_upper_bound_si(set, type, pos, value);
6720 }
6721 
6722 /* Bound the given variable of "bmap" from below (or above is "upper"
6723  * is set) to "value".
6724  */
basic_map_bound(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6725 static __isl_give isl_basic_map *basic_map_bound(
6726 	__isl_take isl_basic_map *bmap,
6727 	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6728 {
6729 	int j;
6730 	isl_size total;
6731 
6732 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6733 		return isl_basic_map_free(bmap);
6734 	total = isl_basic_map_dim(bmap, isl_dim_all);
6735 	if (total < 0)
6736 		return isl_basic_map_free(bmap);
6737 	pos += isl_basic_map_offset(bmap, type);
6738 	bmap = isl_basic_map_cow(bmap);
6739 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6740 	j = isl_basic_map_alloc_inequality(bmap);
6741 	if (j < 0)
6742 		goto error;
6743 	isl_seq_clr(bmap->ineq[j], 1 + total);
6744 	if (upper) {
6745 		isl_int_set_si(bmap->ineq[j][pos], -1);
6746 		isl_int_set(bmap->ineq[j][0], value);
6747 	} else {
6748 		isl_int_set_si(bmap->ineq[j][pos], 1);
6749 		isl_int_neg(bmap->ineq[j][0], value);
6750 	}
6751 	bmap = isl_basic_map_simplify(bmap);
6752 	return isl_basic_map_finalize(bmap);
6753 error:
6754 	isl_basic_map_free(bmap);
6755 	return NULL;
6756 }
6757 
6758 /* Bound the given variable of "map" from below (or above is "upper"
6759  * is set) to "value".
6760  */
map_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6761 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6762 	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6763 {
6764 	int i;
6765 
6766 	map = isl_map_cow(map);
6767 	if (isl_map_check_range(map, type, pos, 1) < 0)
6768 		return isl_map_free(map);
6769 	for (i = map->n - 1; i >= 0; --i) {
6770 		map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6771 		map = remove_if_empty(map, i);
6772 		if (!map)
6773 			return NULL;
6774 	}
6775 	map = isl_map_unmark_normalized(map);
6776 	return map;
6777 }
6778 
isl_map_lower_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6779 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6780 	enum isl_dim_type type, unsigned pos, isl_int value)
6781 {
6782 	return map_bound(map, type, pos, value, 0);
6783 }
6784 
isl_map_upper_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6785 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6786 	enum isl_dim_type type, unsigned pos, isl_int value)
6787 {
6788 	return map_bound(map, type, pos, value, 1);
6789 }
6790 
isl_set_lower_bound(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6791 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6792 	enum isl_dim_type type, unsigned pos, isl_int value)
6793 {
6794 	return isl_map_lower_bound(set, type, pos, value);
6795 }
6796 
isl_set_upper_bound(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6797 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6798 	enum isl_dim_type type, unsigned pos, isl_int value)
6799 {
6800 	return isl_map_upper_bound(set, type, pos, value);
6801 }
6802 
6803 /* Force the values of the variable at position "pos" of type "type" of "map"
6804  * to be no smaller than "value".
6805  */
isl_map_lower_bound_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6806 __isl_give isl_map *isl_map_lower_bound_val(__isl_take isl_map *map,
6807 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6808 {
6809 	if (!value)
6810 		goto error;
6811 	if (!isl_val_is_int(value))
6812 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
6813 			"expecting integer value", goto error);
6814 	map = isl_map_lower_bound(map, type, pos, value->n);
6815 	isl_val_free(value);
6816 	return map;
6817 error:
6818 	isl_val_free(value);
6819 	isl_map_free(map);
6820 	return NULL;
6821 }
6822 
6823 /* Force the values of the variable at position "pos" of type "type" of "set"
6824  * to be no smaller than "value".
6825  */
isl_set_lower_bound_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6826 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6827 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6828 {
6829 	isl_map *map;
6830 
6831 	map = set_to_map(set);
6832 	return set_from_map(isl_map_lower_bound_val(map, type, pos, value));
6833 }
6834 
6835 /* Force the values of the variable at position "pos" of type "type" of "map"
6836  * to be no greater than "value".
6837  */
isl_map_upper_bound_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6838 __isl_give isl_map *isl_map_upper_bound_val(__isl_take isl_map *map,
6839 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6840 {
6841 	if (!value)
6842 		goto error;
6843 	if (!isl_val_is_int(value))
6844 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
6845 			"expecting integer value", goto error);
6846 	map = isl_map_upper_bound(map, type, pos, value->n);
6847 	isl_val_free(value);
6848 	return map;
6849 error:
6850 	isl_val_free(value);
6851 	isl_map_free(map);
6852 	return NULL;
6853 }
6854 
6855 /* Force the values of the variable at position "pos" of type "type" of "set"
6856  * to be no greater than "value".
6857  */
isl_set_upper_bound_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6858 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6859 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6860 {
6861 	isl_map *map;
6862 
6863 	map = set_to_map(set);
6864 	return set_from_map(isl_map_upper_bound_val(map, type, pos, value));
6865 }
6866 
6867 #undef BASE
6868 #define BASE	val
6869 #include "isl_map_bound_templ.c"
6870 
6871 /* Apply "map_bound" to "set" with the corresponding value in "bound"
6872  * for each set dimension, by treating the set as a map.
6873  */
set_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * bound,__isl_give isl_map * map_bound (__isl_take isl_map * map,unsigned pos,__isl_take isl_val * value))6874 static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,
6875 	__isl_take isl_multi_val *bound,
6876 	__isl_give isl_map *map_bound(__isl_take isl_map *map,
6877 		unsigned pos, __isl_take isl_val *value))
6878 {
6879 	isl_map *map;
6880 
6881 	map = set_to_map(set);
6882 	return set_from_map(map_bound_multi_val(map, bound, map_bound));
6883 }
6884 
6885 #undef BASE
6886 #define BASE	pw_aff
6887 #include "isl_map_bound_templ.c"
6888 
6889 /* Apply "map_bound" to "set" with the corresponding value in "bound"
6890  * for each set dimension, by converting the set and the bound
6891  * to objects living in a map space.
6892  */
set_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * bound,__isl_give isl_map * set_bound (__isl_take isl_map * map,unsigned pos,__isl_take TYPE * value))6893 static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,
6894 	__isl_take isl_multi_pw_aff *bound,
6895 	__isl_give isl_map *set_bound(__isl_take isl_map *map,
6896 		unsigned pos, __isl_take TYPE *value))
6897 {
6898 	isl_map *map;
6899 
6900 	map = isl_map_from_range(set);
6901 	bound = isl_multi_pw_aff_from_range(bound);
6902 	map = map_bound_multi_pw_aff(map, bound, set_bound);
6903 	return isl_map_range(map);
6904 }
6905 
6906 /* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,
6907  * setting a bound on the given output dimension.
6908  */
map_lower_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)6909 static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,
6910 	unsigned pos, __isl_take isl_val *v)
6911 {
6912 	return isl_map_lower_bound_val(map, isl_dim_out, pos, v);
6913 }
6914 
6915 /* Force the values of the set dimensions of "set"
6916  * to be no smaller than the corresponding values in "lower".
6917  */
isl_set_lower_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * lower)6918 __isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
6919 	__isl_take isl_multi_val *lower)
6920 {
6921 	return set_bound_multi_val(set, lower, &map_lower_bound_val);
6922 }
6923 
6924 /* Force the values of the output dimensions of "map"
6925  * to be no smaller than the corresponding values in "lower".
6926  */
isl_map_lower_bound_multi_val(__isl_take isl_map * map,__isl_take isl_multi_val * lower)6927 __isl_give isl_map *isl_map_lower_bound_multi_val(__isl_take isl_map *map,
6928 	__isl_take isl_multi_val *lower)
6929 {
6930 	return map_bound_multi_val(map, lower, &map_lower_bound_val);
6931 }
6932 
6933 /* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,
6934  * setting a bound on the given output dimension.
6935  */
map_upper_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)6936 static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,
6937 	unsigned pos, __isl_take isl_val *v)
6938 {
6939 	return isl_map_upper_bound_val(map, isl_dim_out, pos, v);
6940 }
6941 
6942 /* Force the values of the set dimensions of "set"
6943  * to be no greater than the corresponding values in "upper".
6944  */
isl_set_upper_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * upper)6945 __isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
6946 	__isl_take isl_multi_val *upper)
6947 {
6948 	return set_bound_multi_val(set, upper, &map_upper_bound_val);
6949 }
6950 
6951 /* Force the values of the set dimensions of "set"
6952  * to be no greater than the corresponding values in "upper".
6953  */
isl_map_upper_bound_multi_val(__isl_take isl_map * map,__isl_take isl_multi_val * upper)6954 __isl_give isl_map *isl_map_upper_bound_multi_val(__isl_take isl_map *map,
6955 	__isl_take isl_multi_val *upper)
6956 {
6957 	return map_bound_multi_val(map, upper, &map_upper_bound_val);
6958 }
6959 
6960 /* Force the symbolic constant expression "bound"
6961  * to satisfy the relation "order" with respect to
6962  * the output variable at position "pos" of "map".
6963  *
6964  * Create an affine expression representing the output variable
6965  * in terms of the range and
6966  * compare it using "order" to "bound" (defined on the domain).
6967  * The result is a relation between elements in domain and range that
6968  * can be intersected with "map".
6969  */
map_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * bound,__isl_give isl_map * (* order)(__isl_take isl_pw_aff * pa1,__isl_take isl_pw_aff * pa2))6970 static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,
6971 	unsigned pos, __isl_take isl_pw_aff *bound,
6972 	__isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,
6973 		__isl_take isl_pw_aff *pa2))
6974 {
6975 	isl_space *space;
6976 	isl_local_space *ls;
6977 	isl_pw_aff *var;
6978 
6979 	space = isl_space_range(isl_map_get_space(map));
6980 	ls = isl_local_space_from_space(space);
6981 	var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);
6982 	map = isl_map_intersect(map, order(bound, var));
6983 	return map;
6984 }
6985 
6986 /* Force the values of the output variable at position "pos" of "map"
6987  * to be no smaller than the symbolic constant expression "lower".
6988  */
map_lower_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * lower)6989 static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,
6990 	unsigned pos, __isl_take isl_pw_aff *lower)
6991 {
6992 	return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);
6993 }
6994 
6995 /* Force the values of the output variable at position "pos" of "map"
6996  * to be no greater than the symbolic constant expression "upper".
6997  */
map_upper_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * upper)6998 static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,
6999 	unsigned pos, __isl_take isl_pw_aff *upper)
7000 {
7001 	return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);
7002 }
7003 
7004 /* Force the values of the set dimensions of "set"
7005  * to be no smaller than the corresponding constant symbolic expressions
7006  * in "lower".
7007  */
isl_set_lower_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * lower)7008 __isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
7009 	__isl_take isl_multi_pw_aff *lower)
7010 {
7011 	return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);
7012 }
7013 
7014 /* Force the values of the set dimensions of "set"
7015  * to be no greater than the corresponding constant symbolic expressions
7016  * in "upper".
7017  */
isl_set_upper_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * upper)7018 __isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
7019 	__isl_take isl_multi_pw_aff *upper)
7020 {
7021 	return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);
7022 }
7023 
7024 /* Force the values of the output dimensions of "map"
7025  * to be no smaller than the corresponding constant symbolic expressions
7026  * in "lower".
7027  */
isl_map_lower_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * lower)7028 __isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
7029 	__isl_take isl_multi_pw_aff *lower)
7030 {
7031 	return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);
7032 }
7033 
7034 /* Force the values of the output dimensions of "map"
7035  * to be no greater than the corresponding constant symbolic expressions
7036  * in "upper".
7037  */
isl_map_upper_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * upper)7038 __isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
7039 	__isl_take isl_multi_pw_aff *upper)
7040 {
7041 	return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);
7042 }
7043 
7044 /* Bound the given variable of "bset" from below (or above is "upper"
7045  * is set) to "value".
7046  */
isl_basic_set_bound(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value,int upper)7047 static __isl_give isl_basic_set *isl_basic_set_bound(
7048 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7049 	isl_int value, int upper)
7050 {
7051 	return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
7052 						type, pos, value, upper));
7053 }
7054 
7055 /* Bound the given variable of "bset" from below (or above is "upper"
7056  * is set) to "value".
7057  */
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)7058 static __isl_give isl_basic_set *isl_basic_set_bound_val(
7059 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7060 	__isl_take isl_val *value, int upper)
7061 {
7062 	if (!value)
7063 		goto error;
7064 	if (!isl_val_is_int(value))
7065 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
7066 			"expecting integer value", goto error);
7067 	bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
7068 	isl_val_free(value);
7069 	return bset;
7070 error:
7071 	isl_val_free(value);
7072 	isl_basic_set_free(bset);
7073 	return NULL;
7074 }
7075 
7076 /* Bound the given variable of "bset" from below to "value".
7077  */
isl_basic_set_lower_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7078 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
7079 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7080 	__isl_take isl_val *value)
7081 {
7082 	return isl_basic_set_bound_val(bset, type, pos, value, 0);
7083 }
7084 
7085 /* Bound the given variable of "bset" from above to "value".
7086  */
isl_basic_set_upper_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7087 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
7088 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7089 	__isl_take isl_val *value)
7090 {
7091 	return isl_basic_set_bound_val(bset, type, pos, value, 1);
7092 }
7093 
isl_map_reverse(__isl_take isl_map * map)7094 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
7095 {
7096 	return isl_map_transform(map, &isl_space_reverse,
7097 					&isl_basic_map_reverse);
7098 }
7099 
7100 /* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).
7101  */
isl_map_range_reverse(__isl_take isl_map * map)7102 __isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)
7103 {
7104 	return isl_map_transform(map, &isl_space_range_reverse,
7105 					&isl_basic_map_range_reverse);
7106 }
7107 
7108 #undef TYPE
7109 #define TYPE	isl_pw_multi_aff
7110 #undef SUFFIX
7111 #define SUFFIX	_pw_multi_aff
7112 #undef EMPTY
7113 #define EMPTY	isl_pw_multi_aff_empty
7114 #undef ADD
7115 #define ADD	isl_pw_multi_aff_union_add
7116 #include "isl_map_lexopt_templ.c"
7117 
7118 /* Given a map "map", compute the lexicographically minimal
7119  * (or maximal) image element for each domain element in dom,
7120  * in the form of an isl_pw_multi_aff.
7121  * If "empty" is not NULL, then set *empty to those elements in dom that
7122  * do not have an image element.
7123  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7124  * should be computed over the domain of "map".  "empty" is also NULL
7125  * in this case.
7126  *
7127  * We first compute the lexicographically minimal or maximal element
7128  * in the first basic map.  This results in a partial solution "res"
7129  * and a subset "todo" of dom that still need to be handled.
7130  * We then consider each of the remaining maps in "map" and successively
7131  * update both "res" and "todo".
7132  * If "empty" is NULL, then the todo sets are not needed and therefore
7133  * also not computed.
7134  */
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)7135 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
7136 	__isl_take isl_map *map, __isl_take isl_set *dom,
7137 	__isl_give isl_set **empty, unsigned flags)
7138 {
7139 	int i;
7140 	int full;
7141 	isl_pw_multi_aff *res;
7142 	isl_set *todo;
7143 
7144 	full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7145 	if (!map || (!full && !dom))
7146 		goto error;
7147 
7148 	if (isl_map_plain_is_empty(map)) {
7149 		if (empty)
7150 			*empty = dom;
7151 		else
7152 			isl_set_free(dom);
7153 		return isl_pw_multi_aff_from_map(map);
7154 	}
7155 
7156 	res = basic_map_partial_lexopt_pw_multi_aff(
7157 					    isl_basic_map_copy(map->p[0]),
7158 					    isl_set_copy(dom), empty, flags);
7159 
7160 	if (empty)
7161 		todo = *empty;
7162 	for (i = 1; i < map->n; ++i) {
7163 		isl_pw_multi_aff *res_i;
7164 
7165 		res_i = basic_map_partial_lexopt_pw_multi_aff(
7166 					    isl_basic_map_copy(map->p[i]),
7167 					    isl_set_copy(dom), empty, flags);
7168 
7169 		if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
7170 			res = isl_pw_multi_aff_union_lexmax(res, res_i);
7171 		else
7172 			res = isl_pw_multi_aff_union_lexmin(res, res_i);
7173 
7174 		if (empty)
7175 			todo = isl_set_intersect(todo, *empty);
7176 	}
7177 
7178 	isl_set_free(dom);
7179 	isl_map_free(map);
7180 
7181 	if (empty)
7182 		*empty = todo;
7183 
7184 	return res;
7185 error:
7186 	if (empty)
7187 		*empty = NULL;
7188 	isl_set_free(dom);
7189 	isl_map_free(map);
7190 	return NULL;
7191 }
7192 
7193 #undef TYPE
7194 #define TYPE	isl_map
7195 #undef SUFFIX
7196 #define SUFFIX
7197 #undef EMPTY
7198 #define EMPTY	isl_map_empty
7199 #undef ADD
7200 #define ADD	isl_map_union_disjoint
7201 #include "isl_map_lexopt_templ.c"
7202 
7203 /* Given a map "map", compute the lexicographically minimal
7204  * (or maximal) image element for each domain element in "dom",
7205  * in the form of an isl_map.
7206  * If "empty" is not NULL, then set *empty to those elements in "dom" that
7207  * do not have an image element.
7208  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7209  * should be computed over the domain of "map".  "empty" is also NULL
7210  * in this case.
7211  *
7212  * If the input consists of more than one disjunct, then first
7213  * compute the desired result in the form of an isl_pw_multi_aff and
7214  * then convert that into an isl_map.
7215  *
7216  * This function used to have an explicit implementation in terms
7217  * of isl_maps, but it would continually intersect the domains of
7218  * partial results with the complement of the domain of the next
7219  * partial solution, potentially leading to an explosion in the number
7220  * of disjuncts if there are several disjuncts in the input.
7221  * An even earlier implementation of this function would look for
7222  * better results in the domain of the partial result and for extra
7223  * results in the complement of this domain, which would lead to
7224  * even more splintering.
7225  */
isl_map_partial_lexopt_aligned(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty,unsigned flags)7226 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
7227 	__isl_take isl_map *map, __isl_take isl_set *dom,
7228 	__isl_give isl_set **empty, unsigned flags)
7229 {
7230 	int full;
7231 	struct isl_map *res;
7232 	isl_pw_multi_aff *pma;
7233 
7234 	full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7235 	if (!map || (!full && !dom))
7236 		goto error;
7237 
7238 	if (isl_map_plain_is_empty(map)) {
7239 		if (empty)
7240 			*empty = dom;
7241 		else
7242 			isl_set_free(dom);
7243 		return map;
7244 	}
7245 
7246 	if (map->n == 1) {
7247 		res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
7248 						dom, empty, flags);
7249 		isl_map_free(map);
7250 		return res;
7251 	}
7252 
7253 	pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
7254 							flags);
7255 	return isl_map_from_pw_multi_aff_internal(pma);
7256 error:
7257 	if (empty)
7258 		*empty = NULL;
7259 	isl_set_free(dom);
7260 	isl_map_free(map);
7261 	return NULL;
7262 }
7263 
isl_map_partial_lexmax(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7264 __isl_give isl_map *isl_map_partial_lexmax(
7265 		__isl_take isl_map *map, __isl_take isl_set *dom,
7266 		__isl_give isl_set **empty)
7267 {
7268 	return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
7269 }
7270 
isl_map_partial_lexmin(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7271 __isl_give isl_map *isl_map_partial_lexmin(
7272 		__isl_take isl_map *map, __isl_take isl_set *dom,
7273 		__isl_give isl_set **empty)
7274 {
7275 	return isl_map_partial_lexopt(map, dom, empty, 0);
7276 }
7277 
isl_set_partial_lexmin(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7278 __isl_give isl_set *isl_set_partial_lexmin(
7279 		__isl_take isl_set *set, __isl_take isl_set *dom,
7280 		__isl_give isl_set **empty)
7281 {
7282 	return set_from_map(isl_map_partial_lexmin(set_to_map(set),
7283 						    dom, empty));
7284 }
7285 
isl_set_partial_lexmax(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7286 __isl_give isl_set *isl_set_partial_lexmax(
7287 		__isl_take isl_set *set, __isl_take isl_set *dom,
7288 		__isl_give isl_set **empty)
7289 {
7290 	return set_from_map(isl_map_partial_lexmax(set_to_map(set),
7291 						    dom, empty));
7292 }
7293 
7294 /* Compute the lexicographic minimum (or maximum if "flags" includes
7295  * ISL_OPT_MAX) of "bset" over its parametric domain.
7296  */
isl_basic_set_lexopt(__isl_take isl_basic_set * bset,unsigned flags)7297 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
7298 	unsigned flags)
7299 {
7300 	return isl_basic_map_lexopt(bset, flags);
7301 }
7302 
isl_basic_map_lexmax(__isl_take isl_basic_map * bmap)7303 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
7304 {
7305 	return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
7306 }
7307 
isl_basic_set_lexmin(__isl_take isl_basic_set * bset)7308 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
7309 {
7310 	return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
7311 }
7312 
isl_basic_set_lexmax(__isl_take isl_basic_set * bset)7313 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
7314 {
7315 	return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
7316 }
7317 
7318 /* Compute the lexicographic minimum of "bset" over its parametric domain
7319  * for the purpose of quantifier elimination.
7320  * That is, find an explicit representation for all the existentially
7321  * quantified variables in "bset" by computing their lexicographic
7322  * minimum.
7323  */
isl_basic_set_lexmin_compute_divs(__isl_take isl_basic_set * bset)7324 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
7325 	__isl_take isl_basic_set *bset)
7326 {
7327 	return isl_basic_set_lexopt(bset, ISL_OPT_QE);
7328 }
7329 
7330 /* Given a basic map with one output dimension, compute the minimum or
7331  * maximum of that dimension as an isl_pw_aff.
7332  *
7333  * Compute the optimum as a lexicographic optimum over the single
7334  * output dimension and extract the single isl_pw_aff from the result.
7335  */
basic_map_dim_opt(__isl_keep isl_basic_map * bmap,int max)7336 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
7337 	int max)
7338 {
7339 	isl_pw_multi_aff *pma;
7340 	isl_pw_aff *pwaff;
7341 
7342 	bmap = isl_basic_map_copy(bmap);
7343 	pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
7344 	pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
7345 	isl_pw_multi_aff_free(pma);
7346 
7347 	return pwaff;
7348 }
7349 
7350 /* Compute the minimum or maximum of the given output dimension
7351  * as a function of the parameters and the input dimensions,
7352  * but independently of the other output dimensions.
7353  *
7354  * We first project out the other output dimension and then compute
7355  * the "lexicographic" maximum in each basic map, combining the results
7356  * using isl_pw_aff_union_max.
7357  */
map_dim_opt(__isl_take isl_map * map,int pos,int max)7358 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
7359 	int max)
7360 {
7361 	int i;
7362 	isl_pw_aff *pwaff;
7363 	isl_size n_out;
7364 
7365 	n_out = isl_map_dim(map, isl_dim_out);
7366 	if (n_out < 0)
7367 		map = isl_map_free(map);
7368 	map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7369 	map = isl_map_project_out(map, isl_dim_out, 0, pos);
7370 	if (!map)
7371 		return NULL;
7372 
7373 	if (map->n == 0) {
7374 		isl_space *space = isl_map_get_space(map);
7375 		isl_map_free(map);
7376 		return isl_pw_aff_empty(space);
7377 	}
7378 
7379 	pwaff = basic_map_dim_opt(map->p[0], max);
7380 	for (i = 1; i < map->n; ++i) {
7381 		isl_pw_aff *pwaff_i;
7382 
7383 		pwaff_i = basic_map_dim_opt(map->p[i], max);
7384 		pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7385 	}
7386 
7387 	isl_map_free(map);
7388 
7389 	return pwaff;
7390 }
7391 
7392 /* Compute the minimum of the given output dimension as a function of the
7393  * parameters and input dimensions, but independently of
7394  * the other output dimensions.
7395  */
isl_map_dim_min(__isl_take isl_map * map,int pos)7396 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7397 {
7398 	return map_dim_opt(map, pos, 0);
7399 }
7400 
7401 /* Compute the maximum of the given output dimension as a function of the
7402  * parameters and input dimensions, but independently of
7403  * the other output dimensions.
7404  */
isl_map_dim_max(__isl_take isl_map * map,int pos)7405 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7406 {
7407 	return map_dim_opt(map, pos, 1);
7408 }
7409 
7410 /* Compute the minimum or maximum of the given set dimension
7411  * as a function of the parameters,
7412  * but independently of the other set dimensions.
7413  */
set_dim_opt(__isl_take isl_set * set,int pos,int max)7414 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7415 	int max)
7416 {
7417 	return map_dim_opt(set, pos, max);
7418 }
7419 
7420 /* Compute the maximum of the given set dimension as a function of the
7421  * parameters, but independently of the other set dimensions.
7422  */
isl_set_dim_max(__isl_take isl_set * set,int pos)7423 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7424 {
7425 	return set_dim_opt(set, pos, 1);
7426 }
7427 
7428 /* Compute the minimum of the given set dimension as a function of the
7429  * parameters, but independently of the other set dimensions.
7430  */
isl_set_dim_min(__isl_take isl_set * set,int pos)7431 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7432 {
7433 	return set_dim_opt(set, pos, 0);
7434 }
7435 
7436 /* Apply a preimage specified by "mat" on the parameters of "bset".
7437  * bset is assumed to have only parameters and divs.
7438  */
basic_set_parameter_preimage(__isl_take isl_basic_set * bset,__isl_take isl_mat * mat)7439 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7440 	__isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7441 {
7442 	isl_size nparam;
7443 
7444 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7445 	if (nparam < 0 || !mat)
7446 		goto error;
7447 
7448 	bset->dim = isl_space_cow(bset->dim);
7449 	if (!bset->dim)
7450 		goto error;
7451 
7452 	isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7453 
7454 	bset->dim->nparam = 0;
7455 	bset->dim->n_out = nparam;
7456 	bset = isl_basic_set_preimage(bset, mat);
7457 	if (bset) {
7458 		bset->dim->nparam = bset->dim->n_out;
7459 		bset->dim->n_out = 0;
7460 	}
7461 	return bset;
7462 error:
7463 	isl_mat_free(mat);
7464 	isl_basic_set_free(bset);
7465 	return NULL;
7466 }
7467 
7468 /* Apply a preimage specified by "mat" on the parameters of "set".
7469  * set is assumed to have only parameters and divs.
7470  */
set_parameter_preimage(__isl_take isl_set * set,__isl_take isl_mat * mat)7471 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7472 	__isl_take isl_mat *mat)
7473 {
7474 	isl_space *space;
7475 	isl_size nparam;
7476 
7477 	nparam = isl_set_dim(set, isl_dim_param);
7478 	if (nparam < 0 || !mat)
7479 		goto error;
7480 
7481 	if (mat->n_row != 1 + nparam)
7482 		isl_die(isl_set_get_ctx(set), isl_error_internal,
7483 			"unexpected number of rows", goto error);
7484 
7485 	space = isl_set_get_space(set);
7486 	space = isl_space_move_dims(space, isl_dim_set, 0,
7487 				    isl_dim_param, 0, nparam);
7488 	set = isl_set_reset_space(set, space);
7489 	set = isl_set_preimage(set, mat);
7490 	nparam = isl_set_dim(set, isl_dim_out);
7491 	if (nparam < 0)
7492 		set = isl_set_free(set);
7493 	space = isl_set_get_space(set);
7494 	space = isl_space_move_dims(space, isl_dim_param, 0,
7495 				    isl_dim_out, 0, nparam);
7496 	set = isl_set_reset_space(set, space);
7497 	return set;
7498 error:
7499 	isl_mat_free(mat);
7500 	isl_set_free(set);
7501 	return NULL;
7502 }
7503 
7504 /* Intersect the basic set "bset" with the affine space specified by the
7505  * equalities in "eq".
7506  */
basic_set_append_equalities(__isl_take isl_basic_set * bset,__isl_take isl_mat * eq)7507 static __isl_give isl_basic_set *basic_set_append_equalities(
7508 	__isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7509 {
7510 	int i, k;
7511 	unsigned len;
7512 
7513 	if (!bset || !eq)
7514 		goto error;
7515 
7516 	bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);
7517 	if (!bset)
7518 		goto error;
7519 
7520 	len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7521 	for (i = 0; i < eq->n_row; ++i) {
7522 		k = isl_basic_set_alloc_equality(bset);
7523 		if (k < 0)
7524 			goto error;
7525 		isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7526 		isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7527 	}
7528 	isl_mat_free(eq);
7529 
7530 	bset = isl_basic_set_gauss(bset, NULL);
7531 	bset = isl_basic_set_finalize(bset);
7532 
7533 	return bset;
7534 error:
7535 	isl_mat_free(eq);
7536 	isl_basic_set_free(bset);
7537 	return NULL;
7538 }
7539 
7540 /* Intersect the set "set" with the affine space specified by the
7541  * equalities in "eq".
7542  */
set_append_equalities(__isl_take isl_set * set,__isl_take isl_mat * eq)7543 static __isl_give isl_set *set_append_equalities(__isl_take isl_set *set,
7544 	__isl_take isl_mat *eq)
7545 {
7546 	int i;
7547 
7548 	if (!set || !eq)
7549 		goto error;
7550 
7551 	for (i = 0; i < set->n; ++i) {
7552 		set->p[i] = basic_set_append_equalities(set->p[i],
7553 					isl_mat_copy(eq));
7554 		if (!set->p[i])
7555 			goto error;
7556 	}
7557 	isl_mat_free(eq);
7558 	return set;
7559 error:
7560 	isl_mat_free(eq);
7561 	isl_set_free(set);
7562 	return NULL;
7563 }
7564 
7565 /* Given a basic set "bset" that only involves parameters and existentially
7566  * quantified variables, return the index of the first equality
7567  * that only involves parameters.  If there is no such equality then
7568  * return bset->n_eq.
7569  *
7570  * This function assumes that isl_basic_set_gauss has been called on "bset".
7571  */
first_parameter_equality(__isl_keep isl_basic_set * bset)7572 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7573 {
7574 	int i, j;
7575 	isl_size nparam, n_div;
7576 
7577 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7578 	n_div = isl_basic_set_dim(bset, isl_dim_div);
7579 	if (nparam < 0 || n_div < 0)
7580 		return -1;
7581 
7582 	for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7583 		if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7584 			++i;
7585 	}
7586 
7587 	return i;
7588 }
7589 
7590 /* Compute an explicit representation for the existentially quantified
7591  * variables in "bset" by computing the "minimal value" of the set
7592  * variables.  Since there are no set variables, the computation of
7593  * the minimal value essentially computes an explicit representation
7594  * of the non-empty part(s) of "bset".
7595  *
7596  * The input only involves parameters and existentially quantified variables.
7597  * All equalities among parameters have been removed.
7598  *
7599  * Since the existentially quantified variables in the result are in general
7600  * going to be different from those in the input, we first replace
7601  * them by the minimal number of variables based on their equalities.
7602  * This should simplify the parametric integer programming.
7603  */
base_compute_divs(__isl_take isl_basic_set * bset)7604 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7605 {
7606 	isl_morph *morph1, *morph2;
7607 	isl_set *set;
7608 	isl_size n;
7609 
7610 	if (!bset)
7611 		return NULL;
7612 	if (bset->n_eq == 0)
7613 		return isl_basic_set_lexmin_compute_divs(bset);
7614 
7615 	morph1 = isl_basic_set_parameter_compression(bset);
7616 	bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7617 	bset = isl_basic_set_lift(bset);
7618 	morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7619 	bset = isl_morph_basic_set(morph2, bset);
7620 	n = isl_basic_set_dim(bset, isl_dim_set);
7621 	if (n < 0)
7622 		bset = isl_basic_set_free(bset);
7623 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7624 
7625 	set = isl_basic_set_lexmin_compute_divs(bset);
7626 
7627 	set = isl_morph_set(isl_morph_inverse(morph1), set);
7628 
7629 	return set;
7630 }
7631 
7632 /* Project the given basic set onto its parameter domain, possibly introducing
7633  * new, explicit, existential variables in the constraints.
7634  * The input has parameters and (possibly implicit) existential variables.
7635  * The output has the same parameters, but only
7636  * explicit existentially quantified variables.
7637  *
7638  * The actual projection is performed by pip, but pip doesn't seem
7639  * to like equalities very much, so we first remove the equalities
7640  * among the parameters by performing a variable compression on
7641  * the parameters.  Afterward, an inverse transformation is performed
7642  * and the equalities among the parameters are inserted back in.
7643  *
7644  * The variable compression on the parameters may uncover additional
7645  * equalities that were only implicit before.  We therefore check
7646  * if there are any new parameter equalities in the result and
7647  * if so recurse.  The removal of parameter equalities is required
7648  * for the parameter compression performed by base_compute_divs.
7649  */
parameter_compute_divs(__isl_take isl_basic_set * bset)7650 static __isl_give isl_set *parameter_compute_divs(
7651 	__isl_take isl_basic_set *bset)
7652 {
7653 	int i;
7654 	struct isl_mat *eq;
7655 	struct isl_mat *T, *T2;
7656 	struct isl_set *set;
7657 	isl_size nparam;
7658 
7659 	bset = isl_basic_set_cow(bset);
7660 	if (!bset)
7661 		return NULL;
7662 
7663 	if (bset->n_eq == 0)
7664 		return base_compute_divs(bset);
7665 
7666 	bset = isl_basic_set_gauss(bset, NULL);
7667 	if (!bset)
7668 		return NULL;
7669 	if (isl_basic_set_plain_is_empty(bset))
7670 		return isl_set_from_basic_set(bset);
7671 
7672 	i = first_parameter_equality(bset);
7673 	if (i == bset->n_eq)
7674 		return base_compute_divs(bset);
7675 
7676 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7677 	if (nparam < 0)
7678 		return isl_set_from_basic_set(isl_basic_set_free(bset));
7679 	eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7680 		0, 1 + nparam);
7681 	eq = isl_mat_cow(eq);
7682 	T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7683 	if (T && T->n_col == 0) {
7684 		isl_mat_free(T);
7685 		isl_mat_free(T2);
7686 		isl_mat_free(eq);
7687 		bset = isl_basic_set_set_to_empty(bset);
7688 		return isl_set_from_basic_set(bset);
7689 	}
7690 	bset = basic_set_parameter_preimage(bset, T);
7691 
7692 	i = first_parameter_equality(bset);
7693 	if (!bset)
7694 		set = NULL;
7695 	else if (i == bset->n_eq)
7696 		set = base_compute_divs(bset);
7697 	else
7698 		set = parameter_compute_divs(bset);
7699 	set = set_parameter_preimage(set, T2);
7700 	set = set_append_equalities(set, eq);
7701 	return set;
7702 }
7703 
7704 /* Insert the divs from "ls" before those of "bmap".
7705  *
7706  * The number of columns is not changed, which means that the last
7707  * dimensions of "bmap" are being reintepreted as the divs from "ls".
7708  * The caller is responsible for removing the same number of dimensions
7709  * from the space of "bmap".
7710  */
insert_divs_from_local_space(__isl_take isl_basic_map * bmap,__isl_keep isl_local_space * ls)7711 static __isl_give isl_basic_map *insert_divs_from_local_space(
7712 	__isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7713 {
7714 	int i;
7715 	isl_size n_div;
7716 	int old_n_div;
7717 
7718 	n_div = isl_local_space_dim(ls, isl_dim_div);
7719 	if (n_div < 0)
7720 		return isl_basic_map_free(bmap);
7721 	if (n_div == 0)
7722 		return bmap;
7723 
7724 	old_n_div = bmap->n_div;
7725 	bmap = insert_div_rows(bmap, n_div);
7726 	if (!bmap)
7727 		return NULL;
7728 
7729 	for (i = 0; i < n_div; ++i) {
7730 		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7731 		isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7732 	}
7733 
7734 	return bmap;
7735 }
7736 
7737 /* Replace the space of "bmap" by the space and divs of "ls".
7738  *
7739  * If "ls" has any divs, then we simplify the result since we may
7740  * have discovered some additional equalities that could simplify
7741  * the div expressions.
7742  */
basic_replace_space_by_local_space(__isl_take isl_basic_map * bmap,__isl_take isl_local_space * ls)7743 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7744 	__isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7745 {
7746 	isl_size n_div;
7747 
7748 	bmap = isl_basic_map_cow(bmap);
7749 	n_div = isl_local_space_dim(ls, isl_dim_div);
7750 	if (!bmap || n_div < 0)
7751 		goto error;
7752 
7753 	bmap = insert_divs_from_local_space(bmap, ls);
7754 	if (!bmap)
7755 		goto error;
7756 
7757 	isl_space_free(bmap->dim);
7758 	bmap->dim = isl_local_space_get_space(ls);
7759 	if (!bmap->dim)
7760 		goto error;
7761 
7762 	isl_local_space_free(ls);
7763 	if (n_div > 0)
7764 		bmap = isl_basic_map_simplify(bmap);
7765 	bmap = isl_basic_map_finalize(bmap);
7766 	return bmap;
7767 error:
7768 	isl_basic_map_free(bmap);
7769 	isl_local_space_free(ls);
7770 	return NULL;
7771 }
7772 
7773 /* Replace the space of "map" by the space and divs of "ls".
7774  */
replace_space_by_local_space(__isl_take isl_map * map,__isl_take isl_local_space * ls)7775 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7776 	__isl_take isl_local_space *ls)
7777 {
7778 	int i;
7779 
7780 	map = isl_map_cow(map);
7781 	if (!map || !ls)
7782 		goto error;
7783 
7784 	for (i = 0; i < map->n; ++i) {
7785 		map->p[i] = basic_replace_space_by_local_space(map->p[i],
7786 						    isl_local_space_copy(ls));
7787 		if (!map->p[i])
7788 			goto error;
7789 	}
7790 	isl_space_free(isl_map_take_space(map));
7791 	map = isl_map_restore_space(map, isl_local_space_get_space(ls));
7792 
7793 	isl_local_space_free(ls);
7794 	return map;
7795 error:
7796 	isl_local_space_free(ls);
7797 	isl_map_free(map);
7798 	return NULL;
7799 }
7800 
7801 /* Compute an explicit representation for the existentially
7802  * quantified variables for which do not know any explicit representation yet.
7803  *
7804  * We first sort the existentially quantified variables so that the
7805  * existentially quantified variables for which we already have an explicit
7806  * representation are placed before those for which we do not.
7807  * The input dimensions, the output dimensions and the existentially
7808  * quantified variables for which we already have an explicit
7809  * representation are then turned into parameters.
7810  * compute_divs returns a map with the same parameters and
7811  * no input or output dimensions and the dimension specification
7812  * is reset to that of the input, including the existentially quantified
7813  * variables for which we already had an explicit representation.
7814  */
compute_divs(__isl_take isl_basic_map * bmap)7815 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7816 {
7817 	struct isl_basic_set *bset;
7818 	struct isl_set *set;
7819 	struct isl_map *map;
7820 	isl_space *space;
7821 	isl_local_space *ls;
7822 	isl_size nparam;
7823 	isl_size n_in;
7824 	isl_size n_out;
7825 	int n_known;
7826 	int i;
7827 
7828 	bmap = isl_basic_map_sort_divs(bmap);
7829 	bmap = isl_basic_map_cow(bmap);
7830 	if (!bmap)
7831 		return NULL;
7832 
7833 	n_known = isl_basic_map_first_unknown_div(bmap);
7834 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
7835 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
7836 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
7837 	if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
7838 		return isl_map_from_basic_map(isl_basic_map_free(bmap));
7839 
7840 	space = isl_space_set_alloc(bmap->ctx,
7841 				    nparam + n_in + n_out + n_known, 0);
7842 	if (!space)
7843 		goto error;
7844 
7845 	ls = isl_basic_map_get_local_space(bmap);
7846 	ls = isl_local_space_drop_dims(ls, isl_dim_div,
7847 					n_known, bmap->n_div - n_known);
7848 	if (n_known > 0) {
7849 		for (i = n_known; i < bmap->n_div; ++i)
7850 			swap_div(bmap, i - n_known, i);
7851 		bmap->n_div -= n_known;
7852 		bmap->extra -= n_known;
7853 	}
7854 	bmap = isl_basic_map_reset_space(bmap, space);
7855 	bset = bset_from_bmap(bmap);
7856 
7857 	set = parameter_compute_divs(bset);
7858 	map = set_to_map(set);
7859 	map = replace_space_by_local_space(map, ls);
7860 
7861 	return map;
7862 error:
7863 	isl_basic_map_free(bmap);
7864 	return NULL;
7865 }
7866 
7867 /* Remove the explicit representation of local variable "div",
7868  * if there is any.
7869  */
isl_basic_map_mark_div_unknown(__isl_take isl_basic_map * bmap,int div)7870 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7871 	__isl_take isl_basic_map *bmap, int div)
7872 {
7873 	isl_bool unknown;
7874 
7875 	unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7876 	if (unknown < 0)
7877 		return isl_basic_map_free(bmap);
7878 	if (unknown)
7879 		return bmap;
7880 
7881 	bmap = isl_basic_map_cow(bmap);
7882 	if (!bmap)
7883 		return NULL;
7884 	isl_int_set_si(bmap->div[div][0], 0);
7885 	return bmap;
7886 }
7887 
7888 /* Is local variable "div" of "bmap" marked as not having an explicit
7889  * representation?
7890  * Note that even if "div" is not marked in this way and therefore
7891  * has an explicit representation, this representation may still
7892  * depend (indirectly) on other local variables that do not
7893  * have an explicit representation.
7894  */
isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map * bmap,int div)7895 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7896 	int div)
7897 {
7898 	if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7899 		return isl_bool_error;
7900 	return isl_int_is_zero(bmap->div[div][0]);
7901 }
7902 
7903 /* Return the position of the first local variable that does not
7904  * have an explicit representation.
7905  * Return the total number of local variables if they all have
7906  * an explicit representation.
7907  * Return -1 on error.
7908  */
isl_basic_map_first_unknown_div(__isl_keep isl_basic_map * bmap)7909 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7910 {
7911 	int i;
7912 
7913 	if (!bmap)
7914 		return -1;
7915 
7916 	for (i = 0; i < bmap->n_div; ++i) {
7917 		if (!isl_basic_map_div_is_known(bmap, i))
7918 			return i;
7919 	}
7920 	return bmap->n_div;
7921 }
7922 
7923 /* Return the position of the first local variable that does not
7924  * have an explicit representation.
7925  * Return the total number of local variables if they all have
7926  * an explicit representation.
7927  * Return -1 on error.
7928  */
isl_basic_set_first_unknown_div(__isl_keep isl_basic_set * bset)7929 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7930 {
7931 	return isl_basic_map_first_unknown_div(bset);
7932 }
7933 
7934 /* Does "bmap" have an explicit representation for all local variables?
7935  */
isl_basic_map_divs_known(__isl_keep isl_basic_map * bmap)7936 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7937 {
7938 	int first;
7939 	isl_size n;
7940 
7941 	n = isl_basic_map_dim(bmap, isl_dim_div);
7942 	first = isl_basic_map_first_unknown_div(bmap);
7943 	if (n < 0 || first < 0)
7944 		return isl_bool_error;
7945 	return first == n;
7946 }
7947 
7948 /* Do all basic maps in "map" have an explicit representation
7949  * for all local variables?
7950  */
isl_map_divs_known(__isl_keep isl_map * map)7951 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7952 {
7953 	int i;
7954 
7955 	if (!map)
7956 		return isl_bool_error;
7957 
7958 	for (i = 0; i < map->n; ++i) {
7959 		int known = isl_basic_map_divs_known(map->p[i]);
7960 		if (known <= 0)
7961 			return known;
7962 	}
7963 
7964 	return isl_bool_true;
7965 }
7966 
7967 /* If bmap contains any unknown divs, then compute explicit
7968  * expressions for them.  However, this computation may be
7969  * quite expensive, so first try to remove divs that aren't
7970  * strictly needed.
7971  */
isl_basic_map_compute_divs(__isl_take isl_basic_map * bmap)7972 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7973 {
7974 	int known;
7975 	struct isl_map *map;
7976 
7977 	known = isl_basic_map_divs_known(bmap);
7978 	if (known < 0)
7979 		goto error;
7980 	if (known)
7981 		return isl_map_from_basic_map(bmap);
7982 
7983 	bmap = isl_basic_map_drop_redundant_divs(bmap);
7984 
7985 	known = isl_basic_map_divs_known(bmap);
7986 	if (known < 0)
7987 		goto error;
7988 	if (known)
7989 		return isl_map_from_basic_map(bmap);
7990 
7991 	map = compute_divs(bmap);
7992 	return map;
7993 error:
7994 	isl_basic_map_free(bmap);
7995 	return NULL;
7996 }
7997 
isl_map_compute_divs(__isl_take isl_map * map)7998 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7999 {
8000 	int i;
8001 	int known;
8002 	struct isl_map *res;
8003 
8004 	if (!map)
8005 		return NULL;
8006 	if (map->n == 0)
8007 		return map;
8008 
8009 	known = isl_map_divs_known(map);
8010 	if (known < 0) {
8011 		isl_map_free(map);
8012 		return NULL;
8013 	}
8014 	if (known)
8015 		return map;
8016 
8017 	res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
8018 	for (i = 1 ; i < map->n; ++i) {
8019 		struct isl_map *r2;
8020 		r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
8021 		if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
8022 			res = isl_map_union_disjoint(res, r2);
8023 		else
8024 			res = isl_map_union(res, r2);
8025 	}
8026 	isl_map_free(map);
8027 
8028 	return res;
8029 }
8030 
isl_basic_set_compute_divs(__isl_take isl_basic_set * bset)8031 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
8032 {
8033 	return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
8034 }
8035 
isl_set_compute_divs(__isl_take isl_set * set)8036 __isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set)
8037 {
8038 	return set_from_map(isl_map_compute_divs(set_to_map(set)));
8039 }
8040 
isl_map_domain(__isl_take isl_map * map)8041 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
8042 {
8043 	isl_space *space;
8044 	isl_size n_out;
8045 
8046 	n_out = isl_map_dim(map, isl_dim_out);
8047 	if (n_out < 0)
8048 		return set_from_map(isl_map_free(map));
8049 	space = isl_space_domain(isl_map_get_space(map));
8050 
8051 	map = isl_map_project_out(map, isl_dim_out, 0, n_out);
8052 
8053 	return set_from_map(isl_map_reset_space(map, space));
8054 }
8055 
8056 /* Return the union of "map1" and "map2", where we assume for now that
8057  * "map1" and "map2" are disjoint.  Note that the basic maps inside
8058  * "map1" or "map2" may not be disjoint from each other.
8059  * Also note that this function is also called from isl_map_union,
8060  * which takes care of handling the situation where "map1" and "map2"
8061  * may not be disjoint.
8062  *
8063  * If one of the inputs is empty, we can simply return the other input.
8064  * Similarly, if one of the inputs is universal, then it is equal to the union.
8065  */
map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8066 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
8067 	__isl_take isl_map *map2)
8068 {
8069 	int i;
8070 	unsigned flags = 0;
8071 	struct isl_map *map = NULL;
8072 	int is_universe;
8073 
8074 	if (isl_map_check_equal_space(map1, map2) < 0)
8075 		goto error;
8076 
8077 	if (map1->n == 0) {
8078 		isl_map_free(map1);
8079 		return map2;
8080 	}
8081 	if (map2->n == 0) {
8082 		isl_map_free(map2);
8083 		return map1;
8084 	}
8085 
8086 	is_universe = isl_map_plain_is_universe(map1);
8087 	if (is_universe < 0)
8088 		goto error;
8089 	if (is_universe) {
8090 		isl_map_free(map2);
8091 		return map1;
8092 	}
8093 
8094 	is_universe = isl_map_plain_is_universe(map2);
8095 	if (is_universe < 0)
8096 		goto error;
8097 	if (is_universe) {
8098 		isl_map_free(map1);
8099 		return map2;
8100 	}
8101 
8102 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
8103 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
8104 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8105 
8106 	map = isl_map_alloc_space(isl_space_copy(map1->dim),
8107 				map1->n + map2->n, flags);
8108 	if (!map)
8109 		goto error;
8110 	for (i = 0; i < map1->n; ++i) {
8111 		map = isl_map_add_basic_map(map,
8112 				  isl_basic_map_copy(map1->p[i]));
8113 		if (!map)
8114 			goto error;
8115 	}
8116 	for (i = 0; i < map2->n; ++i) {
8117 		map = isl_map_add_basic_map(map,
8118 				  isl_basic_map_copy(map2->p[i]));
8119 		if (!map)
8120 			goto error;
8121 	}
8122 	isl_map_free(map1);
8123 	isl_map_free(map2);
8124 	return map;
8125 error:
8126 	isl_map_free(map);
8127 	isl_map_free(map1);
8128 	isl_map_free(map2);
8129 	return NULL;
8130 }
8131 
8132 /* Return the union of "map1" and "map2", where "map1" and "map2" are
8133  * guaranteed to be disjoint by the caller.
8134  *
8135  * Note that this functions is called from within isl_map_make_disjoint,
8136  * so we have to be careful not to touch the constraints of the inputs
8137  * in any way.
8138  */
isl_map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8139 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
8140 	__isl_take isl_map *map2)
8141 {
8142 	isl_map_align_params_bin(&map1, &map2);
8143 	return map_union_disjoint(map1, map2);
8144 }
8145 
8146 /* Return the union of "map1" and "map2", where "map1" and "map2" may
8147  * not be disjoint.
8148  *
8149  * We currently simply call map_union_disjoint, the internal operation
8150  * of which does not really depend on the inputs being disjoint.
8151  * If the result contains more than one basic map, then we clear
8152  * the disjoint flag since the result may contain basic maps from
8153  * both inputs and these are not guaranteed to be disjoint.
8154  *
8155  * As a special case, if "map1" and "map2" are obviously equal,
8156  * then we simply return "map1".
8157  */
isl_map_union(__isl_take isl_map * map1,__isl_take isl_map * map2)8158 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
8159 	__isl_take isl_map *map2)
8160 {
8161 	int equal;
8162 
8163 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8164 		goto error;
8165 
8166 	equal = isl_map_plain_is_equal(map1, map2);
8167 	if (equal < 0)
8168 		goto error;
8169 	if (equal) {
8170 		isl_map_free(map2);
8171 		return map1;
8172 	}
8173 
8174 	map1 = map_union_disjoint(map1, map2);
8175 	if (!map1)
8176 		return NULL;
8177 	if (map1->n > 1)
8178 		ISL_F_CLR(map1, ISL_MAP_DISJOINT);
8179 	return map1;
8180 error:
8181 	isl_map_free(map1);
8182 	isl_map_free(map2);
8183 	return NULL;
8184 }
8185 
isl_set_union_disjoint(__isl_take isl_set * set1,__isl_take isl_set * set2)8186 __isl_give isl_set *isl_set_union_disjoint(
8187 	__isl_take isl_set *set1, __isl_take isl_set *set2)
8188 {
8189 	return set_from_map(isl_map_union_disjoint(set_to_map(set1),
8190 						    set_to_map(set2)));
8191 }
8192 
isl_set_union(__isl_take isl_set * set1,__isl_take isl_set * set2)8193 __isl_give isl_set *isl_set_union(__isl_take isl_set *set1,
8194 	__isl_take isl_set *set2)
8195 {
8196 	return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
8197 }
8198 
8199 /* Apply "fn" to pairs of elements from "map" and "set" and collect
8200  * the results in a map living in "space".
8201  *
8202  * "map" and "set" are assumed to be compatible and non-NULL.
8203  */
map_intersect_set(__isl_take isl_map * map,__isl_take isl_space * space,__isl_take isl_set * set,__isl_give isl_basic_map * fn (__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset))8204 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
8205 	__isl_take isl_space *space, __isl_take isl_set *set,
8206 	__isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
8207 		__isl_take isl_basic_set *bset))
8208 {
8209 	unsigned flags = 0;
8210 	struct isl_map *result;
8211 	int i, j;
8212 
8213 	if (isl_set_plain_is_universe(set)) {
8214 		isl_set_free(set);
8215 		return isl_map_reset_equal_dim_space(map, space);
8216 	}
8217 
8218 	if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
8219 	    ISL_F_ISSET(set, ISL_MAP_DISJOINT))
8220 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8221 
8222 	result = isl_map_alloc_space(space, map->n * set->n, flags);
8223 	for (i = 0; result && i < map->n; ++i)
8224 		for (j = 0; j < set->n; ++j) {
8225 			result = isl_map_add_basic_map(result,
8226 					fn(isl_basic_map_copy(map->p[i]),
8227 					    isl_basic_set_copy(set->p[j])));
8228 			if (!result)
8229 				break;
8230 		}
8231 
8232 	isl_map_free(map);
8233 	isl_set_free(set);
8234 	return result;
8235 }
8236 
isl_map_intersect_range(__isl_take isl_map * map,__isl_take isl_set * set)8237 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
8238 	__isl_take isl_set *set)
8239 {
8240 	isl_bool ok;
8241 	isl_space *space;
8242 
8243 	isl_map_align_params_set(&map, &set);
8244 	ok = isl_map_compatible_range(map, set);
8245 	if (ok < 0)
8246 		goto error;
8247 	if (!ok)
8248 		isl_die(set->ctx, isl_error_invalid,
8249 			"incompatible spaces", goto error);
8250 
8251 	space = isl_map_get_space(map);
8252 	return map_intersect_set(map, space, set,
8253 				&isl_basic_map_intersect_range);
8254 error:
8255 	isl_map_free(map);
8256 	isl_set_free(set);
8257 	return NULL;
8258 }
8259 
8260 /* Intersect the domain of "map" with "set".
8261  *
8262  * If the domain dimensions of "map" do not have any identifiers,
8263  * then copy them over from "set".
8264  */
isl_map_intersect_domain(__isl_take isl_map * map,__isl_take isl_set * set)8265 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
8266 	__isl_take isl_set *set)
8267 {
8268 	isl_bool ok;
8269 	isl_space *space;
8270 
8271 	isl_map_align_params_set(&map, &set);
8272 	ok = isl_map_compatible_domain(map, set);
8273 	if (ok < 0)
8274 		goto error;
8275 	if (!ok)
8276 		isl_die(set->ctx, isl_error_invalid,
8277 			"incompatible spaces", goto error);
8278 
8279 	space = isl_map_get_space(map);
8280 	space = isl_space_copy_ids_if_unset(space, isl_dim_in,
8281 					isl_set_peek_space(set), isl_dim_set);
8282 	return map_intersect_set(map, space, set,
8283 				&isl_basic_map_intersect_domain);
8284 error:
8285 	isl_map_free(map);
8286 	isl_set_free(set);
8287 	return NULL;
8288 }
8289 
8290 /* Data structure that specifies how isl_map_intersect_factor
8291  * should operate.
8292  *
8293  * "preserve_type" is the tuple where the factor differs from
8294  * the input map and of which the identifiers needs
8295  * to be preserved explicitly.
8296  * "other_factor" is used to extract the space of the other factor
8297  * from the space of the product ("map").
8298  * "product" is used to combine the given factor and a universe map
8299  * in the space returned by "other_factor" to produce a map
8300  * that lives in the same space as the input map.
8301  */
8302 struct isl_intersect_factor_control {
8303 	enum isl_dim_type preserve_type;
8304 	__isl_give isl_space *(*other_factor)(__isl_take isl_space *space);
8305 	__isl_give isl_map *(*product)(__isl_take isl_map *factor,
8306 		__isl_take isl_map *other);
8307 };
8308 
8309 /* Given a map "map" in some product space and a map "factor"
8310  * living in some factor space, return the intersection.
8311  *
8312  * After aligning the parameters,
8313  * the map "factor" is first extended to a map living in the same space
8314  * as "map" and then a regular intersection is computed.
8315  *
8316  * Note that the extension is computed as a product, which is anonymous
8317  * by default.  If "map" has an identifier on the corresponding tuple,
8318  * then this identifier needs to be set on the product
8319  * before the intersection is computed.
8320  */
isl_map_intersect_factor(__isl_take isl_map * map,__isl_take isl_map * factor,struct isl_intersect_factor_control * control)8321 static __isl_give isl_map *isl_map_intersect_factor(
8322 	__isl_take isl_map *map, __isl_take isl_map *factor,
8323 	struct isl_intersect_factor_control *control)
8324 {
8325 	isl_bool equal, has_id;
8326 	isl_id *id;
8327 	isl_space *space;
8328 	isl_map *other, *product;
8329 
8330 	equal = isl_map_has_equal_params(map, factor);
8331 	if (equal < 0)
8332 		goto error;
8333 	if (!equal) {
8334 		map = isl_map_align_params(map, isl_map_get_space(factor));
8335 		factor = isl_map_align_params(factor, isl_map_get_space(map));
8336 	}
8337 
8338 	space = isl_map_get_space(map);
8339 	has_id = isl_space_has_tuple_id(space, control->preserve_type);
8340 	if (has_id < 0)
8341 		space = isl_space_free(space);
8342 	else if (has_id)
8343 		id = isl_space_get_tuple_id(space, control->preserve_type);
8344 
8345 	other = isl_map_universe(control->other_factor(space));
8346 	product = control->product(factor, other);
8347 
8348 	if (has_id >= 0 && has_id)
8349 		product = isl_map_set_tuple_id(product,
8350 						control->preserve_type, id);
8351 
8352 	return map_intersect(map, product);
8353 error:
8354 	isl_map_free(map);
8355 	isl_map_free(factor);
8356 	return NULL;
8357 }
8358 
8359 /* Return the domain product of "map2" and "map1".
8360  */
isl_map_reverse_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8361 static __isl_give isl_map *isl_map_reverse_domain_product(
8362 	__isl_take isl_map *map1, __isl_take isl_map *map2)
8363 {
8364 	return isl_map_domain_product(map2, map1);
8365 }
8366 
8367 /* Return the range product of "map2" and "map1".
8368  */
isl_map_reverse_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8369 static __isl_give isl_map *isl_map_reverse_range_product(
8370 	__isl_take isl_map *map1, __isl_take isl_map *map2)
8371 {
8372 	return isl_map_range_product(map2, map1);
8373 }
8374 
8375 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8376  * in the space B -> C, return the intersection.
8377  */
isl_map_intersect_domain_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8378 __isl_give isl_map *isl_map_intersect_domain_factor_range(
8379 	__isl_take isl_map *map, __isl_take isl_map *factor)
8380 {
8381 	struct isl_intersect_factor_control control = {
8382 		.preserve_type = isl_dim_in,
8383 		.other_factor = isl_space_domain_factor_domain,
8384 		.product = isl_map_reverse_domain_product,
8385 	};
8386 
8387 	return isl_map_intersect_factor(map, factor, &control);
8388 }
8389 
8390 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8391  * in the space A -> B, return the intersection.
8392  */
isl_map_intersect_range_factor_domain(__isl_take isl_map * map,__isl_take isl_map * factor)8393 __isl_give isl_map *isl_map_intersect_range_factor_domain(
8394 	__isl_take isl_map *map, __isl_take isl_map *factor)
8395 {
8396 	struct isl_intersect_factor_control control = {
8397 		.preserve_type = isl_dim_out,
8398 		.other_factor = isl_space_range_factor_range,
8399 		.product = isl_map_range_product,
8400 	};
8401 
8402 	return isl_map_intersect_factor(map, factor, &control);
8403 }
8404 
8405 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8406  * in the space A -> C, return the intersection.
8407  */
isl_map_intersect_range_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8408 __isl_give isl_map *isl_map_intersect_range_factor_range(
8409 	__isl_take isl_map *map, __isl_take isl_map *factor)
8410 {
8411 	struct isl_intersect_factor_control control = {
8412 		.preserve_type = isl_dim_out,
8413 		.other_factor = isl_space_range_factor_domain,
8414 		.product = isl_map_reverse_range_product,
8415 	};
8416 
8417 	return isl_map_intersect_factor(map, factor, &control);
8418 }
8419 
8420 /* Given a set "set" in a space [A -> B] and a set "domain"
8421  * in the space A, return the intersection.
8422  *
8423  * The set "domain" is first extended to a set living in the space
8424  * [A -> B] and then a regular intersection is computed.
8425  */
isl_set_intersect_factor_domain(__isl_take isl_set * set,__isl_take isl_set * domain)8426 __isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
8427 	__isl_take isl_set *domain)
8428 {
8429 	struct isl_intersect_factor_control control = {
8430 		.preserve_type = isl_dim_set,
8431 		.other_factor = isl_space_factor_range,
8432 		.product = isl_map_range_product,
8433 	};
8434 
8435 	return set_from_map(isl_map_intersect_factor(set_to_map(set),
8436 						set_to_map(domain), &control));
8437 }
8438 
8439 /* Given a set "set" in a space [A -> B] and a set "range"
8440  * in the space B, return the intersection.
8441  *
8442  * The set "range" is first extended to a set living in the space
8443  * [A -> B] and then a regular intersection is computed.
8444  */
isl_set_intersect_factor_range(__isl_take isl_set * set,__isl_take isl_set * range)8445 __isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
8446 	__isl_take isl_set *range)
8447 {
8448 	struct isl_intersect_factor_control control = {
8449 		.preserve_type = isl_dim_set,
8450 		.other_factor = isl_space_factor_domain,
8451 		.product = isl_map_reverse_range_product,
8452 	};
8453 
8454 	return set_from_map(isl_map_intersect_factor(set_to_map(set),
8455 						set_to_map(range), &control));
8456 }
8457 
isl_map_apply_domain(__isl_take isl_map * map1,__isl_take isl_map * map2)8458 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8459 	__isl_take isl_map *map2)
8460 {
8461 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8462 		goto error;
8463 	map1 = isl_map_reverse(map1);
8464 	map1 = isl_map_apply_range(map1, map2);
8465 	return isl_map_reverse(map1);
8466 error:
8467 	isl_map_free(map1);
8468 	isl_map_free(map2);
8469 	return NULL;
8470 }
8471 
isl_map_apply_range(__isl_take isl_map * map1,__isl_take isl_map * map2)8472 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8473 	__isl_take isl_map *map2)
8474 {
8475 	isl_space *space;
8476 	struct isl_map *result;
8477 	int i, j;
8478 
8479 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8480 		goto error;
8481 
8482 	space = isl_space_join(isl_space_copy(map1->dim),
8483 				  isl_space_copy(map2->dim));
8484 
8485 	result = isl_map_alloc_space(space, map1->n * map2->n, 0);
8486 	if (!result)
8487 		goto error;
8488 	for (i = 0; i < map1->n; ++i)
8489 		for (j = 0; j < map2->n; ++j) {
8490 			result = isl_map_add_basic_map(result,
8491 			    isl_basic_map_apply_range(
8492 				isl_basic_map_copy(map1->p[i]),
8493 				isl_basic_map_copy(map2->p[j])));
8494 			if (!result)
8495 				goto error;
8496 		}
8497 	isl_map_free(map1);
8498 	isl_map_free(map2);
8499 	if (result && result->n <= 1)
8500 		ISL_F_SET(result, ISL_MAP_DISJOINT);
8501 	return result;
8502 error:
8503 	isl_map_free(map1);
8504 	isl_map_free(map2);
8505 	return NULL;
8506 }
8507 
8508 /* Is "bmap" a transformation, i.e.,
8509  * does it relate elements from the same space.
8510  */
isl_basic_map_is_transformation(__isl_keep isl_basic_map * bmap)8511 isl_bool isl_basic_map_is_transformation(__isl_keep isl_basic_map *bmap)
8512 {
8513 	isl_space *space;
8514 
8515 	space = isl_basic_map_peek_space(bmap);
8516 	return isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8517 }
8518 
8519 /* Check that "bmap" is a transformation, i.e.,
8520  * that it relates elements from the same space.
8521  */
isl_basic_map_check_transformation(__isl_keep isl_basic_map * bmap)8522 static isl_stat isl_basic_map_check_transformation(
8523 	__isl_keep isl_basic_map *bmap)
8524 {
8525 	isl_bool equal;
8526 
8527 	equal = isl_basic_map_is_transformation(bmap);
8528 	if (equal < 0)
8529 		return isl_stat_error;
8530 	if (!equal)
8531 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
8532 			"domain and range don't match", return isl_stat_error);
8533 	return isl_stat_ok;
8534 }
8535 
8536 /*
8537  * returns range - domain
8538  */
isl_basic_map_deltas(__isl_take isl_basic_map * bmap)8539 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8540 {
8541 	isl_space *target_space;
8542 	struct isl_basic_set *bset;
8543 	isl_size dim;
8544 	isl_size nparam;
8545 	isl_size total;
8546 	int i;
8547 
8548 	if (isl_basic_map_check_transformation(bmap) < 0)
8549 		return isl_basic_map_free(bmap);
8550 	dim = isl_basic_map_dim(bmap, isl_dim_in);
8551 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
8552 	if (dim < 0 || nparam < 0)
8553 		goto error;
8554 	target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8555 	bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8556 	bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8557 	total = isl_basic_map_dim(bmap, isl_dim_all);
8558 	if (total < 0)
8559 		bmap = isl_basic_map_free(bmap);
8560 	bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8561 	for (i = 0; i < dim; ++i) {
8562 		int j = isl_basic_map_alloc_equality(bmap);
8563 		if (j < 0) {
8564 			bmap = isl_basic_map_free(bmap);
8565 			break;
8566 		}
8567 		isl_seq_clr(bmap->eq[j], 1 + total);
8568 		isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8569 		isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8570 		isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8571 	}
8572 	bset = isl_basic_map_domain(bmap);
8573 	bset = isl_basic_set_reset_space(bset, target_space);
8574 	return bset;
8575 error:
8576 	isl_basic_map_free(bmap);
8577 	return NULL;
8578 }
8579 
8580 /* Is the tuple of type "type1" of "map" the same as
8581  * the tuple of type "type2" of "space"?
8582  */
isl_map_space_tuple_is_equal(__isl_keep isl_map * map,enum isl_dim_type type1,__isl_keep isl_space * space,enum isl_dim_type type2)8583 isl_bool isl_map_space_tuple_is_equal(__isl_keep isl_map *map,
8584 	enum isl_dim_type type1, __isl_keep isl_space *space,
8585 	enum isl_dim_type type2)
8586 {
8587 	isl_space *map_space;
8588 
8589 	map_space = isl_map_peek_space(map);
8590 	return isl_space_tuple_is_equal(map_space, type1, space, type2);
8591 }
8592 
8593 /* Is the tuple of type "type1" of "map1" the same as
8594  * the tuple of type "type2" of "map2"?
8595  */
isl_map_tuple_is_equal(__isl_keep isl_map * map1,enum isl_dim_type type1,__isl_keep isl_map * map2,enum isl_dim_type type2)8596 isl_bool isl_map_tuple_is_equal(__isl_keep isl_map *map1,
8597 	enum isl_dim_type type1, __isl_keep isl_map *map2,
8598 	enum isl_dim_type type2)
8599 {
8600 	isl_space *space1, *space2;
8601 
8602 	space1 = isl_map_peek_space(map1);
8603 	space2 = isl_map_peek_space(map2);
8604 	return isl_space_tuple_is_equal(space1, type1, space2, type2);
8605 }
8606 
8607 /* Check that "map" is a transformation, i.e.,
8608  * that it relates elements from the same space.
8609  */
isl_map_check_transformation(__isl_keep isl_map * map)8610 isl_stat isl_map_check_transformation(__isl_keep isl_map *map)
8611 {
8612 	isl_bool equal;
8613 
8614 	equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
8615 	if (equal < 0)
8616 		return isl_stat_error;
8617 	if (!equal)
8618 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
8619 			"domain and range don't match", return isl_stat_error);
8620 	return isl_stat_ok;
8621 }
8622 
8623 /*
8624  * returns range - domain
8625  */
isl_map_deltas(__isl_take isl_map * map)8626 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8627 {
8628 	int i;
8629 	isl_space *space;
8630 	struct isl_set *result;
8631 
8632 	if (isl_map_check_transformation(map) < 0)
8633 		goto error;
8634 	space = isl_map_get_space(map);
8635 	space = isl_space_domain(space);
8636 	result = isl_set_alloc_space(space, map->n, 0);
8637 	if (!result)
8638 		goto error;
8639 	for (i = 0; i < map->n; ++i)
8640 		result = isl_set_add_basic_set(result,
8641 			  isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8642 	isl_map_free(map);
8643 	return result;
8644 error:
8645 	isl_map_free(map);
8646 	return NULL;
8647 }
8648 
8649 /*
8650  * returns [domain -> range] -> range - domain
8651  */
isl_basic_map_deltas_map(__isl_take isl_basic_map * bmap)8652 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8653 	__isl_take isl_basic_map *bmap)
8654 {
8655 	int i, k;
8656 	isl_space *space;
8657 	isl_basic_map *domain;
8658 	isl_size nparam, n;
8659 	isl_size total;
8660 
8661 	if (isl_basic_map_check_transformation(bmap) < 0)
8662 		return isl_basic_map_free(bmap);
8663 
8664 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
8665 	n = isl_basic_map_dim(bmap, isl_dim_in);
8666 	if (nparam < 0 || n < 0)
8667 		return isl_basic_map_free(bmap);
8668 
8669 	space = isl_basic_map_get_space(bmap);
8670 	space = isl_space_from_range(isl_space_domain(space));
8671 	domain = isl_basic_map_universe(space);
8672 
8673 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8674 	bmap = isl_basic_map_apply_range(bmap, domain);
8675 	bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8676 
8677 	total = isl_basic_map_dim(bmap, isl_dim_all);
8678 	if (total < 0)
8679 		return isl_basic_map_free(bmap);
8680 
8681 	for (i = 0; i < n; ++i) {
8682 		k = isl_basic_map_alloc_equality(bmap);
8683 		if (k < 0)
8684 			goto error;
8685 		isl_seq_clr(bmap->eq[k], 1 + total);
8686 		isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8687 		isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8688 		isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8689 	}
8690 
8691 	bmap = isl_basic_map_gauss(bmap, NULL);
8692 	return isl_basic_map_finalize(bmap);
8693 error:
8694 	isl_basic_map_free(bmap);
8695 	return NULL;
8696 }
8697 
8698 /*
8699  * returns [domain -> range] -> range - domain
8700  */
isl_map_deltas_map(__isl_take isl_map * map)8701 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8702 {
8703 	if (isl_map_check_transformation(map) < 0)
8704 		return isl_map_free(map);
8705 
8706 	return isl_map_transform(map, &isl_space_range_map,
8707 					&isl_basic_map_deltas_map);
8708 }
8709 
isl_basic_map_identity(__isl_take isl_space * space)8710 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8711 {
8712 	isl_size n_in, n_out;
8713 
8714 	n_in = isl_space_dim(space, isl_dim_in);
8715 	n_out = isl_space_dim(space, isl_dim_out);
8716 	if (n_in < 0 || n_out < 0)
8717 		goto error;
8718 	if (n_in != n_out)
8719 		isl_die(space->ctx, isl_error_invalid,
8720 			"number of input and output dimensions needs to be "
8721 			"the same", goto error);
8722 	return isl_basic_map_equal(space, n_in);
8723 error:
8724 	isl_space_free(space);
8725 	return NULL;
8726 }
8727 
isl_map_identity(__isl_take isl_space * space)8728 __isl_give isl_map *isl_map_identity(__isl_take isl_space *space)
8729 {
8730 	return isl_map_from_basic_map(isl_basic_map_identity(space));
8731 }
8732 
isl_set_identity(__isl_take isl_set * set)8733 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8734 {
8735 	isl_space *space = isl_set_get_space(set);
8736 	isl_map *id;
8737 	id = isl_map_identity(isl_space_map_from_set(space));
8738 	return isl_map_intersect_range(id, set);
8739 }
8740 
8741 /* Construct a basic set with all set dimensions having only non-negative
8742  * values.
8743  */
isl_basic_set_positive_orthant(__isl_take isl_space * space)8744 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8745 	__isl_take isl_space *space)
8746 {
8747 	int i;
8748 	isl_size nparam;
8749 	isl_size dim;
8750 	isl_size total;
8751 	struct isl_basic_set *bset;
8752 
8753 	nparam = isl_space_dim(space, isl_dim_param);
8754 	dim = isl_space_dim(space, isl_dim_set);
8755 	total = isl_space_dim(space, isl_dim_all);
8756 	if (nparam < 0 || dim < 0 || total < 0)
8757 		space = isl_space_free(space);
8758 	bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8759 	if (!bset)
8760 		return NULL;
8761 	for (i = 0; i < dim; ++i) {
8762 		int k = isl_basic_set_alloc_inequality(bset);
8763 		if (k < 0)
8764 			goto error;
8765 		isl_seq_clr(bset->ineq[k], 1 + total);
8766 		isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8767 	}
8768 	return bset;
8769 error:
8770 	isl_basic_set_free(bset);
8771 	return NULL;
8772 }
8773 
8774 /* Construct the half-space x_pos >= 0.
8775  */
nonneg_halfspace(__isl_take isl_space * space,int pos)8776 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8777 	int pos)
8778 {
8779 	int k;
8780 	isl_size total;
8781 	isl_basic_set *nonneg;
8782 
8783 	total = isl_space_dim(space, isl_dim_all);
8784 	if (total < 0)
8785 		space = isl_space_free(space);
8786 	nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8787 	k = isl_basic_set_alloc_inequality(nonneg);
8788 	if (k < 0)
8789 		goto error;
8790 	isl_seq_clr(nonneg->ineq[k], 1 + total);
8791 	isl_int_set_si(nonneg->ineq[k][pos], 1);
8792 
8793 	return isl_basic_set_finalize(nonneg);
8794 error:
8795 	isl_basic_set_free(nonneg);
8796 	return NULL;
8797 }
8798 
8799 /* Construct the half-space x_pos <= -1.
8800  */
neg_halfspace(__isl_take isl_space * space,int pos)8801 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8802 	int pos)
8803 {
8804 	int k;
8805 	isl_size total;
8806 	isl_basic_set *neg;
8807 
8808 	total = isl_space_dim(space, isl_dim_all);
8809 	if (total < 0)
8810 		space = isl_space_free(space);
8811 	neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8812 	k = isl_basic_set_alloc_inequality(neg);
8813 	if (k < 0)
8814 		goto error;
8815 	isl_seq_clr(neg->ineq[k], 1 + total);
8816 	isl_int_set_si(neg->ineq[k][0], -1);
8817 	isl_int_set_si(neg->ineq[k][pos], -1);
8818 
8819 	return isl_basic_set_finalize(neg);
8820 error:
8821 	isl_basic_set_free(neg);
8822 	return NULL;
8823 }
8824 
isl_set_split_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)8825 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8826 	enum isl_dim_type type, unsigned first, unsigned n)
8827 {
8828 	int i;
8829 	unsigned offset;
8830 	isl_basic_set *nonneg;
8831 	isl_basic_set *neg;
8832 
8833 	if (n == 0)
8834 		return set;
8835 
8836 	if (isl_set_check_range(set, type, first, n) < 0)
8837 		return isl_set_free(set);
8838 
8839 	offset = pos(set->dim, type);
8840 	for (i = 0; i < n; ++i) {
8841 		nonneg = nonneg_halfspace(isl_set_get_space(set),
8842 					  offset + first + i);
8843 		neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8844 
8845 		set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8846 	}
8847 
8848 	return set;
8849 }
8850 
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)8851 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8852 	int len,
8853 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8854 	void *user)
8855 {
8856 	isl_set *half;
8857 
8858 	if (!set)
8859 		return isl_stat_error;
8860 	if (isl_set_plain_is_empty(set)) {
8861 		isl_set_free(set);
8862 		return isl_stat_ok;
8863 	}
8864 	if (first == len)
8865 		return fn(set, signs, user);
8866 
8867 	signs[first] = 1;
8868 	half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8869 							1 + first));
8870 	half = isl_set_intersect(half, isl_set_copy(set));
8871 	if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8872 		goto error;
8873 
8874 	signs[first] = -1;
8875 	half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8876 							1 + first));
8877 	half = isl_set_intersect(half, set);
8878 	return foreach_orthant(half, signs, first + 1, len, fn, user);
8879 error:
8880 	isl_set_free(set);
8881 	return isl_stat_error;
8882 }
8883 
8884 /* Call "fn" on the intersections of "set" with each of the orthants
8885  * (except for obviously empty intersections).  The orthant is identified
8886  * by the signs array, with each entry having value 1 or -1 according
8887  * to the sign of the corresponding variable.
8888  */
isl_set_foreach_orthant(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_set * orthant,int * signs,void * user),void * user)8889 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8890 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8891 	void *user)
8892 {
8893 	isl_size nparam;
8894 	isl_size nvar;
8895 	int *signs;
8896 	isl_stat r;
8897 
8898 	if (!set)
8899 		return isl_stat_error;
8900 	if (isl_set_plain_is_empty(set))
8901 		return isl_stat_ok;
8902 
8903 	nparam = isl_set_dim(set, isl_dim_param);
8904 	nvar = isl_set_dim(set, isl_dim_set);
8905 	if (nparam < 0 || nvar < 0)
8906 		return isl_stat_error;
8907 
8908 	signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8909 
8910 	r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8911 			    fn, user);
8912 
8913 	free(signs);
8914 
8915 	return r;
8916 }
8917 
isl_set_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)8918 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8919 {
8920 	return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8921 }
8922 
isl_basic_map_is_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8923 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8924 	__isl_keep isl_basic_map *bmap2)
8925 {
8926 	isl_bool is_subset;
8927 	struct isl_map *map1;
8928 	struct isl_map *map2;
8929 
8930 	if (!bmap1 || !bmap2)
8931 		return isl_bool_error;
8932 
8933 	map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8934 	map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8935 
8936 	is_subset = isl_map_is_subset(map1, map2);
8937 
8938 	isl_map_free(map1);
8939 	isl_map_free(map2);
8940 
8941 	return is_subset;
8942 }
8943 
isl_basic_set_is_subset(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8944 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8945 	__isl_keep isl_basic_set *bset2)
8946 {
8947 	return isl_basic_map_is_subset(bset1, bset2);
8948 }
8949 
isl_basic_map_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8950 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8951 	__isl_keep isl_basic_map *bmap2)
8952 {
8953 	isl_bool is_subset;
8954 
8955 	if (!bmap1 || !bmap2)
8956 		return isl_bool_error;
8957 	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8958 	if (is_subset != isl_bool_true)
8959 		return is_subset;
8960 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8961 	return is_subset;
8962 }
8963 
isl_basic_set_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8964 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8965 	__isl_keep isl_basic_set *bset2)
8966 {
8967 	return isl_basic_map_is_equal(
8968 		bset_to_bmap(bset1), bset_to_bmap(bset2));
8969 }
8970 
isl_map_is_empty(__isl_keep isl_map * map)8971 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8972 {
8973 	int i;
8974 	int is_empty;
8975 
8976 	if (!map)
8977 		return isl_bool_error;
8978 	for (i = 0; i < map->n; ++i) {
8979 		is_empty = isl_basic_map_is_empty(map->p[i]);
8980 		if (is_empty < 0)
8981 			return isl_bool_error;
8982 		if (!is_empty)
8983 			return isl_bool_false;
8984 	}
8985 	return isl_bool_true;
8986 }
8987 
isl_map_plain_is_empty(__isl_keep isl_map * map)8988 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8989 {
8990 	return map ? map->n == 0 : isl_bool_error;
8991 }
8992 
isl_set_plain_is_empty(__isl_keep isl_set * set)8993 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8994 {
8995 	return set ? set->n == 0 : isl_bool_error;
8996 }
8997 
isl_set_is_empty(__isl_keep isl_set * set)8998 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8999 {
9000 	return isl_map_is_empty(set_to_map(set));
9001 }
9002 
9003 #undef TYPE
9004 #define TYPE	isl_basic_map
9005 
9006 static
9007 #include "isl_type_has_equal_space_bin_templ.c"
9008 #include "isl_type_check_equal_space_templ.c"
9009 
9010 /* Check that "bset1" and "bset2" live in the same space,
9011  * reporting an error if they do not.
9012  */
isl_basic_set_check_equal_space(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9013 isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
9014 	__isl_keep isl_basic_set *bset2)
9015 {
9016 	return isl_basic_map_check_equal_space(bset_to_bmap(bset1),
9017 						bset_to_bmap(bset1));
9018 }
9019 
9020 #undef TYPE
9021 #define TYPE	isl_map
9022 
9023 #include "isl_type_has_equal_space_bin_templ.c"
9024 #include "isl_type_check_equal_space_templ.c"
9025 
isl_set_has_equal_space(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9026 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
9027 	__isl_keep isl_set *set2)
9028 {
9029 	return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));
9030 }
9031 
9032 #undef TYPE1
9033 #define TYPE1		isl_map
9034 #undef TYPE2
9035 #define TYPE2		isl_basic_map
9036 #undef TYPE_PAIR
9037 #define TYPE_PAIR	isl_map_basic_map
9038 
9039 static
9040 #include "isl_type_has_equal_space_templ.c"
9041 #include "isl_type_check_equal_space_templ.c"
9042 
9043 /* Check that "set" and "bset" live in the same space,
9044  * reporting an error if they do not.
9045  */
isl_set_basic_set_check_equal_space(__isl_keep isl_set * set,__isl_keep isl_basic_set * bset)9046 isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
9047 	__isl_keep isl_basic_set *bset)
9048 {
9049 	return isl_map_basic_map_check_equal_space(set_to_map(set),
9050 						    bset_to_bmap(bset));
9051 }
9052 
map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9053 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9054 {
9055 	isl_bool is_subset;
9056 
9057 	if (!map1 || !map2)
9058 		return isl_bool_error;
9059 	is_subset = isl_map_is_subset(map1, map2);
9060 	if (is_subset != isl_bool_true)
9061 		return is_subset;
9062 	is_subset = isl_map_is_subset(map2, map1);
9063 	return is_subset;
9064 }
9065 
9066 /* Is "map1" equal to "map2"?
9067  *
9068  * First check if they are obviously equal.
9069  * If not, then perform a more detailed analysis.
9070  */
isl_map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9071 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9072 {
9073 	isl_bool equal;
9074 
9075 	equal = isl_map_plain_is_equal(map1, map2);
9076 	if (equal < 0 || equal)
9077 		return equal;
9078 	return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
9079 }
9080 
isl_basic_map_is_strict_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9081 isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
9082 	__isl_keep isl_basic_map *bmap2)
9083 {
9084 	isl_bool is_subset;
9085 
9086 	if (!bmap1 || !bmap2)
9087 		return isl_bool_error;
9088 	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9089 	if (is_subset != isl_bool_true)
9090 		return is_subset;
9091 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9092 	return isl_bool_not(is_subset);
9093 }
9094 
isl_map_is_strict_subset(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9095 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
9096 	__isl_keep isl_map *map2)
9097 {
9098 	isl_bool is_subset;
9099 
9100 	if (!map1 || !map2)
9101 		return isl_bool_error;
9102 	is_subset = isl_map_is_subset(map1, map2);
9103 	if (is_subset != isl_bool_true)
9104 		return is_subset;
9105 	is_subset = isl_map_is_subset(map2, map1);
9106 	return isl_bool_not(is_subset);
9107 }
9108 
isl_set_is_strict_subset(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9109 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
9110 	__isl_keep isl_set *set2)
9111 {
9112 	return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
9113 }
9114 
9115 /* Is "bmap" obviously equal to the universe with the same space?
9116  *
9117  * That is, does it not have any constraints?
9118  */
isl_basic_map_plain_is_universe(__isl_keep isl_basic_map * bmap)9119 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
9120 {
9121 	if (!bmap)
9122 		return isl_bool_error;
9123 	return bmap->n_eq == 0 && bmap->n_ineq == 0;
9124 }
9125 
9126 /* Is "bset" obviously equal to the universe with the same space?
9127  */
isl_basic_set_plain_is_universe(__isl_keep isl_basic_set * bset)9128 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
9129 {
9130 	return isl_basic_map_plain_is_universe(bset);
9131 }
9132 
9133 /* If "c" does not involve any existentially quantified variables,
9134  * then set *univ to false and abort
9135  */
involves_divs(__isl_take isl_constraint * c,void * user)9136 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
9137 {
9138 	isl_bool *univ = user;
9139 	isl_size n;
9140 
9141 	n = isl_constraint_dim(c, isl_dim_div);
9142 	if (n < 0)
9143 		c = isl_constraint_free(c);
9144 	*univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
9145 	isl_constraint_free(c);
9146 	if (*univ < 0 || !*univ)
9147 		return isl_stat_error;
9148 	return isl_stat_ok;
9149 }
9150 
9151 /* Is "bmap" equal to the universe with the same space?
9152  *
9153  * First check if it is obviously equal to the universe.
9154  * If not and if there are any constraints not involving
9155  * existentially quantified variables, then it is certainly
9156  * not equal to the universe.
9157  * Otherwise, check if the universe is a subset of "bmap".
9158  */
isl_basic_map_is_universe(__isl_keep isl_basic_map * bmap)9159 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
9160 {
9161 	isl_size n_div;
9162 	isl_bool univ;
9163 	isl_basic_map *test;
9164 
9165 	univ = isl_basic_map_plain_is_universe(bmap);
9166 	if (univ < 0 || univ)
9167 		return univ;
9168 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
9169 	if (n_div < 0)
9170 		return isl_bool_error;
9171 	if (n_div == 0)
9172 		return isl_bool_false;
9173 	univ = isl_bool_true;
9174 	if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
9175 	    univ)
9176 		return isl_bool_error;
9177 	if (univ < 0 || !univ)
9178 		return univ;
9179 	test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
9180 	univ = isl_basic_map_is_subset(test, bmap);
9181 	isl_basic_map_free(test);
9182 	return univ;
9183 }
9184 
9185 /* Is "bset" equal to the universe with the same space?
9186  */
isl_basic_set_is_universe(__isl_keep isl_basic_set * bset)9187 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
9188 {
9189 	return isl_basic_map_is_universe(bset);
9190 }
9191 
isl_map_plain_is_universe(__isl_keep isl_map * map)9192 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
9193 {
9194 	int i;
9195 
9196 	if (!map)
9197 		return isl_bool_error;
9198 
9199 	for (i = 0; i < map->n; ++i) {
9200 		isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
9201 		if (r < 0 || r)
9202 			return r;
9203 	}
9204 
9205 	return isl_bool_false;
9206 }
9207 
isl_set_plain_is_universe(__isl_keep isl_set * set)9208 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
9209 {
9210 	return isl_map_plain_is_universe(set_to_map(set));
9211 }
9212 
isl_basic_map_is_empty(__isl_keep isl_basic_map * bmap)9213 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
9214 {
9215 	struct isl_basic_set *bset = NULL;
9216 	struct isl_vec *sample = NULL;
9217 	isl_bool empty, non_empty;
9218 
9219 	if (!bmap)
9220 		return isl_bool_error;
9221 
9222 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
9223 		return isl_bool_true;
9224 
9225 	if (isl_basic_map_plain_is_universe(bmap))
9226 		return isl_bool_false;
9227 
9228 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
9229 		struct isl_basic_map *copy = isl_basic_map_copy(bmap);
9230 		copy = isl_basic_map_remove_redundancies(copy);
9231 		empty = isl_basic_map_plain_is_empty(copy);
9232 		isl_basic_map_free(copy);
9233 		return empty;
9234 	}
9235 
9236 	non_empty = isl_basic_map_plain_is_non_empty(bmap);
9237 	if (non_empty < 0)
9238 		return isl_bool_error;
9239 	if (non_empty)
9240 		return isl_bool_false;
9241 	isl_vec_free(bmap->sample);
9242 	bmap->sample = NULL;
9243 	bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
9244 	if (!bset)
9245 		return isl_bool_error;
9246 	sample = isl_basic_set_sample_vec(bset);
9247 	if (!sample)
9248 		return isl_bool_error;
9249 	empty = sample->size == 0;
9250 	isl_vec_free(bmap->sample);
9251 	bmap->sample = sample;
9252 	if (empty)
9253 		ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
9254 
9255 	return empty;
9256 }
9257 
isl_basic_map_plain_is_empty(__isl_keep isl_basic_map * bmap)9258 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
9259 {
9260 	if (!bmap)
9261 		return isl_bool_error;
9262 	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
9263 }
9264 
isl_basic_set_plain_is_empty(__isl_keep isl_basic_set * bset)9265 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
9266 {
9267 	if (!bset)
9268 		return isl_bool_error;
9269 	return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
9270 }
9271 
9272 /* Is "bmap" known to be non-empty?
9273  *
9274  * That is, is the cached sample still valid?
9275  */
isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map * bmap)9276 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
9277 {
9278 	isl_size total;
9279 
9280 	if (!bmap)
9281 		return isl_bool_error;
9282 	if (!bmap->sample)
9283 		return isl_bool_false;
9284 	total = isl_basic_map_dim(bmap, isl_dim_all);
9285 	if (total < 0)
9286 		return isl_bool_error;
9287 	if (bmap->sample->size != 1 + total)
9288 		return isl_bool_false;
9289 	return isl_basic_map_contains(bmap, bmap->sample);
9290 }
9291 
isl_basic_set_is_empty(__isl_keep isl_basic_set * bset)9292 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
9293 {
9294 	return isl_basic_map_is_empty(bset_to_bmap(bset));
9295 }
9296 
isl_basic_map_union(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)9297 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
9298 	__isl_take isl_basic_map *bmap2)
9299 {
9300 	struct isl_map *map;
9301 
9302 	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
9303 		goto error;
9304 
9305 	map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
9306 	if (!map)
9307 		goto error;
9308 	map = isl_map_add_basic_map(map, bmap1);
9309 	map = isl_map_add_basic_map(map, bmap2);
9310 	return map;
9311 error:
9312 	isl_basic_map_free(bmap1);
9313 	isl_basic_map_free(bmap2);
9314 	return NULL;
9315 }
9316 
isl_basic_set_union(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)9317 __isl_give isl_set *isl_basic_set_union(__isl_take isl_basic_set *bset1,
9318 	__isl_take isl_basic_set *bset2)
9319 {
9320 	return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
9321 						bset_to_bmap(bset2)));
9322 }
9323 
9324 /* Order divs such that any div only depends on previous divs */
isl_basic_map_order_divs(__isl_take isl_basic_map * bmap)9325 __isl_give isl_basic_map *isl_basic_map_order_divs(
9326 	__isl_take isl_basic_map *bmap)
9327 {
9328 	int i;
9329 	isl_size off;
9330 
9331 	off = isl_basic_map_var_offset(bmap, isl_dim_div);
9332 	if (off < 0)
9333 		return isl_basic_map_free(bmap);
9334 
9335 	for (i = 0; i < bmap->n_div; ++i) {
9336 		int pos;
9337 		if (isl_int_is_zero(bmap->div[i][0]))
9338 			continue;
9339 		pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
9340 							    bmap->n_div-i);
9341 		if (pos == -1)
9342 			continue;
9343 		if (pos == 0)
9344 			isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
9345 				"integer division depends on itself",
9346 				return isl_basic_map_free(bmap));
9347 		bmap = isl_basic_map_swap_div(bmap, i, i + pos);
9348 		if (!bmap)
9349 			return NULL;
9350 		--i;
9351 	}
9352 	return bmap;
9353 }
9354 
isl_map_order_divs(__isl_take isl_map * map)9355 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
9356 {
9357 	int i;
9358 
9359 	if (!map)
9360 		return 0;
9361 
9362 	for (i = 0; i < map->n; ++i) {
9363 		map->p[i] = isl_basic_map_order_divs(map->p[i]);
9364 		if (!map->p[i])
9365 			goto error;
9366 	}
9367 
9368 	return map;
9369 error:
9370 	isl_map_free(map);
9371 	return NULL;
9372 }
9373 
9374 /* Sort the local variables of "bset".
9375  */
isl_basic_set_sort_divs(__isl_take isl_basic_set * bset)9376 __isl_give isl_basic_set *isl_basic_set_sort_divs(
9377 	__isl_take isl_basic_set *bset)
9378 {
9379 	return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
9380 }
9381 
9382 /* Apply the expansion computed by isl_merge_divs.
9383  * The expansion itself is given by "exp" while the resulting
9384  * list of divs is given by "div".
9385  *
9386  * Move the integer divisions of "bmap" into the right position
9387  * according to "exp" and then introduce the additional integer
9388  * divisions, adding div constraints.
9389  * The moving should be done first to avoid moving coefficients
9390  * in the definitions of the extra integer divisions.
9391  */
isl_basic_map_expand_divs(__isl_take isl_basic_map * bmap,__isl_take isl_mat * div,int * exp)9392 __isl_give isl_basic_map *isl_basic_map_expand_divs(
9393 	__isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
9394 {
9395 	int i, j;
9396 	int n_div;
9397 
9398 	bmap = isl_basic_map_cow(bmap);
9399 	if (!bmap || !div)
9400 		goto error;
9401 
9402 	if (div->n_row < bmap->n_div)
9403 		isl_die(isl_mat_get_ctx(div), isl_error_invalid,
9404 			"not an expansion", goto error);
9405 
9406 	n_div = bmap->n_div;
9407 	bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,
9408 					    2 * (div->n_row - n_div));
9409 
9410 	for (i = n_div; i < div->n_row; ++i)
9411 		if (isl_basic_map_alloc_div(bmap) < 0)
9412 			goto error;
9413 
9414 	for (j = n_div - 1; j >= 0; --j) {
9415 		if (exp[j] == j)
9416 			break;
9417 		bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
9418 		if (!bmap)
9419 			goto error;
9420 	}
9421 	j = 0;
9422 	for (i = 0; i < div->n_row; ++i) {
9423 		if (j < n_div && exp[j] == i) {
9424 			j++;
9425 		} else {
9426 			isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
9427 			if (isl_basic_map_div_is_marked_unknown(bmap, i))
9428 				continue;
9429 			bmap = isl_basic_map_add_div_constraints(bmap, i);
9430 			if (!bmap)
9431 				goto error;
9432 		}
9433 	}
9434 
9435 	isl_mat_free(div);
9436 	return bmap;
9437 error:
9438 	isl_basic_map_free(bmap);
9439 	isl_mat_free(div);
9440 	return NULL;
9441 }
9442 
9443 /* Apply the expansion computed by isl_merge_divs.
9444  * The expansion itself is given by "exp" while the resulting
9445  * list of divs is given by "div".
9446  */
isl_basic_set_expand_divs(__isl_take isl_basic_set * bset,__isl_take isl_mat * div,int * exp)9447 __isl_give isl_basic_set *isl_basic_set_expand_divs(
9448 	__isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
9449 {
9450 	return isl_basic_map_expand_divs(bset, div, exp);
9451 }
9452 
9453 /* Look for a div in dst that corresponds to the div "div" in src.
9454  * The divs before "div" in src and dst are assumed to be the same.
9455  *
9456  * Return the position of the corresponding div in dst
9457  * if there is one.  Otherwise, return a position beyond the integer divisions.
9458  * Return -1 on error.
9459  */
find_div(__isl_keep isl_basic_map * dst,__isl_keep isl_basic_map * src,unsigned div)9460 static int find_div(__isl_keep isl_basic_map *dst,
9461 	__isl_keep isl_basic_map *src, unsigned div)
9462 {
9463 	int i;
9464 	isl_size n_div;
9465 	isl_size v_div;
9466 
9467 	v_div = isl_basic_map_var_offset(src, isl_dim_div);
9468 	n_div = isl_basic_map_dim(dst, isl_dim_div);
9469 	if (n_div < 0 || v_div < 0)
9470 		return -1;
9471 	isl_assert(dst->ctx, div <= n_div, return -1);
9472 	for (i = div; i < n_div; ++i)
9473 		if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
9474 		    isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
9475 						n_div - div) == -1)
9476 			return i;
9477 	return n_div;
9478 }
9479 
9480 /* Align the divs of "dst" to those of "src", adding divs from "src"
9481  * if needed.  That is, make sure that the first src->n_div divs
9482  * of the result are equal to those of src.
9483  *
9484  * The result is not finalized as by design it will have redundant
9485  * divs if any divs from "src" were copied.
9486  */
isl_basic_map_align_divs(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)9487 __isl_give isl_basic_map *isl_basic_map_align_divs(
9488 	__isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
9489 {
9490 	int i;
9491 	isl_bool known;
9492 	int extended;
9493 	isl_size v_div;
9494 	isl_size dst_n_div;
9495 
9496 	if (!dst || !src)
9497 		return isl_basic_map_free(dst);
9498 
9499 	if (src->n_div == 0)
9500 		return dst;
9501 
9502 	known = isl_basic_map_divs_known(src);
9503 	if (known < 0)
9504 		return isl_basic_map_free(dst);
9505 	if (!known)
9506 		isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9507 			"some src divs are unknown",
9508 			return isl_basic_map_free(dst));
9509 
9510 	v_div = isl_basic_map_var_offset(src, isl_dim_div);
9511 	if (v_div < 0)
9512 		return isl_basic_map_free(dst);
9513 
9514 	src = isl_basic_map_order_divs(isl_basic_map_copy(src));
9515 	if (!src)
9516 		return isl_basic_map_free(dst);
9517 
9518 	extended = 0;
9519 	dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
9520 	if (dst_n_div < 0)
9521 		dst = isl_basic_map_free(dst);
9522 	for (i = 0; i < src->n_div; ++i) {
9523 		int j = find_div(dst, src, i);
9524 		if (j < 0)
9525 			dst = isl_basic_map_free(dst);
9526 		if (j == dst_n_div) {
9527 			if (!extended) {
9528 				int extra = src->n_div - i;
9529 				dst = isl_basic_map_cow(dst);
9530 				if (!dst)
9531 					goto error;
9532 				dst = isl_basic_map_extend(dst,
9533 						extra, 0, 2 * extra);
9534 				extended = 1;
9535 			}
9536 			j = isl_basic_map_alloc_div(dst);
9537 			if (j < 0)
9538 				goto error;
9539 			isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
9540 			isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
9541 			dst_n_div++;
9542 			dst = isl_basic_map_add_div_constraints(dst, j);
9543 			if (!dst)
9544 				goto error;
9545 		}
9546 		if (j != i)
9547 			dst = isl_basic_map_swap_div(dst, i, j);
9548 		if (!dst)
9549 			goto error;
9550 	}
9551 	isl_basic_map_free(src);
9552 	return dst;
9553 error:
9554 	isl_basic_map_free(src);
9555 	isl_basic_map_free(dst);
9556 	return NULL;
9557 }
9558 
isl_map_align_divs_internal(__isl_take isl_map * map)9559 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9560 {
9561 	int i;
9562 
9563 	if (!map)
9564 		return NULL;
9565 	if (map->n == 0)
9566 		return map;
9567 	map = isl_map_compute_divs(map);
9568 	map = isl_map_cow(map);
9569 	if (!map)
9570 		return NULL;
9571 
9572 	for (i = 1; i < map->n; ++i)
9573 		map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9574 	for (i = 1; i < map->n; ++i) {
9575 		map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9576 		if (!map->p[i])
9577 			return isl_map_free(map);
9578 	}
9579 
9580 	map = isl_map_unmark_normalized(map);
9581 	return map;
9582 }
9583 
isl_map_align_divs(__isl_take isl_map * map)9584 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9585 {
9586 	return isl_map_align_divs_internal(map);
9587 }
9588 
isl_set_align_divs(__isl_take isl_set * set)9589 __isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set)
9590 {
9591 	return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9592 }
9593 
9594 /* Align the divs of the basic maps in "map" to those
9595  * of the basic maps in "list", as well as to the other basic maps in "map".
9596  * The elements in "list" are assumed to have known divs.
9597  */
isl_map_align_divs_to_basic_map_list(__isl_take isl_map * map,__isl_keep isl_basic_map_list * list)9598 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9599 	__isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9600 {
9601 	int i;
9602 	isl_size n;
9603 
9604 	n = isl_basic_map_list_n_basic_map(list);
9605 	map = isl_map_compute_divs(map);
9606 	map = isl_map_cow(map);
9607 	if (!map || n < 0)
9608 		return isl_map_free(map);
9609 	if (map->n == 0)
9610 		return map;
9611 
9612 	for (i = 0; i < n; ++i) {
9613 		isl_basic_map *bmap;
9614 
9615 		bmap = isl_basic_map_list_get_basic_map(list, i);
9616 		map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9617 		isl_basic_map_free(bmap);
9618 	}
9619 	if (!map->p[0])
9620 		return isl_map_free(map);
9621 
9622 	return isl_map_align_divs_internal(map);
9623 }
9624 
9625 /* Align the divs of each element of "list" to those of "bmap".
9626  * Both "bmap" and the elements of "list" are assumed to have known divs.
9627  */
isl_basic_map_list_align_divs_to_basic_map(__isl_take isl_basic_map_list * list,__isl_keep isl_basic_map * bmap)9628 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9629 	__isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9630 {
9631 	int i;
9632 	isl_size n;
9633 
9634 	n = isl_basic_map_list_n_basic_map(list);
9635 	if (n < 0 || !bmap)
9636 		return isl_basic_map_list_free(list);
9637 
9638 	for (i = 0; i < n; ++i) {
9639 		isl_basic_map *bmap_i;
9640 
9641 		bmap_i = isl_basic_map_list_get_basic_map(list, i);
9642 		bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9643 		list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9644 	}
9645 
9646 	return list;
9647 }
9648 
isl_set_apply(__isl_take isl_set * set,__isl_take isl_map * map)9649 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9650 	__isl_take isl_map *map)
9651 {
9652 	isl_bool ok;
9653 
9654 	isl_map_align_params_set(&map, &set);
9655 	ok = isl_map_compatible_domain(map, set);
9656 	if (ok < 0)
9657 		goto error;
9658 	if (!ok)
9659 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
9660 			"incompatible spaces", goto error);
9661 	map = isl_map_intersect_domain(map, set);
9662 	set = isl_map_range(map);
9663 	return set;
9664 error:
9665 	isl_set_free(set);
9666 	isl_map_free(map);
9667 	return NULL;
9668 }
9669 
9670 /* There is no need to cow as removing empty parts doesn't change
9671  * the meaning of the set.
9672  */
isl_map_remove_empty_parts(__isl_take isl_map * map)9673 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9674 {
9675 	int i;
9676 
9677 	if (!map)
9678 		return NULL;
9679 
9680 	for (i = map->n - 1; i >= 0; --i)
9681 		map = remove_if_empty(map, i);
9682 
9683 	return map;
9684 }
9685 
isl_set_remove_empty_parts(__isl_take isl_set * set)9686 __isl_give isl_set *isl_set_remove_empty_parts(__isl_take isl_set *set)
9687 {
9688 	return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9689 }
9690 
9691 /* Create a binary relation that maps the shared initial "pos" dimensions
9692  * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9693  */
join_initial(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9694 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9695 	__isl_keep isl_basic_set *bset2, int pos)
9696 {
9697 	isl_basic_map *bmap1;
9698 	isl_basic_map *bmap2;
9699 
9700 	bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9701 	bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9702 	bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9703 					isl_dim_out, 0, pos);
9704 	bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9705 					isl_dim_out, 0, pos);
9706 	return isl_basic_map_range_product(bmap1, bmap2);
9707 }
9708 
9709 /* Given two basic sets bset1 and bset2, compute the maximal difference
9710  * between the values of dimension pos in bset1 and those in bset2
9711  * for any common value of the parameters and dimensions preceding pos.
9712  */
basic_set_maximal_difference_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos,isl_int * opt)9713 static enum isl_lp_result basic_set_maximal_difference_at(
9714 	__isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9715 	int pos, isl_int *opt)
9716 {
9717 	isl_basic_map *bmap1;
9718 	struct isl_ctx *ctx;
9719 	struct isl_vec *obj;
9720 	isl_size total;
9721 	isl_size nparam;
9722 	isl_size dim1;
9723 	enum isl_lp_result res;
9724 
9725 	nparam = isl_basic_set_dim(bset1, isl_dim_param);
9726 	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9727 	if (nparam < 0 || dim1 < 0 || !bset2)
9728 		return isl_lp_error;
9729 
9730 	bmap1 = join_initial(bset1, bset2, pos);
9731 	total = isl_basic_map_dim(bmap1, isl_dim_all);
9732 	if (total < 0)
9733 		return isl_lp_error;
9734 
9735 	ctx = bmap1->ctx;
9736 	obj = isl_vec_alloc(ctx, 1 + total);
9737 	if (!obj)
9738 		goto error;
9739 	isl_seq_clr(obj->block.data, 1 + total);
9740 	isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9741 	isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9742 	res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9743 					opt, NULL, NULL);
9744 	isl_basic_map_free(bmap1);
9745 	isl_vec_free(obj);
9746 	return res;
9747 error:
9748 	isl_basic_map_free(bmap1);
9749 	return isl_lp_error;
9750 }
9751 
9752 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9753  * for any common value of the parameters and dimensions preceding pos
9754  * in both basic sets, the values of dimension pos in bset1 are
9755  * smaller or larger than those in bset2.
9756  *
9757  * Returns
9758  *	 1 if bset1 follows bset2
9759  *	-1 if bset1 precedes bset2
9760  *	 0 if bset1 and bset2 are incomparable
9761  *	-2 if some error occurred.
9762  */
isl_basic_set_compare_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9763 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9764 	__isl_keep isl_basic_set *bset2, int pos)
9765 {
9766 	isl_int opt;
9767 	enum isl_lp_result res;
9768 	int cmp;
9769 
9770 	isl_int_init(opt);
9771 
9772 	res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9773 
9774 	if (res == isl_lp_empty)
9775 		cmp = 0;
9776 	else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9777 		  res == isl_lp_unbounded)
9778 		cmp = 1;
9779 	else if (res == isl_lp_ok && isl_int_is_neg(opt))
9780 		cmp = -1;
9781 	else
9782 		cmp = -2;
9783 
9784 	isl_int_clear(opt);
9785 	return cmp;
9786 }
9787 
9788 /* Given two basic sets bset1 and bset2, check whether
9789  * for any common value of the parameters and dimensions preceding pos
9790  * there is a value of dimension pos in bset1 that is larger
9791  * than a value of the same dimension in bset2.
9792  *
9793  * Return
9794  *	 1 if there exists such a pair
9795  *	 0 if there is no such pair, but there is a pair of equal values
9796  *	-1 otherwise
9797  *	-2 if some error occurred.
9798  */
isl_basic_set_follows_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9799 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9800 	__isl_keep isl_basic_set *bset2, int pos)
9801 {
9802 	isl_bool empty;
9803 	isl_basic_map *bmap;
9804 	isl_size dim1;
9805 
9806 	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9807 	if (dim1 < 0)
9808 		return -2;
9809 	bmap = join_initial(bset1, bset2, pos);
9810 	bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9811 					    isl_dim_out, dim1 - pos);
9812 	empty = isl_basic_map_is_empty(bmap);
9813 	if (empty < 0)
9814 		goto error;
9815 	if (empty) {
9816 		isl_basic_map_free(bmap);
9817 		return -1;
9818 	}
9819 	bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9820 					    isl_dim_out, dim1 - pos);
9821 	empty = isl_basic_map_is_empty(bmap);
9822 	if (empty < 0)
9823 		goto error;
9824 	isl_basic_map_free(bmap);
9825 	if (empty)
9826 		return 0;
9827 	return 1;
9828 error:
9829 	isl_basic_map_free(bmap);
9830 	return -2;
9831 }
9832 
9833 /* Given two sets set1 and set2, check whether
9834  * for any common value of the parameters and dimensions preceding pos
9835  * there is a value of dimension pos in set1 that is larger
9836  * than a value of the same dimension in set2.
9837  *
9838  * Return
9839  *	 1 if there exists such a pair
9840  *	 0 if there is no such pair, but there is a pair of equal values
9841  *	-1 otherwise
9842  *	-2 if some error occurred.
9843  */
isl_set_follows_at(__isl_keep isl_set * set1,__isl_keep isl_set * set2,int pos)9844 int isl_set_follows_at(__isl_keep isl_set *set1,
9845 	__isl_keep isl_set *set2, int pos)
9846 {
9847 	int i, j;
9848 	int follows = -1;
9849 
9850 	if (!set1 || !set2)
9851 		return -2;
9852 
9853 	for (i = 0; i < set1->n; ++i)
9854 		for (j = 0; j < set2->n; ++j) {
9855 			int f;
9856 			f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9857 			if (f == 1 || f == -2)
9858 				return f;
9859 			if (f > follows)
9860 				follows = f;
9861 		}
9862 
9863 	return follows;
9864 }
9865 
isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * val)9866 static isl_bool isl_basic_map_plain_has_fixed_var(
9867 	__isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9868 {
9869 	int i;
9870 	int d;
9871 	isl_size total;
9872 
9873 	total = isl_basic_map_dim(bmap, isl_dim_all);
9874 	if (total < 0)
9875 		return isl_bool_error;
9876 	for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9877 		for (; d+1 > pos; --d)
9878 			if (!isl_int_is_zero(bmap->eq[i][1+d]))
9879 				break;
9880 		if (d != pos)
9881 			continue;
9882 		if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9883 			return isl_bool_false;
9884 		if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9885 			return isl_bool_false;
9886 		if (!isl_int_is_one(bmap->eq[i][1+d]))
9887 			return isl_bool_false;
9888 		if (val)
9889 			isl_int_neg(*val, bmap->eq[i][0]);
9890 		return isl_bool_true;
9891 	}
9892 	return isl_bool_false;
9893 }
9894 
isl_map_plain_has_fixed_var(__isl_keep isl_map * map,unsigned pos,isl_int * val)9895 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9896 	unsigned pos, isl_int *val)
9897 {
9898 	int i;
9899 	isl_int v;
9900 	isl_int tmp;
9901 	isl_bool fixed;
9902 
9903 	if (!map)
9904 		return isl_bool_error;
9905 	if (map->n == 0)
9906 		return isl_bool_false;
9907 	if (map->n == 1)
9908 		return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9909 	isl_int_init(v);
9910 	isl_int_init(tmp);
9911 	fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9912 	for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9913 		fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9914 		if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9915 			fixed = isl_bool_false;
9916 	}
9917 	if (val)
9918 		isl_int_set(*val, v);
9919 	isl_int_clear(tmp);
9920 	isl_int_clear(v);
9921 	return fixed;
9922 }
9923 
isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set * bset,unsigned pos,isl_int * val)9924 static isl_bool isl_basic_set_plain_has_fixed_var(
9925 	__isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9926 {
9927 	return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9928 						pos, val);
9929 }
9930 
isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int * val)9931 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9932 	enum isl_dim_type type, unsigned pos, isl_int *val)
9933 {
9934 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9935 		return isl_bool_error;
9936 	return isl_basic_map_plain_has_fixed_var(bmap,
9937 		isl_basic_map_offset(bmap, type) - 1 + pos, val);
9938 }
9939 
9940 /* If "bmap" obviously lies on a hyperplane where the given dimension
9941  * has a fixed value, then return that value.
9942  * Otherwise return NaN.
9943  */
isl_basic_map_plain_get_val_if_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)9944 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9945 	__isl_keep isl_basic_map *bmap,
9946 	enum isl_dim_type type, unsigned pos)
9947 {
9948 	isl_ctx *ctx;
9949 	isl_val *v;
9950 	isl_bool fixed;
9951 
9952 	if (!bmap)
9953 		return NULL;
9954 	ctx = isl_basic_map_get_ctx(bmap);
9955 	v = isl_val_alloc(ctx);
9956 	if (!v)
9957 		return NULL;
9958 	fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9959 	if (fixed < 0)
9960 		return isl_val_free(v);
9961 	if (fixed) {
9962 		isl_int_set_si(v->d, 1);
9963 		return v;
9964 	}
9965 	isl_val_free(v);
9966 	return isl_val_nan(ctx);
9967 }
9968 
isl_map_plain_is_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_int * val)9969 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9970 	enum isl_dim_type type, unsigned pos, isl_int *val)
9971 {
9972 	if (isl_map_check_range(map, type, pos, 1) < 0)
9973 		return isl_bool_error;
9974 	return isl_map_plain_has_fixed_var(map,
9975 		map_offset(map, type) - 1 + pos, val);
9976 }
9977 
9978 /* If "map" obviously lies on a hyperplane where the given dimension
9979  * has a fixed value, then return that value.
9980  * Otherwise return NaN.
9981  */
isl_map_plain_get_val_if_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)9982 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9983 	enum isl_dim_type type, unsigned pos)
9984 {
9985 	isl_ctx *ctx;
9986 	isl_val *v;
9987 	isl_bool fixed;
9988 
9989 	if (!map)
9990 		return NULL;
9991 	ctx = isl_map_get_ctx(map);
9992 	v = isl_val_alloc(ctx);
9993 	if (!v)
9994 		return NULL;
9995 	fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9996 	if (fixed < 0)
9997 		return isl_val_free(v);
9998 	if (fixed) {
9999 		isl_int_set_si(v->d, 1);
10000 		return v;
10001 	}
10002 	isl_val_free(v);
10003 	return isl_val_nan(ctx);
10004 }
10005 
10006 /* If "set" obviously lies on a hyperplane where the given dimension
10007  * has a fixed value, then return that value.
10008  * Otherwise return NaN.
10009  */
isl_set_plain_get_val_if_fixed(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10010 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
10011 	enum isl_dim_type type, unsigned pos)
10012 {
10013 	return isl_map_plain_get_val_if_fixed(set, type, pos);
10014 }
10015 
10016 /* Return a sequence of values in the same space as "set"
10017  * that are equal to the corresponding set dimensions of "set"
10018  * for those set dimensions that obviously lie on a hyperplane
10019  * where the dimension has a fixed value.
10020  * The other elements are set to NaN.
10021  */
isl_set_get_plain_multi_val_if_fixed(__isl_keep isl_set * set)10022 __isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
10023 	__isl_keep isl_set *set)
10024 {
10025 	int i;
10026 	isl_size n;
10027 	isl_space *space;
10028 	isl_multi_val *mv;
10029 
10030 	space = isl_space_drop_all_params(isl_set_get_space(set));
10031 	mv = isl_multi_val_alloc(space);
10032 	n = isl_multi_val_size(mv);
10033 	if (n < 0)
10034 		return isl_multi_val_free(mv);
10035 
10036 	for (i = 0; i < n; ++i) {
10037 		isl_val *v;
10038 
10039 		v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);
10040 		mv = isl_multi_val_set_val(mv, i, v);
10041 	}
10042 
10043 	return mv;
10044 }
10045 
10046 /* Check if dimension dim has fixed value and if so and if val is not NULL,
10047  * then return this fixed value in *val.
10048  */
isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set * bset,unsigned dim,isl_int * val)10049 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
10050 	unsigned dim, isl_int *val)
10051 {
10052 	isl_size nparam;
10053 
10054 	nparam = isl_basic_set_dim(bset, isl_dim_param);
10055 	if (nparam < 0)
10056 		return isl_bool_error;
10057 	return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
10058 }
10059 
10060 /* Return -1 if the constraint "c1" should be sorted before "c2"
10061  * and 1 if it should be sorted after "c2".
10062  * Return 0 if the two constraints are the same (up to the constant term).
10063  *
10064  * In particular, if a constraint involves later variables than another
10065  * then it is sorted after this other constraint.
10066  * uset_gist depends on constraints without existentially quantified
10067  * variables sorting first.
10068  *
10069  * For constraints that have the same latest variable, those
10070  * with the same coefficient for this latest variable (first in absolute value
10071  * and then in actual value) are grouped together.
10072  * This is useful for detecting pairs of constraints that can
10073  * be chained in their printed representation.
10074  *
10075  * Finally, within a group, constraints are sorted according to
10076  * their coefficients (excluding the constant term).
10077  */
sort_constraint_cmp(const void * p1,const void * p2,void * arg)10078 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
10079 {
10080 	isl_int **c1 = (isl_int **) p1;
10081 	isl_int **c2 = (isl_int **) p2;
10082 	int l1, l2;
10083 	unsigned size = *(unsigned *) arg;
10084 	int cmp;
10085 
10086 	l1 = isl_seq_last_non_zero(*c1 + 1, size);
10087 	l2 = isl_seq_last_non_zero(*c2 + 1, size);
10088 
10089 	if (l1 != l2)
10090 		return l1 - l2;
10091 
10092 	cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10093 	if (cmp != 0)
10094 		return cmp;
10095 	cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10096 	if (cmp != 0)
10097 		return -cmp;
10098 
10099 	return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
10100 }
10101 
10102 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
10103  * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
10104  * and 0 if the two constraints are the same (up to the constant term).
10105  */
isl_basic_map_constraint_cmp(__isl_keep isl_basic_map * bmap,isl_int * c1,isl_int * c2)10106 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
10107 	isl_int *c1, isl_int *c2)
10108 {
10109 	isl_size total;
10110 	unsigned size;
10111 
10112 	total = isl_basic_map_dim(bmap, isl_dim_all);
10113 	if (total < 0)
10114 		return -2;
10115 	size = total;
10116 	return sort_constraint_cmp(&c1, &c2, &size);
10117 }
10118 
isl_basic_map_sort_constraints(__isl_take isl_basic_map * bmap)10119 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
10120 	__isl_take isl_basic_map *bmap)
10121 {
10122 	isl_size total;
10123 	unsigned size;
10124 
10125 	if (!bmap)
10126 		return NULL;
10127 	if (bmap->n_ineq == 0)
10128 		return bmap;
10129 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
10130 		return bmap;
10131 	total = isl_basic_map_dim(bmap, isl_dim_all);
10132 	if (total < 0)
10133 		return isl_basic_map_free(bmap);
10134 	size = total;
10135 	if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
10136 		    &sort_constraint_cmp, &size) < 0)
10137 		return isl_basic_map_free(bmap);
10138 	ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
10139 	return bmap;
10140 }
10141 
isl_basic_set_sort_constraints(__isl_take isl_basic_set * bset)10142 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
10143 	__isl_take isl_basic_set *bset)
10144 {
10145 	isl_basic_map *bmap = bset_to_bmap(bset);
10146 	return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
10147 }
10148 
isl_basic_map_normalize(__isl_take isl_basic_map * bmap)10149 __isl_give isl_basic_map *isl_basic_map_normalize(
10150 	__isl_take isl_basic_map *bmap)
10151 {
10152 	bmap = isl_basic_map_remove_redundancies(bmap);
10153 	bmap = isl_basic_map_sort_constraints(bmap);
10154 	return bmap;
10155 }
isl_basic_map_plain_cmp(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10156 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
10157 	__isl_keep isl_basic_map *bmap2)
10158 {
10159 	int i, cmp;
10160 	isl_size total;
10161 	isl_space *space1, *space2;
10162 
10163 	if (!bmap1 || !bmap2)
10164 		return -1;
10165 
10166 	if (bmap1 == bmap2)
10167 		return 0;
10168 	space1 = isl_basic_map_peek_space(bmap1);
10169 	space2 = isl_basic_map_peek_space(bmap2);
10170 	cmp = isl_space_cmp(space1, space2);
10171 	if (cmp)
10172 		return cmp;
10173 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
10174 	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
10175 		return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
10176 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
10177 	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10178 		return 0;
10179 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
10180 		return 1;
10181 	if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10182 		return -1;
10183 	if (bmap1->n_eq != bmap2->n_eq)
10184 		return bmap1->n_eq - bmap2->n_eq;
10185 	if (bmap1->n_ineq != bmap2->n_ineq)
10186 		return bmap1->n_ineq - bmap2->n_ineq;
10187 	if (bmap1->n_div != bmap2->n_div)
10188 		return bmap1->n_div - bmap2->n_div;
10189 	total = isl_basic_map_dim(bmap1, isl_dim_all);
10190 	if (total < 0)
10191 		return -1;
10192 	for (i = 0; i < bmap1->n_eq; ++i) {
10193 		cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
10194 		if (cmp)
10195 			return cmp;
10196 	}
10197 	for (i = 0; i < bmap1->n_ineq; ++i) {
10198 		cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
10199 		if (cmp)
10200 			return cmp;
10201 	}
10202 	for (i = 0; i < bmap1->n_div; ++i) {
10203 		cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
10204 		if (cmp)
10205 			return cmp;
10206 	}
10207 	return 0;
10208 }
10209 
isl_basic_set_plain_cmp(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10210 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
10211 	__isl_keep isl_basic_set *bset2)
10212 {
10213 	return isl_basic_map_plain_cmp(bset1, bset2);
10214 }
10215 
isl_set_plain_cmp(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10216 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
10217 {
10218 	int i, cmp;
10219 
10220 	if (set1 == set2)
10221 		return 0;
10222 	if (set1->n != set2->n)
10223 		return set1->n - set2->n;
10224 
10225 	for (i = 0; i < set1->n; ++i) {
10226 		cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
10227 		if (cmp)
10228 			return cmp;
10229 	}
10230 
10231 	return 0;
10232 }
10233 
isl_basic_map_plain_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10234 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
10235 	__isl_keep isl_basic_map *bmap2)
10236 {
10237 	if (!bmap1 || !bmap2)
10238 		return isl_bool_error;
10239 	return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
10240 }
10241 
isl_basic_set_plain_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10242 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
10243 	__isl_keep isl_basic_set *bset2)
10244 {
10245 	return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
10246 					    bset_to_bmap(bset2));
10247 }
10248 
qsort_bmap_cmp(const void * p1,const void * p2)10249 static int qsort_bmap_cmp(const void *p1, const void *p2)
10250 {
10251 	isl_basic_map *bmap1 = *(isl_basic_map **) p1;
10252 	isl_basic_map *bmap2 = *(isl_basic_map **) p2;
10253 
10254 	return isl_basic_map_plain_cmp(bmap1, bmap2);
10255 }
10256 
10257 /* Sort the basic maps of "map" and remove duplicate basic maps.
10258  *
10259  * While removing basic maps, we make sure that the basic maps remain
10260  * sorted because isl_map_normalize expects the basic maps of the result
10261  * to be sorted.
10262  */
sort_and_remove_duplicates(__isl_take isl_map * map)10263 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
10264 {
10265 	int i, j;
10266 
10267 	map = isl_map_remove_empty_parts(map);
10268 	if (!map)
10269 		return NULL;
10270 	qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
10271 	for (i = map->n - 1; i >= 1; --i) {
10272 		if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
10273 			continue;
10274 		isl_basic_map_free(map->p[i-1]);
10275 		for (j = i; j < map->n; ++j)
10276 			map->p[j - 1] = map->p[j];
10277 		map->n--;
10278 	}
10279 
10280 	return map;
10281 }
10282 
10283 /* Remove obvious duplicates among the basic maps of "map".
10284  *
10285  * Unlike isl_map_normalize, this function does not remove redundant
10286  * constraints and only removes duplicates that have exactly the same
10287  * constraints in the input.  It does sort the constraints and
10288  * the basic maps to ease the detection of duplicates.
10289  *
10290  * If "map" has already been normalized or if the basic maps are
10291  * disjoint, then there can be no duplicates.
10292  */
isl_map_remove_obvious_duplicates(__isl_take isl_map * map)10293 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
10294 {
10295 	int i;
10296 	isl_basic_map *bmap;
10297 
10298 	if (!map)
10299 		return NULL;
10300 	if (map->n <= 1)
10301 		return map;
10302 	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
10303 		return map;
10304 	for (i = 0; i < map->n; ++i) {
10305 		bmap = isl_basic_map_copy(map->p[i]);
10306 		bmap = isl_basic_map_sort_constraints(bmap);
10307 		if (!bmap)
10308 			return isl_map_free(map);
10309 		isl_basic_map_free(map->p[i]);
10310 		map->p[i] = bmap;
10311 	}
10312 
10313 	map = sort_and_remove_duplicates(map);
10314 	return map;
10315 }
10316 
10317 /* We normalize in place, but if anything goes wrong we need
10318  * to return NULL, so we need to make sure we don't change the
10319  * meaning of any possible other copies of map.
10320  */
isl_map_normalize(__isl_take isl_map * map)10321 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
10322 {
10323 	int i;
10324 	struct isl_basic_map *bmap;
10325 
10326 	if (!map)
10327 		return NULL;
10328 	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
10329 		return map;
10330 	for (i = 0; i < map->n; ++i) {
10331 		bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
10332 		if (!bmap)
10333 			goto error;
10334 		isl_basic_map_free(map->p[i]);
10335 		map->p[i] = bmap;
10336 	}
10337 
10338 	map = sort_and_remove_duplicates(map);
10339 	if (map)
10340 		ISL_F_SET(map, ISL_MAP_NORMALIZED);
10341 	return map;
10342 error:
10343 	isl_map_free(map);
10344 	return NULL;
10345 }
10346 
isl_set_normalize(__isl_take isl_set * set)10347 __isl_give isl_set *isl_set_normalize(__isl_take isl_set *set)
10348 {
10349 	return set_from_map(isl_map_normalize(set_to_map(set)));
10350 }
10351 
isl_map_plain_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)10352 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
10353 	__isl_keep isl_map *map2)
10354 {
10355 	int i;
10356 	isl_bool equal;
10357 
10358 	if (!map1 || !map2)
10359 		return isl_bool_error;
10360 
10361 	if (map1 == map2)
10362 		return isl_bool_true;
10363 	equal = isl_map_has_equal_space(map1, map2);
10364 	if (equal < 0 || !equal)
10365 		return equal;
10366 
10367 	map1 = isl_map_copy(map1);
10368 	map2 = isl_map_copy(map2);
10369 	map1 = isl_map_normalize(map1);
10370 	map2 = isl_map_normalize(map2);
10371 	if (!map1 || !map2)
10372 		goto error;
10373 	equal = map1->n == map2->n;
10374 	for (i = 0; equal && i < map1->n; ++i) {
10375 		equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
10376 		if (equal < 0)
10377 			goto error;
10378 	}
10379 	isl_map_free(map1);
10380 	isl_map_free(map2);
10381 	return equal;
10382 error:
10383 	isl_map_free(map1);
10384 	isl_map_free(map2);
10385 	return isl_bool_error;
10386 }
10387 
isl_set_plain_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10388 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
10389 	__isl_keep isl_set *set2)
10390 {
10391 	return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
10392 }
10393 
10394 /* Return the basic maps in "map" as a list.
10395  */
isl_map_get_basic_map_list(__isl_keep isl_map * map)10396 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
10397 	__isl_keep isl_map *map)
10398 {
10399 	int i;
10400 	isl_ctx *ctx;
10401 	isl_basic_map_list *list;
10402 
10403 	if (!map)
10404 		return NULL;
10405 	ctx = isl_map_get_ctx(map);
10406 	list = isl_basic_map_list_alloc(ctx, map->n);
10407 
10408 	for (i = 0; i < map->n; ++i) {
10409 		isl_basic_map *bmap;
10410 
10411 		bmap = isl_basic_map_copy(map->p[i]);
10412 		list = isl_basic_map_list_add(list, bmap);
10413 	}
10414 
10415 	return list;
10416 }
10417 
10418 /* Return the intersection of the elements in the non-empty list "list".
10419  * All elements are assumed to live in the same space.
10420  */
isl_basic_map_list_intersect(__isl_take isl_basic_map_list * list)10421 __isl_give isl_basic_map *isl_basic_map_list_intersect(
10422 	__isl_take isl_basic_map_list *list)
10423 {
10424 	int i;
10425 	isl_size n;
10426 	isl_basic_map *bmap;
10427 
10428 	n = isl_basic_map_list_n_basic_map(list);
10429 	if (n < 0)
10430 		goto error;
10431 	if (n < 1)
10432 		isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
10433 			"expecting non-empty list", goto error);
10434 
10435 	bmap = isl_basic_map_list_get_basic_map(list, 0);
10436 	for (i = 1; i < n; ++i) {
10437 		isl_basic_map *bmap_i;
10438 
10439 		bmap_i = isl_basic_map_list_get_basic_map(list, i);
10440 		bmap = isl_basic_map_intersect(bmap, bmap_i);
10441 	}
10442 
10443 	isl_basic_map_list_free(list);
10444 	return bmap;
10445 error:
10446 	isl_basic_map_list_free(list);
10447 	return NULL;
10448 }
10449 
10450 /* Return the intersection of the elements in the non-empty list "list".
10451  * All elements are assumed to live in the same space.
10452  */
isl_basic_set_list_intersect(__isl_take isl_basic_set_list * list)10453 __isl_give isl_basic_set *isl_basic_set_list_intersect(
10454 	__isl_take isl_basic_set_list *list)
10455 {
10456 	return isl_basic_map_list_intersect(list);
10457 }
10458 
10459 /* Return the union of the elements of "list".
10460  * The list is required to have at least one element.
10461  */
isl_basic_set_list_union(__isl_take isl_basic_set_list * list)10462 __isl_give isl_set *isl_basic_set_list_union(
10463 	__isl_take isl_basic_set_list *list)
10464 {
10465 	int i;
10466 	isl_size n;
10467 	isl_space *space;
10468 	isl_basic_set *bset;
10469 	isl_set *set;
10470 
10471 	n = isl_basic_set_list_n_basic_set(list);
10472 	if (n < 0)
10473 		goto error;
10474 	if (n < 1)
10475 		isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
10476 			"expecting non-empty list", goto error);
10477 
10478 	bset = isl_basic_set_list_get_basic_set(list, 0);
10479 	space = isl_basic_set_get_space(bset);
10480 	isl_basic_set_free(bset);
10481 
10482 	set = isl_set_alloc_space(space, n, 0);
10483 	for (i = 0; i < n; ++i) {
10484 		bset = isl_basic_set_list_get_basic_set(list, i);
10485 		set = isl_set_add_basic_set(set, bset);
10486 	}
10487 
10488 	isl_basic_set_list_free(list);
10489 	return set;
10490 error:
10491 	isl_basic_set_list_free(list);
10492 	return NULL;
10493 }
10494 
10495 /* Return the union of the elements in the non-empty list "list".
10496  * All elements are assumed to live in the same space.
10497  */
isl_set_list_union(__isl_take isl_set_list * list)10498 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
10499 {
10500 	int i;
10501 	isl_size n;
10502 	isl_set *set;
10503 
10504 	n = isl_set_list_n_set(list);
10505 	if (n < 0)
10506 		goto error;
10507 	if (n < 1)
10508 		isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
10509 			"expecting non-empty list", goto error);
10510 
10511 	set = isl_set_list_get_set(list, 0);
10512 	for (i = 1; i < n; ++i) {
10513 		isl_set *set_i;
10514 
10515 		set_i = isl_set_list_get_set(list, i);
10516 		set = isl_set_union(set, set_i);
10517 	}
10518 
10519 	isl_set_list_free(list);
10520 	return set;
10521 error:
10522 	isl_set_list_free(list);
10523 	return NULL;
10524 }
10525 
isl_basic_map_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10526 __isl_give isl_basic_map *isl_basic_map_product(
10527 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10528 {
10529 	isl_space *space_result = NULL;
10530 	struct isl_basic_map *bmap;
10531 	unsigned in1, in2, out1, out2, nparam, total, pos;
10532 	struct isl_dim_map *dim_map1, *dim_map2;
10533 
10534 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10535 		goto error;
10536 	space_result = isl_space_product(isl_space_copy(bmap1->dim),
10537 						   isl_space_copy(bmap2->dim));
10538 
10539 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10540 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10541 	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10542 	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10543 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10544 
10545 	total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
10546 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10547 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10548 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10549 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10550 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10551 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10552 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10553 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10554 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
10555 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10556 
10557 	bmap = isl_basic_map_alloc_space(space_result,
10558 			bmap1->n_div + bmap2->n_div,
10559 			bmap1->n_eq + bmap2->n_eq,
10560 			bmap1->n_ineq + bmap2->n_ineq);
10561 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10562 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10563 	bmap = isl_basic_map_simplify(bmap);
10564 	return isl_basic_map_finalize(bmap);
10565 error:
10566 	isl_basic_map_free(bmap1);
10567 	isl_basic_map_free(bmap2);
10568 	return NULL;
10569 }
10570 
isl_basic_map_flat_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10571 __isl_give isl_basic_map *isl_basic_map_flat_product(
10572 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10573 {
10574 	isl_basic_map *prod;
10575 
10576 	prod = isl_basic_map_product(bmap1, bmap2);
10577 	prod = isl_basic_map_flatten(prod);
10578 	return prod;
10579 }
10580 
isl_basic_set_flat_product(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)10581 __isl_give isl_basic_set *isl_basic_set_flat_product(
10582 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10583 {
10584 	return isl_basic_map_flat_range_product(bset1, bset2);
10585 }
10586 
isl_basic_map_domain_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10587 __isl_give isl_basic_map *isl_basic_map_domain_product(
10588 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10589 {
10590 	isl_space *space1, *space2;
10591 	isl_space *space_result = NULL;
10592 	isl_basic_map *bmap;
10593 	isl_size in1, in2, out, nparam;
10594 	unsigned total, pos;
10595 	struct isl_dim_map *dim_map1, *dim_map2;
10596 
10597 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10598 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10599 	out = isl_basic_map_dim(bmap1, isl_dim_out);
10600 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10601 	if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
10602 		goto error;
10603 
10604 	space1 = isl_basic_map_get_space(bmap1);
10605 	space2 = isl_basic_map_get_space(bmap2);
10606 	space_result = isl_space_domain_product(space1, space2);
10607 
10608 	total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10609 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10610 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10611 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10612 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10613 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10614 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10615 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10616 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10617 	isl_dim_map_div(dim_map1, bmap1, pos += out);
10618 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10619 
10620 	bmap = isl_basic_map_alloc_space(space_result,
10621 			bmap1->n_div + bmap2->n_div,
10622 			bmap1->n_eq + bmap2->n_eq,
10623 			bmap1->n_ineq + bmap2->n_ineq);
10624 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10625 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10626 	bmap = isl_basic_map_simplify(bmap);
10627 	return isl_basic_map_finalize(bmap);
10628 error:
10629 	isl_basic_map_free(bmap1);
10630 	isl_basic_map_free(bmap2);
10631 	return NULL;
10632 }
10633 
isl_basic_map_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10634 __isl_give isl_basic_map *isl_basic_map_range_product(
10635 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10636 {
10637 	isl_bool rational;
10638 	isl_space *space_result = NULL;
10639 	isl_basic_map *bmap;
10640 	isl_size in, out1, out2, nparam;
10641 	unsigned total, pos;
10642 	struct isl_dim_map *dim_map1, *dim_map2;
10643 
10644 	rational = isl_basic_map_is_rational(bmap1);
10645 	if (rational >= 0 && rational)
10646 		rational = isl_basic_map_is_rational(bmap2);
10647 	in = isl_basic_map_dim(bmap1, isl_dim_in);
10648 	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10649 	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10650 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10651 	if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
10652 		goto error;
10653 
10654 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10655 		goto error;
10656 
10657 	space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10658 					   isl_space_copy(bmap2->dim));
10659 
10660 	total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10661 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10662 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10663 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10664 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10665 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10666 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10667 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10668 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10669 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
10670 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10671 
10672 	bmap = isl_basic_map_alloc_space(space_result,
10673 			bmap1->n_div + bmap2->n_div,
10674 			bmap1->n_eq + bmap2->n_eq,
10675 			bmap1->n_ineq + bmap2->n_ineq);
10676 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10677 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10678 	if (rational)
10679 		bmap = isl_basic_map_set_rational(bmap);
10680 	bmap = isl_basic_map_simplify(bmap);
10681 	return isl_basic_map_finalize(bmap);
10682 error:
10683 	isl_basic_map_free(bmap1);
10684 	isl_basic_map_free(bmap2);
10685 	return NULL;
10686 }
10687 
isl_basic_map_flat_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10688 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10689 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10690 {
10691 	isl_basic_map *prod;
10692 
10693 	prod = isl_basic_map_range_product(bmap1, bmap2);
10694 	prod = isl_basic_map_flatten_range(prod);
10695 	return prod;
10696 }
10697 
10698 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10699  * and collect the results.
10700  * The result live in the space obtained by calling "space_product"
10701  * on the spaces of "map1" and "map2".
10702  * If "remove_duplicates" is set then the result may contain duplicates
10703  * (even if the inputs do not) and so we try and remove the obvious
10704  * duplicates.
10705  */
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)10706 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10707 	__isl_take isl_map *map2,
10708 	__isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10709 					   __isl_take isl_space *right),
10710 	__isl_give isl_basic_map *(*basic_map_product)(
10711 		__isl_take isl_basic_map *left,
10712 		__isl_take isl_basic_map *right),
10713 	int remove_duplicates)
10714 {
10715 	unsigned flags = 0;
10716 	struct isl_map *result;
10717 	int i, j;
10718 	isl_bool m;
10719 
10720 	m = isl_map_has_equal_params(map1, map2);
10721 	if (m < 0)
10722 		goto error;
10723 	if (!m)
10724 		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10725 			"parameters don't match", goto error);
10726 
10727 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10728 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10729 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10730 
10731 	result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10732 					       isl_space_copy(map2->dim)),
10733 				map1->n * map2->n, flags);
10734 	if (!result)
10735 		goto error;
10736 	for (i = 0; i < map1->n; ++i)
10737 		for (j = 0; j < map2->n; ++j) {
10738 			struct isl_basic_map *part;
10739 			part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10740 						 isl_basic_map_copy(map2->p[j]));
10741 			if (isl_basic_map_is_empty(part))
10742 				isl_basic_map_free(part);
10743 			else
10744 				result = isl_map_add_basic_map(result, part);
10745 			if (!result)
10746 				goto error;
10747 		}
10748 	if (remove_duplicates)
10749 		result = isl_map_remove_obvious_duplicates(result);
10750 	isl_map_free(map1);
10751 	isl_map_free(map2);
10752 	return result;
10753 error:
10754 	isl_map_free(map1);
10755 	isl_map_free(map2);
10756 	return NULL;
10757 }
10758 
10759 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10760  */
isl_map_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10761 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10762 	__isl_take isl_map *map2)
10763 {
10764 	isl_map_align_params_bin(&map1, &map2);
10765 	return map_product(map1, map2, &isl_space_product,
10766 			&isl_basic_map_product, 0);
10767 }
10768 
10769 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10770  */
isl_map_flat_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10771 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10772 	__isl_take isl_map *map2)
10773 {
10774 	isl_map *prod;
10775 
10776 	prod = isl_map_product(map1, map2);
10777 	prod = isl_map_flatten(prod);
10778 	return prod;
10779 }
10780 
10781 /* Given two set A and B, construct its Cartesian product A x B.
10782  */
isl_set_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10783 __isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
10784 	__isl_take isl_set *set2)
10785 {
10786 	return isl_map_range_product(set1, set2);
10787 }
10788 
isl_set_flat_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10789 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10790 	__isl_take isl_set *set2)
10791 {
10792 	return isl_map_flat_range_product(set1, set2);
10793 }
10794 
10795 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10796  */
isl_map_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10797 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10798 	__isl_take isl_map *map2)
10799 {
10800 	isl_map_align_params_bin(&map1, &map2);
10801 	return map_product(map1, map2, &isl_space_domain_product,
10802 				&isl_basic_map_domain_product, 1);
10803 }
10804 
10805 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10806  */
isl_map_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10807 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10808 	__isl_take isl_map *map2)
10809 {
10810 	isl_map_align_params_bin(&map1, &map2);
10811 	return map_product(map1, map2, &isl_space_range_product,
10812 				&isl_basic_map_range_product, 1);
10813 }
10814 
10815 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10816  */
isl_map_factor_domain(__isl_take isl_map * map)10817 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10818 {
10819 	isl_space *space;
10820 	isl_size total1, keep1, total2, keep2;
10821 
10822 	total1 = isl_map_dim(map, isl_dim_in);
10823 	total2 = isl_map_dim(map, isl_dim_out);
10824 	if (total1 < 0 || total2 < 0)
10825 		return isl_map_free(map);
10826 	if (!isl_space_domain_is_wrapping(map->dim) ||
10827 	    !isl_space_range_is_wrapping(map->dim))
10828 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10829 			"not a product", return isl_map_free(map));
10830 
10831 	space = isl_map_get_space(map);
10832 	space = isl_space_factor_domain(space);
10833 	keep1 = isl_space_dim(space, isl_dim_in);
10834 	keep2 = isl_space_dim(space, isl_dim_out);
10835 	if (keep1 < 0 || keep2 < 0)
10836 		map = isl_map_free(map);
10837 	map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10838 	map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10839 	map = isl_map_reset_space(map, space);
10840 
10841 	return map;
10842 }
10843 
10844 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10845  */
isl_map_factor_range(__isl_take isl_map * map)10846 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10847 {
10848 	isl_space *space;
10849 	isl_size total1, keep1, total2, keep2;
10850 
10851 	total1 = isl_map_dim(map, isl_dim_in);
10852 	total2 = isl_map_dim(map, isl_dim_out);
10853 	if (total1 < 0 || total2 < 0)
10854 		return isl_map_free(map);
10855 	if (!isl_space_domain_is_wrapping(map->dim) ||
10856 	    !isl_space_range_is_wrapping(map->dim))
10857 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10858 			"not a product", return isl_map_free(map));
10859 
10860 	space = isl_map_get_space(map);
10861 	space = isl_space_factor_range(space);
10862 	keep1 = isl_space_dim(space, isl_dim_in);
10863 	keep2 = isl_space_dim(space, isl_dim_out);
10864 	if (keep1 < 0 || keep2 < 0)
10865 		map = isl_map_free(map);
10866 	map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10867 	map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10868 	map = isl_map_reset_space(map, space);
10869 
10870 	return map;
10871 }
10872 
10873 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10874  */
isl_map_domain_factor_domain(__isl_take isl_map * map)10875 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10876 {
10877 	isl_space *space;
10878 	isl_size total, keep;
10879 
10880 	total = isl_map_dim(map, isl_dim_in);
10881 	if (total < 0)
10882 		return isl_map_free(map);
10883 	if (!isl_space_domain_is_wrapping(map->dim))
10884 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10885 			"domain is not a product", return isl_map_free(map));
10886 
10887 	space = isl_map_get_space(map);
10888 	space = isl_space_domain_factor_domain(space);
10889 	keep = isl_space_dim(space, isl_dim_in);
10890 	if (keep < 0)
10891 		map = isl_map_free(map);
10892 	map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10893 	map = isl_map_reset_space(map, space);
10894 
10895 	return map;
10896 }
10897 
10898 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10899  */
isl_map_domain_factor_range(__isl_take isl_map * map)10900 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10901 {
10902 	isl_space *space;
10903 	isl_size total, keep;
10904 
10905 	total = isl_map_dim(map, isl_dim_in);
10906 	if (total < 0)
10907 		return isl_map_free(map);
10908 	if (!isl_space_domain_is_wrapping(map->dim))
10909 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10910 			"domain is not a product", return isl_map_free(map));
10911 
10912 	space = isl_map_get_space(map);
10913 	space = isl_space_domain_factor_range(space);
10914 	keep = isl_space_dim(space, isl_dim_in);
10915 	if (keep < 0)
10916 		map = isl_map_free(map);
10917 	map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10918 	map = isl_map_reset_space(map, space);
10919 
10920 	return map;
10921 }
10922 
10923 /* Given a map A -> [B -> C], extract the map A -> B.
10924  */
isl_map_range_factor_domain(__isl_take isl_map * map)10925 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10926 {
10927 	isl_space *space;
10928 	isl_size total, keep;
10929 
10930 	total = isl_map_dim(map, isl_dim_out);
10931 	if (total < 0)
10932 		return isl_map_free(map);
10933 	if (!isl_space_range_is_wrapping(map->dim))
10934 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10935 			"range is not a product", return isl_map_free(map));
10936 
10937 	space = isl_map_get_space(map);
10938 	space = isl_space_range_factor_domain(space);
10939 	keep = isl_space_dim(space, isl_dim_out);
10940 	if (keep < 0)
10941 		map = isl_map_free(map);
10942 	map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10943 	map = isl_map_reset_space(map, space);
10944 
10945 	return map;
10946 }
10947 
10948 /* Given a map A -> [B -> C], extract the map A -> C.
10949  */
isl_map_range_factor_range(__isl_take isl_map * map)10950 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10951 {
10952 	isl_space *space;
10953 	isl_size total, keep;
10954 
10955 	total = isl_map_dim(map, isl_dim_out);
10956 	if (total < 0)
10957 		return isl_map_free(map);
10958 	if (!isl_space_range_is_wrapping(map->dim))
10959 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10960 			"range is not a product", return isl_map_free(map));
10961 
10962 	space = isl_map_get_space(map);
10963 	space = isl_space_range_factor_range(space);
10964 	keep = isl_space_dim(space, isl_dim_out);
10965 	if (keep < 0)
10966 		map = isl_map_free(map);
10967 	map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10968 	map = isl_map_reset_space(map, space);
10969 
10970 	return map;
10971 }
10972 
10973 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10974  */
isl_map_flat_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10975 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10976 	__isl_take isl_map *map2)
10977 {
10978 	isl_map *prod;
10979 
10980 	prod = isl_map_domain_product(map1, map2);
10981 	prod = isl_map_flatten_domain(prod);
10982 	return prod;
10983 }
10984 
10985 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10986  */
isl_map_flat_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10987 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10988 	__isl_take isl_map *map2)
10989 {
10990 	isl_map *prod;
10991 
10992 	prod = isl_map_range_product(map1, map2);
10993 	prod = isl_map_flatten_range(prod);
10994 	return prod;
10995 }
10996 
isl_basic_map_get_hash(__isl_keep isl_basic_map * bmap)10997 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10998 {
10999 	int i;
11000 	uint32_t hash = isl_hash_init();
11001 	isl_size total;
11002 
11003 	if (!bmap)
11004 		return 0;
11005 	bmap = isl_basic_map_copy(bmap);
11006 	bmap = isl_basic_map_normalize(bmap);
11007 	total = isl_basic_map_dim(bmap, isl_dim_all);
11008 	if (total < 0)
11009 		return 0;
11010 	isl_hash_byte(hash, bmap->n_eq & 0xFF);
11011 	for (i = 0; i < bmap->n_eq; ++i) {
11012 		uint32_t c_hash;
11013 		c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
11014 		isl_hash_hash(hash, c_hash);
11015 	}
11016 	isl_hash_byte(hash, bmap->n_ineq & 0xFF);
11017 	for (i = 0; i < bmap->n_ineq; ++i) {
11018 		uint32_t c_hash;
11019 		c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
11020 		isl_hash_hash(hash, c_hash);
11021 	}
11022 	isl_hash_byte(hash, bmap->n_div & 0xFF);
11023 	for (i = 0; i < bmap->n_div; ++i) {
11024 		uint32_t c_hash;
11025 		if (isl_int_is_zero(bmap->div[i][0]))
11026 			continue;
11027 		isl_hash_byte(hash, i & 0xFF);
11028 		c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
11029 		isl_hash_hash(hash, c_hash);
11030 	}
11031 	isl_basic_map_free(bmap);
11032 	return hash;
11033 }
11034 
isl_basic_set_get_hash(__isl_keep isl_basic_set * bset)11035 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
11036 {
11037 	return isl_basic_map_get_hash(bset_to_bmap(bset));
11038 }
11039 
isl_map_get_hash(__isl_keep isl_map * map)11040 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
11041 {
11042 	int i;
11043 	uint32_t hash;
11044 
11045 	if (!map)
11046 		return 0;
11047 	map = isl_map_copy(map);
11048 	map = isl_map_normalize(map);
11049 	if (!map)
11050 		return 0;
11051 
11052 	hash = isl_hash_init();
11053 	for (i = 0; i < map->n; ++i) {
11054 		uint32_t bmap_hash;
11055 		bmap_hash = isl_basic_map_get_hash(map->p[i]);
11056 		isl_hash_hash(hash, bmap_hash);
11057 	}
11058 
11059 	isl_map_free(map);
11060 
11061 	return hash;
11062 }
11063 
isl_set_get_hash(__isl_keep isl_set * set)11064 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
11065 {
11066 	return isl_map_get_hash(set_to_map(set));
11067 }
11068 
11069 /* Return the number of basic maps in the (current) representation of "map".
11070  */
isl_map_n_basic_map(__isl_keep isl_map * map)11071 isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
11072 {
11073 	return map ? map->n : isl_size_error;
11074 }
11075 
isl_set_n_basic_set(__isl_keep isl_set * set)11076 isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
11077 {
11078 	return set ? set->n : isl_size_error;
11079 }
11080 
isl_map_foreach_basic_map(__isl_keep isl_map * map,isl_stat (* fn)(__isl_take isl_basic_map * bmap,void * user),void * user)11081 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
11082 	isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
11083 {
11084 	int i;
11085 
11086 	if (!map)
11087 		return isl_stat_error;
11088 
11089 	for (i = 0; i < map->n; ++i)
11090 		if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
11091 			return isl_stat_error;
11092 
11093 	return isl_stat_ok;
11094 }
11095 
isl_set_foreach_basic_set(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_basic_set * bset,void * user),void * user)11096 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
11097 	isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
11098 {
11099 	int i;
11100 
11101 	if (!set)
11102 		return isl_stat_error;
11103 
11104 	for (i = 0; i < set->n; ++i)
11105 		if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
11106 			return isl_stat_error;
11107 
11108 	return isl_stat_ok;
11109 }
11110 
11111 /* Does "test" succeed on every basic set in "set"?
11112  */
isl_set_every_basic_set(__isl_keep isl_set * set,isl_bool (* test)(__isl_keep isl_basic_set * bset,void * user),void * user)11113 isl_bool isl_set_every_basic_set(__isl_keep isl_set *set,
11114 	isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),
11115 	void *user)
11116 {
11117 	int i;
11118 
11119 	if (!set)
11120 		return isl_bool_error;
11121 
11122 	for (i = 0; i < set->n; ++i) {
11123 		isl_bool r;
11124 
11125 		r = test(set->p[i], user);
11126 		if (r < 0 || !r)
11127 			return r;
11128 	}
11129 
11130 	return isl_bool_true;
11131 }
11132 
11133 /* Return a list of basic sets, the union of which is equal to "set".
11134  */
isl_set_get_basic_set_list(__isl_keep isl_set * set)11135 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
11136 	__isl_keep isl_set *set)
11137 {
11138 	int i;
11139 	isl_basic_set_list *list;
11140 
11141 	if (!set)
11142 		return NULL;
11143 
11144 	list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
11145 	for (i = 0; i < set->n; ++i) {
11146 		isl_basic_set *bset;
11147 
11148 		bset = isl_basic_set_copy(set->p[i]);
11149 		list = isl_basic_set_list_add(list, bset);
11150 	}
11151 
11152 	return list;
11153 }
11154 
isl_basic_set_lift(__isl_take isl_basic_set * bset)11155 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
11156 {
11157 	isl_space *space;
11158 
11159 	if (!bset)
11160 		return NULL;
11161 
11162 	bset = isl_basic_set_cow(bset);
11163 	if (!bset)
11164 		return NULL;
11165 
11166 	space = isl_basic_set_get_space(bset);
11167 	space = isl_space_lift(space, bset->n_div);
11168 	if (!space)
11169 		goto error;
11170 	isl_space_free(bset->dim);
11171 	bset->dim = space;
11172 	bset->extra -= bset->n_div;
11173 	bset->n_div = 0;
11174 
11175 	bset = isl_basic_set_finalize(bset);
11176 
11177 	return bset;
11178 error:
11179 	isl_basic_set_free(bset);
11180 	return NULL;
11181 }
11182 
isl_set_lift(__isl_take isl_set * set)11183 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
11184 {
11185 	int i;
11186 	isl_space *space;
11187 	unsigned n_div;
11188 
11189 	set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
11190 
11191 	if (!set)
11192 		return NULL;
11193 
11194 	set = isl_set_cow(set);
11195 	if (!set)
11196 		return NULL;
11197 
11198 	n_div = set->p[0]->n_div;
11199 	space = isl_set_get_space(set);
11200 	space = isl_space_lift(space, n_div);
11201 	if (!space)
11202 		goto error;
11203 	isl_space_free(set->dim);
11204 	set->dim = space;
11205 
11206 	for (i = 0; i < set->n; ++i) {
11207 		set->p[i] = isl_basic_set_lift(set->p[i]);
11208 		if (!set->p[i])
11209 			goto error;
11210 	}
11211 
11212 	return set;
11213 error:
11214 	isl_set_free(set);
11215 	return NULL;
11216 }
11217 
isl_basic_set_size(__isl_keep isl_basic_set * bset)11218 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
11219 {
11220 	isl_size dim;
11221 	int size = 0;
11222 
11223 	dim = isl_basic_set_dim(bset, isl_dim_all);
11224 	if (dim < 0)
11225 		return -1;
11226 	size += bset->n_eq * (1 + dim);
11227 	size += bset->n_ineq * (1 + dim);
11228 	size += bset->n_div * (2 + dim);
11229 
11230 	return size;
11231 }
11232 
isl_set_size(__isl_keep isl_set * set)11233 int isl_set_size(__isl_keep isl_set *set)
11234 {
11235 	int i;
11236 	int size = 0;
11237 
11238 	if (!set)
11239 		return -1;
11240 
11241 	for (i = 0; i < set->n; ++i)
11242 		size += isl_basic_set_size(set->p[i]);
11243 
11244 	return size;
11245 }
11246 
11247 /* Check if there is any lower bound (if lower == 0) and/or upper
11248  * bound (if upper == 0) on the specified dim.
11249  */
basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int lower,int upper)11250 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11251 	enum isl_dim_type type, unsigned pos, int lower, int upper)
11252 {
11253 	int i;
11254 
11255 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
11256 		return isl_bool_error;
11257 
11258 	pos += isl_basic_map_offset(bmap, type);
11259 
11260 	for (i = 0; i < bmap->n_div; ++i) {
11261 		if (isl_int_is_zero(bmap->div[i][0]))
11262 			continue;
11263 		if (!isl_int_is_zero(bmap->div[i][1 + pos]))
11264 			return isl_bool_true;
11265 	}
11266 
11267 	for (i = 0; i < bmap->n_eq; ++i)
11268 		if (!isl_int_is_zero(bmap->eq[i][pos]))
11269 			return isl_bool_true;
11270 
11271 	for (i = 0; i < bmap->n_ineq; ++i) {
11272 		int sgn = isl_int_sgn(bmap->ineq[i][pos]);
11273 		if (sgn > 0)
11274 			lower = 1;
11275 		if (sgn < 0)
11276 			upper = 1;
11277 	}
11278 
11279 	return lower && upper;
11280 }
11281 
isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11282 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11283 	enum isl_dim_type type, unsigned pos)
11284 {
11285 	return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
11286 }
11287 
isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11288 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
11289 	enum isl_dim_type type, unsigned pos)
11290 {
11291 	return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
11292 }
11293 
isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11294 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
11295 	enum isl_dim_type type, unsigned pos)
11296 {
11297 	return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
11298 }
11299 
isl_map_dim_is_bounded(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)11300 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
11301 	enum isl_dim_type type, unsigned pos)
11302 {
11303 	int i;
11304 
11305 	if (!map)
11306 		return isl_bool_error;
11307 
11308 	for (i = 0; i < map->n; ++i) {
11309 		isl_bool bounded;
11310 		bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
11311 		if (bounded < 0 || !bounded)
11312 			return bounded;
11313 	}
11314 
11315 	return isl_bool_true;
11316 }
11317 
11318 /* Return true if the specified dim is involved in both an upper bound
11319  * and a lower bound.
11320  */
isl_set_dim_is_bounded(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11321 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
11322 	enum isl_dim_type type, unsigned pos)
11323 {
11324 	return isl_map_dim_is_bounded(set_to_map(set), type, pos);
11325 }
11326 
11327 /* Does "map" have a bound (according to "fn") for any of its basic maps?
11328  */
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))11329 static isl_bool has_any_bound(__isl_keep isl_map *map,
11330 	enum isl_dim_type type, unsigned pos,
11331 	isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11332 		  enum isl_dim_type type, unsigned pos))
11333 {
11334 	int i;
11335 
11336 	if (!map)
11337 		return isl_bool_error;
11338 
11339 	for (i = 0; i < map->n; ++i) {
11340 		isl_bool bounded;
11341 		bounded = fn(map->p[i], type, pos);
11342 		if (bounded < 0 || bounded)
11343 			return bounded;
11344 	}
11345 
11346 	return isl_bool_false;
11347 }
11348 
11349 /* Return 1 if the specified dim is involved in any lower bound.
11350  */
isl_set_dim_has_any_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11351 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
11352 	enum isl_dim_type type, unsigned pos)
11353 {
11354 	return has_any_bound(set, type, pos,
11355 				&isl_basic_map_dim_has_lower_bound);
11356 }
11357 
11358 /* Return 1 if the specified dim is involved in any upper bound.
11359  */
isl_set_dim_has_any_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11360 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
11361 	enum isl_dim_type type, unsigned pos)
11362 {
11363 	return has_any_bound(set, type, pos,
11364 				&isl_basic_map_dim_has_upper_bound);
11365 }
11366 
11367 /* Does "map" have a bound (according to "fn") for all of its basic maps?
11368  */
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))11369 static isl_bool has_bound(__isl_keep isl_map *map,
11370 	enum isl_dim_type type, unsigned pos,
11371 	isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11372 		  enum isl_dim_type type, unsigned pos))
11373 {
11374 	int i;
11375 
11376 	if (!map)
11377 		return isl_bool_error;
11378 
11379 	for (i = 0; i < map->n; ++i) {
11380 		isl_bool bounded;
11381 		bounded = fn(map->p[i], type, pos);
11382 		if (bounded < 0 || !bounded)
11383 			return bounded;
11384 	}
11385 
11386 	return isl_bool_true;
11387 }
11388 
11389 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
11390  */
isl_set_dim_has_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11391 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
11392 	enum isl_dim_type type, unsigned pos)
11393 {
11394 	return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
11395 }
11396 
11397 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
11398  */
isl_set_dim_has_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11399 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
11400 	enum isl_dim_type type, unsigned pos)
11401 {
11402 	return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
11403 }
11404 
11405 /* For each of the "n" variables starting at "first", determine
11406  * the sign of the variable and put the results in the first "n"
11407  * elements of the array "signs".
11408  * Sign
11409  *	1 means that the variable is non-negative
11410  *	-1 means that the variable is non-positive
11411  *	0 means the variable attains both positive and negative values.
11412  */
isl_basic_set_vars_get_sign(__isl_keep isl_basic_set * bset,unsigned first,unsigned n,int * signs)11413 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
11414 	unsigned first, unsigned n, int *signs)
11415 {
11416 	isl_vec *bound = NULL;
11417 	struct isl_tab *tab = NULL;
11418 	struct isl_tab_undo *snap;
11419 	int i;
11420 	isl_size total;
11421 
11422 	total = isl_basic_set_dim(bset, isl_dim_all);
11423 	if (total < 0 || !signs)
11424 		return isl_stat_error;
11425 
11426 	bound = isl_vec_alloc(bset->ctx, 1 + total);
11427 	tab = isl_tab_from_basic_set(bset, 0);
11428 	if (!bound || !tab)
11429 		goto error;
11430 
11431 	isl_seq_clr(bound->el, bound->size);
11432 	isl_int_set_si(bound->el[0], -1);
11433 
11434 	snap = isl_tab_snap(tab);
11435 	for (i = 0; i < n; ++i) {
11436 		int empty;
11437 
11438 		isl_int_set_si(bound->el[1 + first + i], -1);
11439 		if (isl_tab_add_ineq(tab, bound->el) < 0)
11440 			goto error;
11441 		empty = tab->empty;
11442 		isl_int_set_si(bound->el[1 + first + i], 0);
11443 		if (isl_tab_rollback(tab, snap) < 0)
11444 			goto error;
11445 
11446 		if (empty) {
11447 			signs[i] = 1;
11448 			continue;
11449 		}
11450 
11451 		isl_int_set_si(bound->el[1 + first + i], 1);
11452 		if (isl_tab_add_ineq(tab, bound->el) < 0)
11453 			goto error;
11454 		empty = tab->empty;
11455 		isl_int_set_si(bound->el[1 + first + i], 0);
11456 		if (isl_tab_rollback(tab, snap) < 0)
11457 			goto error;
11458 
11459 		signs[i] = empty ? -1 : 0;
11460 	}
11461 
11462 	isl_tab_free(tab);
11463 	isl_vec_free(bound);
11464 	return isl_stat_ok;
11465 error:
11466 	isl_tab_free(tab);
11467 	isl_vec_free(bound);
11468 	return isl_stat_error;
11469 }
11470 
isl_basic_set_dims_get_sign(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n,int * signs)11471 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
11472 	enum isl_dim_type type, unsigned first, unsigned n, int *signs)
11473 {
11474 	if (!bset || !signs)
11475 		return isl_stat_error;
11476 	if (isl_basic_set_check_range(bset, type, first, n) < 0)
11477 		return isl_stat_error;
11478 
11479 	first += pos(bset->dim, type) - 1;
11480 	return isl_basic_set_vars_get_sign(bset, first, n, signs);
11481 }
11482 
11483 /* Is it possible for the integer division "div" to depend (possibly
11484  * indirectly) on any output dimensions?
11485  *
11486  * If the div is undefined, then we conservatively assume that it
11487  * may depend on them.
11488  * Otherwise, we check if it actually depends on them or on any integer
11489  * divisions that may depend on them.
11490  */
div_may_involve_output(__isl_keep isl_basic_map * bmap,int div)11491 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
11492 {
11493 	int i;
11494 	isl_size n_out, n_div;
11495 	unsigned o_out, o_div;
11496 
11497 	if (isl_int_is_zero(bmap->div[div][0]))
11498 		return isl_bool_true;
11499 
11500 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11501 	if (n_out < 0)
11502 		return isl_bool_error;
11503 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11504 
11505 	if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
11506 		return isl_bool_true;
11507 
11508 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11509 	if (n_div < 0)
11510 		return isl_bool_error;
11511 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11512 
11513 	for (i = 0; i < n_div; ++i) {
11514 		isl_bool may_involve;
11515 
11516 		if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
11517 			continue;
11518 		may_involve = div_may_involve_output(bmap, i);
11519 		if (may_involve < 0 || may_involve)
11520 			return may_involve;
11521 	}
11522 
11523 	return isl_bool_false;
11524 }
11525 
11526 /* Return the first integer division of "bmap" in the range
11527  * [first, first + n[ that may depend on any output dimensions and
11528  * that has a non-zero coefficient in "c" (where the first coefficient
11529  * in "c" corresponds to integer division "first").
11530  */
first_div_may_involve_output(__isl_keep isl_basic_map * bmap,isl_int * c,int first,int n)11531 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
11532 	isl_int *c, int first, int n)
11533 {
11534 	int k;
11535 
11536 	if (!bmap)
11537 		return -1;
11538 
11539 	for (k = first; k < first + n; ++k) {
11540 		isl_bool may_involve;
11541 
11542 		if (isl_int_is_zero(c[k]))
11543 			continue;
11544 		may_involve = div_may_involve_output(bmap, k);
11545 		if (may_involve < 0)
11546 			return -1;
11547 		if (may_involve)
11548 			return k;
11549 	}
11550 
11551 	return first + n;
11552 }
11553 
11554 /* Look for a pair of inequality constraints in "bmap" of the form
11555  *
11556  *	-l + i >= 0		or		i >= l
11557  * and
11558  *	n + l - i >= 0		or		i <= l + n
11559  *
11560  * with n < "m" and i the output dimension at position "pos".
11561  * (Note that n >= 0 as otherwise the two constraints would conflict.)
11562  * Furthermore, "l" is only allowed to involve parameters, input dimensions
11563  * and earlier output dimensions, as well as integer divisions that do
11564  * not involve any of the output dimensions.
11565  *
11566  * Return the index of the first inequality constraint or bmap->n_ineq
11567  * if no such pair can be found.
11568  */
find_modulo_constraint_pair(__isl_keep isl_basic_map * bmap,int pos,isl_int m)11569 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
11570 	int pos, isl_int m)
11571 {
11572 	int i, j;
11573 	isl_ctx *ctx;
11574 	isl_size total;
11575 	isl_size n_div, n_out;
11576 	unsigned o_div, o_out;
11577 	int less;
11578 
11579 	total = isl_basic_map_dim(bmap, isl_dim_all);
11580 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11581 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11582 	if (total < 0 || n_out < 0 || n_div < 0)
11583 		return -1;
11584 
11585 	ctx = isl_basic_map_get_ctx(bmap);
11586 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11587 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11588 	for (i = 0; i < bmap->n_ineq; ++i) {
11589 		if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
11590 			continue;
11591 		if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
11592 					n_out - (pos + 1)) != -1)
11593 			continue;
11594 		if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11595 						0, n_div) < n_div)
11596 			continue;
11597 		for (j = i + 1; j < bmap->n_ineq; ++j) {
11598 			if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11599 					    ctx->one))
11600 				continue;
11601 			if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11602 					    bmap->ineq[j] + 1, total))
11603 				continue;
11604 			break;
11605 		}
11606 		if (j >= bmap->n_ineq)
11607 			continue;
11608 		isl_int_add(bmap->ineq[i][0],
11609 			    bmap->ineq[i][0], bmap->ineq[j][0]);
11610 		less = isl_int_abs_lt(bmap->ineq[i][0], m);
11611 		isl_int_sub(bmap->ineq[i][0],
11612 			    bmap->ineq[i][0], bmap->ineq[j][0]);
11613 		if (!less)
11614 			continue;
11615 		if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11616 			return i;
11617 		else
11618 			return j;
11619 	}
11620 
11621 	return bmap->n_ineq;
11622 }
11623 
11624 /* Return the index of the equality of "bmap" that defines
11625  * the output dimension "pos" in terms of earlier dimensions.
11626  * The equality may also involve integer divisions, as long
11627  * as those integer divisions are defined in terms of
11628  * parameters or input dimensions.
11629  * In this case, *div is set to the number of integer divisions and
11630  * *ineq is set to the number of inequality constraints (provided
11631  * div and ineq are not NULL).
11632  *
11633  * The equality may also involve a single integer division involving
11634  * the output dimensions (typically only output dimension "pos") as
11635  * long as the coefficient of output dimension "pos" is 1 or -1 and
11636  * there is a pair of constraints i >= l and i <= l + n, with i referring
11637  * to output dimension "pos", l an expression involving only earlier
11638  * dimensions and n smaller than the coefficient of the integer division
11639  * in the equality.  In this case, the output dimension can be defined
11640  * in terms of a modulo expression that does not involve the integer division.
11641  * *div is then set to this single integer division and
11642  * *ineq is set to the index of constraint i >= l.
11643  *
11644  * Return bmap->n_eq if there is no such equality.
11645  * Return -1 on error.
11646  */
isl_basic_map_output_defining_equality(__isl_keep isl_basic_map * bmap,int pos,int * div,int * ineq)11647 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11648 	int pos, int *div, int *ineq)
11649 {
11650 	int j, k, l;
11651 	isl_size n_div, n_out;
11652 	unsigned o_div, o_out;
11653 
11654 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11655 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11656 	if (n_out < 0 || n_div < 0)
11657 		return -1;
11658 
11659 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11660 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11661 
11662 	if (ineq)
11663 		*ineq = bmap->n_ineq;
11664 	if (div)
11665 		*div = n_div;
11666 	for (j = 0; j < bmap->n_eq; ++j) {
11667 		if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11668 			continue;
11669 		if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11670 					n_out - (pos + 1)) != -1)
11671 			continue;
11672 		k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11673 						0, n_div);
11674 		if (k >= n_div)
11675 			return j;
11676 		if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11677 		    !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11678 			continue;
11679 		if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11680 						k + 1, n_div - (k+1)) < n_div)
11681 			continue;
11682 		l = find_modulo_constraint_pair(bmap, pos,
11683 						bmap->eq[j][o_div + k]);
11684 		if (l < 0)
11685 			return -1;
11686 		if (l >= bmap->n_ineq)
11687 			continue;
11688 		if (div)
11689 			*div = k;
11690 		if (ineq)
11691 			*ineq = l;
11692 		return j;
11693 	}
11694 
11695 	return bmap->n_eq;
11696 }
11697 
11698 /* Check if the given basic map is obviously single-valued.
11699  * In particular, for each output dimension, check that there is
11700  * an equality that defines the output dimension in terms of
11701  * earlier dimensions.
11702  */
isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map * bmap)11703 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11704 {
11705 	int i;
11706 	isl_size n_out;
11707 
11708 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11709 	if (n_out < 0)
11710 		return isl_bool_error;
11711 
11712 	for (i = 0; i < n_out; ++i) {
11713 		int eq;
11714 
11715 		eq = isl_basic_map_output_defining_equality(bmap, i,
11716 							    NULL, NULL);
11717 		if (eq < 0)
11718 			return isl_bool_error;
11719 		if (eq >= bmap->n_eq)
11720 			return isl_bool_false;
11721 	}
11722 
11723 	return isl_bool_true;
11724 }
11725 
11726 /* Check if the given basic map is single-valued.
11727  * We simply compute
11728  *
11729  *	M \circ M^-1
11730  *
11731  * and check if the result is a subset of the identity mapping.
11732  */
isl_basic_map_is_single_valued(__isl_keep isl_basic_map * bmap)11733 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11734 {
11735 	isl_space *space;
11736 	isl_basic_map *test;
11737 	isl_basic_map *id;
11738 	isl_bool sv;
11739 
11740 	sv = isl_basic_map_plain_is_single_valued(bmap);
11741 	if (sv < 0 || sv)
11742 		return sv;
11743 
11744 	test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11745 	test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11746 
11747 	space = isl_basic_map_get_space(bmap);
11748 	space = isl_space_map_from_set(isl_space_range(space));
11749 	id = isl_basic_map_identity(space);
11750 
11751 	sv = isl_basic_map_is_subset(test, id);
11752 
11753 	isl_basic_map_free(test);
11754 	isl_basic_map_free(id);
11755 
11756 	return sv;
11757 }
11758 
11759 /* Check if the given map is obviously single-valued.
11760  */
isl_map_plain_is_single_valued(__isl_keep isl_map * map)11761 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11762 {
11763 	if (!map)
11764 		return isl_bool_error;
11765 	if (map->n == 0)
11766 		return isl_bool_true;
11767 	if (map->n >= 2)
11768 		return isl_bool_false;
11769 
11770 	return isl_basic_map_plain_is_single_valued(map->p[0]);
11771 }
11772 
11773 /* Check if the given map is single-valued.
11774  * We simply compute
11775  *
11776  *	M \circ M^-1
11777  *
11778  * and check if the result is a subset of the identity mapping.
11779  */
isl_map_is_single_valued(__isl_keep isl_map * map)11780 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11781 {
11782 	isl_space *space;
11783 	isl_map *test;
11784 	isl_map *id;
11785 	isl_bool sv;
11786 
11787 	sv = isl_map_plain_is_single_valued(map);
11788 	if (sv < 0 || sv)
11789 		return sv;
11790 
11791 	test = isl_map_reverse(isl_map_copy(map));
11792 	test = isl_map_apply_range(test, isl_map_copy(map));
11793 
11794 	space = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11795 	id = isl_map_identity(space);
11796 
11797 	sv = isl_map_is_subset(test, id);
11798 
11799 	isl_map_free(test);
11800 	isl_map_free(id);
11801 
11802 	return sv;
11803 }
11804 
isl_map_is_injective(__isl_keep isl_map * map)11805 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11806 {
11807 	isl_bool in;
11808 
11809 	map = isl_map_copy(map);
11810 	map = isl_map_reverse(map);
11811 	in = isl_map_is_single_valued(map);
11812 	isl_map_free(map);
11813 
11814 	return in;
11815 }
11816 
11817 /* Check if the given map is obviously injective.
11818  */
isl_map_plain_is_injective(__isl_keep isl_map * map)11819 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11820 {
11821 	isl_bool in;
11822 
11823 	map = isl_map_copy(map);
11824 	map = isl_map_reverse(map);
11825 	in = isl_map_plain_is_single_valued(map);
11826 	isl_map_free(map);
11827 
11828 	return in;
11829 }
11830 
isl_map_is_bijective(__isl_keep isl_map * map)11831 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11832 {
11833 	isl_bool sv;
11834 
11835 	sv = isl_map_is_single_valued(map);
11836 	if (sv < 0 || !sv)
11837 		return sv;
11838 
11839 	return isl_map_is_injective(map);
11840 }
11841 
isl_set_is_singleton(__isl_keep isl_set * set)11842 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11843 {
11844 	return isl_map_is_single_valued(set_to_map(set));
11845 }
11846 
11847 /* Does "map" only map elements to themselves?
11848  *
11849  * If the domain and range spaces are different, then "map"
11850  * is considered not to be an identity relation, even if it is empty.
11851  * Otherwise, construct the maximal identity relation and
11852  * check whether "map" is a subset of this relation.
11853  */
isl_map_is_identity(__isl_keep isl_map * map)11854 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11855 {
11856 	isl_map *id;
11857 	isl_bool equal, is_identity;
11858 
11859 	equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
11860 	if (equal < 0 || !equal)
11861 		return equal;
11862 
11863 	id = isl_map_identity(isl_map_get_space(map));
11864 	is_identity = isl_map_is_subset(map, id);
11865 	isl_map_free(id);
11866 
11867 	return is_identity;
11868 }
11869 
isl_map_is_translation(__isl_keep isl_map * map)11870 int isl_map_is_translation(__isl_keep isl_map *map)
11871 {
11872 	int ok;
11873 	isl_set *delta;
11874 
11875 	delta = isl_map_deltas(isl_map_copy(map));
11876 	ok = isl_set_is_singleton(delta);
11877 	isl_set_free(delta);
11878 
11879 	return ok;
11880 }
11881 
unique(isl_int * p,unsigned pos,unsigned len)11882 static int unique(isl_int *p, unsigned pos, unsigned len)
11883 {
11884 	if (isl_seq_first_non_zero(p, pos) != -1)
11885 		return 0;
11886 	if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11887 		return 0;
11888 	return 1;
11889 }
11890 
isl_basic_set_is_box(__isl_keep isl_basic_set * bset)11891 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11892 {
11893 	int i, j;
11894 	isl_size nvar, n_div;
11895 	unsigned ovar;
11896 
11897 	n_div = isl_basic_set_dim(bset, isl_dim_div);
11898 	if (n_div < 0)
11899 		return isl_bool_error;
11900 	if (n_div != 0)
11901 		return isl_bool_false;
11902 
11903 	nvar = isl_basic_set_dim(bset, isl_dim_set);
11904 	if (nvar < 0)
11905 		return isl_bool_error;
11906 	ovar = isl_space_offset(bset->dim, isl_dim_set);
11907 	for (j = 0; j < nvar; ++j) {
11908 		int lower = 0, upper = 0;
11909 		for (i = 0; i < bset->n_eq; ++i) {
11910 			if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11911 				continue;
11912 			if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11913 				return isl_bool_false;
11914 			break;
11915 		}
11916 		if (i < bset->n_eq)
11917 			continue;
11918 		for (i = 0; i < bset->n_ineq; ++i) {
11919 			if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11920 				continue;
11921 			if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11922 				return isl_bool_false;
11923 			if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11924 				lower = 1;
11925 			else
11926 				upper = 1;
11927 		}
11928 		if (!lower || !upper)
11929 			return isl_bool_false;
11930 	}
11931 
11932 	return isl_bool_true;
11933 }
11934 
isl_set_is_box(__isl_keep isl_set * set)11935 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11936 {
11937 	if (!set)
11938 		return isl_bool_error;
11939 	if (set->n != 1)
11940 		return isl_bool_false;
11941 
11942 	return isl_basic_set_is_box(set->p[0]);
11943 }
11944 
isl_basic_set_is_wrapping(__isl_keep isl_basic_set * bset)11945 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11946 {
11947 	if (!bset)
11948 		return isl_bool_error;
11949 
11950 	return isl_space_is_wrapping(bset->dim);
11951 }
11952 
isl_set_is_wrapping(__isl_keep isl_set * set)11953 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11954 {
11955 	if (!set)
11956 		return isl_bool_error;
11957 
11958 	return isl_space_is_wrapping(set->dim);
11959 }
11960 
11961 /* Modify the space of "map" through a call to "change".
11962  * If "can_change" is set (not NULL), then first call it to check
11963  * if the modification is allowed, printing the error message "cannot_change"
11964  * if it is not.
11965  */
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))11966 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11967 	isl_bool (*can_change)(__isl_keep isl_map *map),
11968 	const char *cannot_change,
11969 	__isl_give isl_space *(*change)(__isl_take isl_space *space))
11970 {
11971 	isl_bool ok;
11972 	isl_space *space;
11973 
11974 	if (!map)
11975 		return NULL;
11976 
11977 	ok = can_change ? can_change(map) : isl_bool_true;
11978 	if (ok < 0)
11979 		return isl_map_free(map);
11980 	if (!ok)
11981 		isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11982 			return isl_map_free(map));
11983 
11984 	space = change(isl_map_get_space(map));
11985 	map = isl_map_reset_space(map, space);
11986 
11987 	return map;
11988 }
11989 
11990 /* Is the domain of "map" a wrapped relation?
11991  */
isl_map_domain_is_wrapping(__isl_keep isl_map * map)11992 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11993 {
11994 	if (!map)
11995 		return isl_bool_error;
11996 
11997 	return isl_space_domain_is_wrapping(map->dim);
11998 }
11999 
12000 /* Does "map" have a wrapped relation in both domain and range?
12001  */
isl_map_is_product(__isl_keep isl_map * map)12002 isl_bool isl_map_is_product(__isl_keep isl_map *map)
12003 {
12004 	return isl_space_is_product(isl_map_peek_space(map));
12005 }
12006 
12007 /* Is the range of "map" a wrapped relation?
12008  */
isl_map_range_is_wrapping(__isl_keep isl_map * map)12009 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
12010 {
12011 	if (!map)
12012 		return isl_bool_error;
12013 
12014 	return isl_space_range_is_wrapping(map->dim);
12015 }
12016 
isl_basic_map_wrap(__isl_take isl_basic_map * bmap)12017 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
12018 {
12019 	isl_space *space;
12020 
12021 	space = isl_basic_map_take_space(bmap);
12022 	space = isl_space_wrap(space);
12023 	bmap = isl_basic_map_restore_space(bmap, space);
12024 
12025 	bmap = isl_basic_map_finalize(bmap);
12026 
12027 	return bset_from_bmap(bmap);
12028 }
12029 
12030 /* Given a map A -> B, return the set (A -> B).
12031  */
isl_map_wrap(__isl_take isl_map * map)12032 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
12033 {
12034 	return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
12035 }
12036 
isl_basic_set_unwrap(__isl_take isl_basic_set * bset)12037 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
12038 {
12039 	bset = isl_basic_set_cow(bset);
12040 	if (!bset)
12041 		return NULL;
12042 
12043 	bset->dim = isl_space_unwrap(bset->dim);
12044 	if (!bset->dim)
12045 		goto error;
12046 
12047 	bset = isl_basic_set_finalize(bset);
12048 
12049 	return bset_to_bmap(bset);
12050 error:
12051 	isl_basic_set_free(bset);
12052 	return NULL;
12053 }
12054 
12055 /* Given a set (A -> B), return the map A -> B.
12056  * Error out if "set" is not of the form (A -> B).
12057  */
isl_set_unwrap(__isl_take isl_set * set)12058 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
12059 {
12060 	return isl_map_change_space(set, &isl_set_is_wrapping,
12061 				    "not a wrapping set", &isl_space_unwrap);
12062 }
12063 
isl_basic_map_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)12064 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
12065 	enum isl_dim_type type)
12066 {
12067 	isl_space *space;
12068 
12069 	space = isl_basic_map_take_space(bmap);
12070 	space = isl_space_reset(space, type);
12071 	bmap = isl_basic_map_restore_space(bmap, space);
12072 
12073 	bmap = isl_basic_map_mark_final(bmap);
12074 
12075 	return bmap;
12076 }
12077 
isl_map_reset(__isl_take isl_map * map,enum isl_dim_type type)12078 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
12079 	enum isl_dim_type type)
12080 {
12081 	int i;
12082 	isl_space *space;
12083 
12084 	if (!map)
12085 		return NULL;
12086 
12087 	if (!isl_space_is_named_or_nested(map->dim, type))
12088 		return map;
12089 
12090 	map = isl_map_cow(map);
12091 	if (!map)
12092 		return NULL;
12093 
12094 	for (i = 0; i < map->n; ++i) {
12095 		map->p[i] = isl_basic_map_reset(map->p[i], type);
12096 		if (!map->p[i])
12097 			goto error;
12098 	}
12099 
12100 	space = isl_map_take_space(map);
12101 	space = isl_space_reset(space, type);
12102 	map = isl_map_restore_space(map, space);
12103 
12104 	return map;
12105 error:
12106 	isl_map_free(map);
12107 	return NULL;
12108 }
12109 
isl_basic_map_flatten(__isl_take isl_basic_map * bmap)12110 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
12111 {
12112 	isl_space *space;
12113 
12114 	space = isl_basic_map_take_space(bmap);
12115 	space = isl_space_flatten(space);
12116 	bmap = isl_basic_map_restore_space(bmap, space);
12117 
12118 	bmap = isl_basic_map_mark_final(bmap);
12119 
12120 	return bmap;
12121 }
12122 
isl_basic_set_flatten(__isl_take isl_basic_set * bset)12123 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
12124 {
12125 	return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
12126 }
12127 
isl_basic_map_flatten_domain(__isl_take isl_basic_map * bmap)12128 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
12129 	__isl_take isl_basic_map *bmap)
12130 {
12131 	isl_space *space;
12132 
12133 	space = isl_basic_map_take_space(bmap);
12134 	space = isl_space_flatten_domain(space);
12135 	bmap = isl_basic_map_restore_space(bmap, space);
12136 
12137 	bmap = isl_basic_map_mark_final(bmap);
12138 
12139 	return bmap;
12140 }
12141 
isl_basic_map_flatten_range(__isl_take isl_basic_map * bmap)12142 __isl_give isl_basic_map *isl_basic_map_flatten_range(
12143 	__isl_take isl_basic_map *bmap)
12144 {
12145 	isl_space *space;
12146 
12147 	space = isl_basic_map_take_space(bmap);
12148 	space = isl_space_flatten_range(space);
12149 	bmap = isl_basic_map_restore_space(bmap, space);
12150 
12151 	bmap = isl_basic_map_mark_final(bmap);
12152 
12153 	return bmap;
12154 }
12155 
12156 /* Remove any internal structure from the spaces of domain and range of "map".
12157  */
isl_map_flatten(__isl_take isl_map * map)12158 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
12159 {
12160 	if (!map)
12161 		return NULL;
12162 
12163 	if (!map->dim->nested[0] && !map->dim->nested[1])
12164 		return map;
12165 
12166 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
12167 }
12168 
isl_set_flatten(__isl_take isl_set * set)12169 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
12170 {
12171 	return set_from_map(isl_map_flatten(set_to_map(set)));
12172 }
12173 
isl_set_flatten_map(__isl_take isl_set * set)12174 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
12175 {
12176 	isl_space *space, *flat_space;
12177 	isl_map *map;
12178 
12179 	space = isl_set_get_space(set);
12180 	flat_space = isl_space_flatten(isl_space_copy(space));
12181 	map = isl_map_identity(isl_space_join(isl_space_reverse(space),
12182 						flat_space));
12183 	map = isl_map_intersect_domain(map, set);
12184 
12185 	return map;
12186 }
12187 
12188 /* Remove any internal structure from the space of the domain of "map".
12189  */
isl_map_flatten_domain(__isl_take isl_map * map)12190 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
12191 {
12192 	if (!map)
12193 		return NULL;
12194 
12195 	if (!map->dim->nested[0])
12196 		return map;
12197 
12198 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
12199 }
12200 
12201 /* Remove any internal structure from the space of the range of "map".
12202  */
isl_map_flatten_range(__isl_take isl_map * map)12203 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
12204 {
12205 	if (!map)
12206 		return NULL;
12207 
12208 	if (!map->dim->nested[1])
12209 		return map;
12210 
12211 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
12212 }
12213 
12214 /* Reorder the dimensions of "bmap" according to the given dim_map
12215  * and set the dimension specification to "space" and
12216  * perform Gaussian elimination on the result.
12217  */
isl_basic_map_realign(__isl_take isl_basic_map * bmap,__isl_take isl_space * space,__isl_take struct isl_dim_map * dim_map)12218 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
12219 	__isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
12220 {
12221 	isl_basic_map *res;
12222 	unsigned flags;
12223 	isl_size n_div;
12224 
12225 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
12226 	if (n_div < 0 || !space || !dim_map)
12227 		goto error;
12228 
12229 	flags = bmap->flags;
12230 	ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
12231 	ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
12232 	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
12233 	res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
12234 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
12235 	if (res)
12236 		res->flags = flags;
12237 	res = isl_basic_map_gauss(res, NULL);
12238 	res = isl_basic_map_finalize(res);
12239 	return res;
12240 error:
12241 	isl_dim_map_free(dim_map);
12242 	isl_basic_map_free(bmap);
12243 	isl_space_free(space);
12244 	return NULL;
12245 }
12246 
12247 /* Reorder the dimensions of "map" according to given reordering.
12248  */
isl_map_realign(__isl_take isl_map * map,__isl_take isl_reordering * r)12249 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
12250 	__isl_take isl_reordering *r)
12251 {
12252 	int i;
12253 	struct isl_dim_map *dim_map;
12254 
12255 	map = isl_map_cow(map);
12256 	dim_map = isl_dim_map_from_reordering(r);
12257 	if (!map || !r || !dim_map)
12258 		goto error;
12259 
12260 	for (i = 0; i < map->n; ++i) {
12261 		struct isl_dim_map *dim_map_i;
12262 		isl_space *space;
12263 
12264 		dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
12265 
12266 		space = isl_reordering_get_space(r);
12267 		map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
12268 
12269 		if (!map->p[i])
12270 			goto error;
12271 	}
12272 
12273 	map = isl_map_reset_space(map, isl_reordering_get_space(r));
12274 	map = isl_map_unmark_normalized(map);
12275 
12276 	isl_reordering_free(r);
12277 	isl_dim_map_free(dim_map);
12278 	return map;
12279 error:
12280 	isl_dim_map_free(dim_map);
12281 	isl_map_free(map);
12282 	isl_reordering_free(r);
12283 	return NULL;
12284 }
12285 
isl_set_realign(__isl_take isl_set * set,__isl_take isl_reordering * r)12286 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
12287 	__isl_take isl_reordering *r)
12288 {
12289 	return set_from_map(isl_map_realign(set_to_map(set), r));
12290 }
12291 
isl_map_align_params(__isl_take isl_map * map,__isl_take isl_space * model)12292 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
12293 	__isl_take isl_space *model)
12294 {
12295 	isl_ctx *ctx;
12296 	isl_bool aligned;
12297 
12298 	if (!map || !model)
12299 		goto error;
12300 
12301 	ctx = isl_space_get_ctx(model);
12302 	if (!isl_space_has_named_params(model))
12303 		isl_die(ctx, isl_error_invalid,
12304 			"model has unnamed parameters", goto error);
12305 	if (isl_map_check_named_params(map) < 0)
12306 		goto error;
12307 	aligned = isl_map_space_has_equal_params(map, model);
12308 	if (aligned < 0)
12309 		goto error;
12310 	if (!aligned) {
12311 		isl_reordering *exp;
12312 
12313 		exp = isl_parameter_alignment_reordering(map->dim, model);
12314 		exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
12315 		map = isl_map_realign(map, exp);
12316 	}
12317 
12318 	isl_space_free(model);
12319 	return map;
12320 error:
12321 	isl_space_free(model);
12322 	isl_map_free(map);
12323 	return NULL;
12324 }
12325 
isl_set_align_params(__isl_take isl_set * set,__isl_take isl_space * model)12326 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
12327 	__isl_take isl_space *model)
12328 {
12329 	return isl_map_align_params(set, model);
12330 }
12331 
12332 /* Align the parameters of "bmap" to those of "model", introducing
12333  * additional parameters if needed.
12334  */
isl_basic_map_align_params(__isl_take isl_basic_map * bmap,__isl_take isl_space * model)12335 __isl_give isl_basic_map *isl_basic_map_align_params(
12336 	__isl_take isl_basic_map *bmap, __isl_take isl_space *model)
12337 {
12338 	isl_ctx *ctx;
12339 	isl_bool equal_params;
12340 
12341 	if (!bmap || !model)
12342 		goto error;
12343 
12344 	ctx = isl_space_get_ctx(model);
12345 	if (!isl_space_has_named_params(model))
12346 		isl_die(ctx, isl_error_invalid,
12347 			"model has unnamed parameters", goto error);
12348 	if (isl_basic_map_check_named_params(bmap) < 0)
12349 		goto error;
12350 	equal_params = isl_space_has_equal_params(bmap->dim, model);
12351 	if (equal_params < 0)
12352 		goto error;
12353 	if (!equal_params) {
12354 		isl_reordering *exp;
12355 		struct isl_dim_map *dim_map;
12356 
12357 		exp = isl_parameter_alignment_reordering(bmap->dim, model);
12358 		exp = isl_reordering_extend_space(exp,
12359 					isl_basic_map_get_space(bmap));
12360 		dim_map = isl_dim_map_from_reordering(exp);
12361 		bmap = isl_basic_map_realign(bmap,
12362 				    isl_reordering_get_space(exp),
12363 				    isl_dim_map_extend(dim_map, bmap));
12364 		isl_reordering_free(exp);
12365 		isl_dim_map_free(dim_map);
12366 	}
12367 
12368 	isl_space_free(model);
12369 	return bmap;
12370 error:
12371 	isl_space_free(model);
12372 	isl_basic_map_free(bmap);
12373 	return NULL;
12374 }
12375 
12376 /* Do "bset" and "space" have the same parameters?
12377  */
isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set * bset,__isl_keep isl_space * space)12378 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
12379 	__isl_keep isl_space *space)
12380 {
12381 	isl_space *bset_space;
12382 
12383 	bset_space = isl_basic_set_peek_space(bset);
12384 	return isl_space_has_equal_params(bset_space, space);
12385 }
12386 
12387 /* Do "map" and "space" have the same parameters?
12388  */
isl_map_space_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_space * space)12389 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
12390 	__isl_keep isl_space *space)
12391 {
12392 	isl_space *map_space;
12393 
12394 	map_space = isl_map_peek_space(map);
12395 	return isl_space_has_equal_params(map_space, space);
12396 }
12397 
12398 /* Do "set" and "space" have the same parameters?
12399  */
isl_set_space_has_equal_params(__isl_keep isl_set * set,__isl_keep isl_space * space)12400 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
12401 	__isl_keep isl_space *space)
12402 {
12403 	return isl_map_space_has_equal_params(set_to_map(set), space);
12404 }
12405 
12406 /* Align the parameters of "bset" to those of "model", introducing
12407  * additional parameters if needed.
12408  */
isl_basic_set_align_params(__isl_take isl_basic_set * bset,__isl_take isl_space * model)12409 __isl_give isl_basic_set *isl_basic_set_align_params(
12410 	__isl_take isl_basic_set *bset, __isl_take isl_space *model)
12411 {
12412 	return isl_basic_map_align_params(bset, model);
12413 }
12414 
12415 /* Drop all parameters not referenced by "map".
12416  */
isl_map_drop_unused_params(__isl_take isl_map * map)12417 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
12418 {
12419 	int i;
12420 	isl_size n;
12421 
12422 	n = isl_map_dim(map, isl_dim_param);
12423 	if (isl_map_check_named_params(map) < 0 || n < 0)
12424 		return isl_map_free(map);
12425 
12426 	for (i = n - 1; i >= 0; i--) {
12427 		isl_bool involves;
12428 
12429 		involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
12430 		if (involves < 0)
12431 			return isl_map_free(map);
12432 		if (!involves)
12433 			map = isl_map_project_out(map, isl_dim_param, i, 1);
12434 	}
12435 
12436 	return map;
12437 }
12438 
12439 /* Drop all parameters not referenced by "set".
12440  */
isl_set_drop_unused_params(__isl_take isl_set * set)12441 __isl_give isl_set *isl_set_drop_unused_params(
12442 	__isl_take isl_set *set)
12443 {
12444 	return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
12445 }
12446 
12447 /* Drop all parameters not referenced by "bmap".
12448  */
isl_basic_map_drop_unused_params(__isl_take isl_basic_map * bmap)12449 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
12450 	__isl_take isl_basic_map *bmap)
12451 {
12452 	isl_size nparam;
12453 	int i;
12454 
12455 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
12456 	if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)
12457 		return isl_basic_map_free(bmap);
12458 
12459 	for (i = nparam - 1; i >= 0; i--) {
12460 		isl_bool involves;
12461 
12462 		involves = isl_basic_map_involves_dims(bmap,
12463 							isl_dim_param, i, 1);
12464 		if (involves < 0)
12465 			return isl_basic_map_free(bmap);
12466 		if (!involves)
12467 			bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
12468 	}
12469 
12470 	return bmap;
12471 }
12472 
12473 /* Drop all parameters not referenced by "bset".
12474  */
isl_basic_set_drop_unused_params(__isl_take isl_basic_set * bset)12475 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
12476 	__isl_take isl_basic_set *bset)
12477 {
12478 	return bset_from_bmap(isl_basic_map_drop_unused_params(
12479 							bset_to_bmap(bset)));
12480 }
12481 
12482 /* Given a tuple of identifiers "tuple" in a space that corresponds
12483  * to that of "set", if any of those identifiers appear as parameters
12484  * in "set", then equate those parameters with the corresponding
12485  * set dimensions and project out the parameters.
12486  * The result therefore has no such parameters.
12487  */
equate_params(__isl_take isl_set * set,__isl_keep isl_multi_id * tuple)12488 static __isl_give isl_set *equate_params(__isl_take isl_set *set,
12489 	__isl_keep isl_multi_id *tuple)
12490 {
12491 	int i;
12492 	isl_size n;
12493 	isl_space *set_space, *tuple_space;
12494 
12495 	set_space = isl_set_peek_space(set);
12496 	tuple_space = isl_multi_id_peek_space(tuple);
12497 	if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
12498 		return isl_set_free(set);
12499 	n = isl_multi_id_size(tuple);
12500 	if (n < 0)
12501 		return isl_set_free(set);
12502 	for (i = 0; i < n; ++i) {
12503 		isl_id *id;
12504 		int pos;
12505 
12506 		id = isl_multi_id_get_at(tuple, i);
12507 		if (!id)
12508 			return isl_set_free(set);
12509 		pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
12510 		isl_id_free(id);
12511 		if (pos < 0)
12512 			continue;
12513 		set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
12514 		set = isl_set_project_out(set, isl_dim_param, pos, 1);
12515 	}
12516 	return set;
12517 }
12518 
12519 /* Bind the set dimensions of "set" to parameters with identifiers
12520  * specified by "tuple", living in the same space as "set".
12521  *
12522  * If no parameters with these identifiers appear in "set" already,
12523  * then the set dimensions are simply reinterpreted as parameters.
12524  * Otherwise, the parameters are first equated to the corresponding
12525  * set dimensions.
12526  */
isl_set_bind(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12527 __isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
12528 	__isl_take isl_multi_id *tuple)
12529 {
12530 	isl_space *space;
12531 
12532 	set = equate_params(set, tuple);
12533 	space = isl_set_get_space(set);
12534 	space = isl_space_bind_set(space, tuple);
12535 	isl_multi_id_free(tuple);
12536 	set = isl_set_reset_space(set, space);
12537 
12538 	return set;
12539 }
12540 
12541 /* Given a tuple of identifiers "tuple" in a space that corresponds
12542  * to the domain of "map", if any of those identifiers appear as parameters
12543  * in "map", then equate those parameters with the corresponding
12544  * input dimensions and project out the parameters.
12545  * The result therefore has no such parameters.
12546  */
map_equate_params(__isl_take isl_map * map,__isl_keep isl_multi_id * tuple)12547 static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
12548 	__isl_keep isl_multi_id *tuple)
12549 {
12550 	int i;
12551 	isl_size n;
12552 	isl_space *map_space, *tuple_space;
12553 
12554 	map_space = isl_map_peek_space(map);
12555 	tuple_space = isl_multi_id_peek_space(tuple);
12556 	if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
12557 		return isl_map_free(map);
12558 	n = isl_multi_id_size(tuple);
12559 	if (n < 0)
12560 		return isl_map_free(map);
12561 	for (i = 0; i < n; ++i) {
12562 		isl_id *id;
12563 		int pos;
12564 
12565 		id = isl_multi_id_get_at(tuple, i);
12566 		if (!id)
12567 			return isl_map_free(map);
12568 		pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
12569 		isl_id_free(id);
12570 		if (pos < 0)
12571 			continue;
12572 		map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
12573 		map = isl_map_project_out(map, isl_dim_param, pos, 1);
12574 	}
12575 	return map;
12576 }
12577 
12578 /* Bind the input dimensions of "map" to parameters with identifiers
12579  * specified by "tuple", living in the domain space of "map".
12580  *
12581  * If no parameters with these identifiers appear in "map" already,
12582  * then the input dimensions are simply reinterpreted as parameters.
12583  * Otherwise, the parameters are first equated to the corresponding
12584  * input dimensions.
12585  */
isl_map_bind_domain(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12586 __isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
12587 	__isl_take isl_multi_id *tuple)
12588 {
12589 	isl_space *space;
12590 	isl_set *set;
12591 
12592 	map = map_equate_params(map, tuple);
12593 	space = isl_map_get_space(map);
12594 	space = isl_space_bind_map_domain(space, tuple);
12595 	isl_multi_id_free(tuple);
12596 	set = set_from_map(isl_map_reset_space(map, space));
12597 
12598 	return set;
12599 }
12600 
12601 /* Bind the output dimensions of "map" to parameters with identifiers
12602  * specified by "tuple", living in the range space of "map".
12603  *
12604  * Since binding is more easily implemented on the domain,
12605  * bind the input dimensions of the inverse of "map".
12606  */
isl_map_bind_range(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12607 __isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
12608 	__isl_take isl_multi_id *tuple)
12609 {
12610 	return isl_map_bind_domain(isl_map_reverse(map), tuple);
12611 }
12612 
12613 /* Insert a domain corresponding to "tuple"
12614  * into the nullary or unary relation "set".
12615  * The result has an extra initial tuple and is therefore
12616  * either a unary or binary relation.
12617  * Any parameters with identifiers in "tuple" are reinterpreted
12618  * as the corresponding domain dimensions.
12619  */
unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12620 static __isl_give isl_map *unbind_params_insert_domain(
12621 	__isl_take isl_set *set, __isl_take isl_multi_id *tuple)
12622 {
12623 	isl_space *space;
12624 	isl_reordering *r;
12625 
12626 	space = isl_set_peek_space(set);
12627 	r = isl_reordering_unbind_params_insert_domain(space, tuple);
12628 	isl_multi_id_free(tuple);
12629 
12630 	return isl_map_realign(set_to_map(set), r);
12631 }
12632 
12633 /* Construct a set with "tuple" as domain from the parameter domain "set".
12634  * Any parameters with identifiers in "tuple" are reinterpreted
12635  * as the corresponding set dimensions.
12636  */
isl_set_unbind_params(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12637 __isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
12638 	__isl_take isl_multi_id *tuple)
12639 {
12640 	isl_bool is_params;
12641 
12642 	is_params = isl_set_is_params(set);
12643 	if (is_params < 0)
12644 		set = isl_set_free(set);
12645 	else if (!is_params)
12646 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
12647 			"expecting parameter domain", set = isl_set_free(set));
12648 	return set_from_map(unbind_params_insert_domain(set, tuple));
12649 }
12650 
12651 /* Check that "set" is a proper set, i.e., that it is not a parameter domain.
12652  */
isl_set_check_is_set(__isl_keep isl_set * set)12653 static isl_stat isl_set_check_is_set(__isl_keep isl_set *set)
12654 {
12655 	isl_bool is_params;
12656 
12657 	is_params = isl_set_is_params(set);
12658 	if (is_params < 0)
12659 		return isl_stat_error;
12660 	else if (is_params)
12661 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
12662 			"expecting proper set", return isl_stat_error);
12663 
12664 	return isl_stat_ok;
12665 }
12666 
12667 /* Construct a map with "domain" as domain and "set" as range.
12668  * Any parameters with identifiers in "domain" are reinterpreted
12669  * as the corresponding domain dimensions.
12670  */
isl_set_unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * domain)12671 __isl_give isl_map *isl_set_unbind_params_insert_domain(
12672 	__isl_take isl_set *set, __isl_take isl_multi_id *domain)
12673 {
12674 	if (isl_set_check_is_set(set) < 0)
12675 		set = isl_set_free(set);
12676 	return unbind_params_insert_domain(set, domain);
12677 }
12678 
12679 /* Construct a map with "domain" as domain and "set" as range.
12680  */
isl_set_insert_domain(__isl_take isl_set * set,__isl_take isl_space * domain)12681 __isl_give isl_map *isl_set_insert_domain(__isl_take isl_set *set,
12682 	__isl_take isl_space *domain)
12683 {
12684 	isl_size dim;
12685 	isl_space *space;
12686 	isl_map *map;
12687 
12688 	if (isl_set_check_is_set(set) < 0 || isl_space_check_is_set(domain) < 0)
12689 		domain = isl_space_free(domain);
12690 	dim = isl_space_dim(domain, isl_dim_set);
12691 	if (dim < 0)
12692 		domain = isl_space_free(domain);
12693 	space = isl_set_get_space(set);
12694 	domain = isl_space_replace_params(domain, space);
12695 	space = isl_space_map_from_domain_and_range(domain, space);
12696 
12697 	map = isl_map_from_range(set);
12698 	map = isl_map_add_dims(map, isl_dim_in, dim);
12699 	map = isl_map_reset_space(map, space);
12700 
12701 	return map;
12702 }
12703 
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)12704 __isl_give isl_mat *isl_basic_map_equalities_matrix(
12705 		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12706 		enum isl_dim_type c2, enum isl_dim_type c3,
12707 		enum isl_dim_type c4, enum isl_dim_type c5)
12708 {
12709 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12710 	struct isl_mat *mat;
12711 	int i, j, k;
12712 	int pos;
12713 	isl_size total;
12714 
12715 	total = isl_basic_map_dim(bmap, isl_dim_all);
12716 	if (total < 0)
12717 		return NULL;
12718 	mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
12719 	if (!mat)
12720 		return NULL;
12721 	for (i = 0; i < bmap->n_eq; ++i)
12722 		for (j = 0, pos = 0; j < 5; ++j) {
12723 			int off = isl_basic_map_offset(bmap, c[j]);
12724 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12725 			if (dim < 0)
12726 				return isl_mat_free(mat);
12727 			for (k = 0; k < dim; ++k) {
12728 				isl_int_set(mat->row[i][pos],
12729 					    bmap->eq[i][off + k]);
12730 				++pos;
12731 			}
12732 		}
12733 
12734 	return mat;
12735 }
12736 
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)12737 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
12738 		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12739 		enum isl_dim_type c2, enum isl_dim_type c3,
12740 		enum isl_dim_type c4, enum isl_dim_type c5)
12741 {
12742 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12743 	struct isl_mat *mat;
12744 	int i, j, k;
12745 	int pos;
12746 	isl_size total;
12747 
12748 	total = isl_basic_map_dim(bmap, isl_dim_all);
12749 	if (total < 0)
12750 		return NULL;
12751 	mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
12752 	if (!mat)
12753 		return NULL;
12754 	for (i = 0; i < bmap->n_ineq; ++i)
12755 		for (j = 0, pos = 0; j < 5; ++j) {
12756 			int off = isl_basic_map_offset(bmap, c[j]);
12757 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12758 			if (dim < 0)
12759 				return isl_mat_free(mat);
12760 			for (k = 0; k < dim; ++k) {
12761 				isl_int_set(mat->row[i][pos],
12762 					    bmap->ineq[i][off + k]);
12763 				++pos;
12764 			}
12765 		}
12766 
12767 	return mat;
12768 }
12769 
isl_basic_map_from_constraint_matrices(__isl_take isl_space * space,__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)12770 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
12771 	__isl_take isl_space *space,
12772 	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12773 	enum isl_dim_type c2, enum isl_dim_type c3,
12774 	enum isl_dim_type c4, enum isl_dim_type c5)
12775 {
12776 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12777 	isl_basic_map *bmap = NULL;
12778 	isl_size dim;
12779 	unsigned total;
12780 	unsigned extra;
12781 	int i, j, k, l;
12782 	int pos;
12783 
12784 	dim = isl_space_dim(space, isl_dim_all);
12785 	if (dim < 0 || !eq || !ineq)
12786 		goto error;
12787 
12788 	if (eq->n_col != ineq->n_col)
12789 		isl_die(space->ctx, isl_error_invalid,
12790 			"equalities and inequalities matrices should have "
12791 			"same number of columns", goto error);
12792 
12793 	total = 1 + dim;
12794 
12795 	if (eq->n_col < total)
12796 		isl_die(space->ctx, isl_error_invalid,
12797 			"number of columns too small", goto error);
12798 
12799 	extra = eq->n_col - total;
12800 
12801 	bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
12802 				       eq->n_row, ineq->n_row);
12803 	if (!bmap)
12804 		goto error;
12805 	for (i = 0; i < extra; ++i) {
12806 		k = isl_basic_map_alloc_div(bmap);
12807 		if (k < 0)
12808 			goto error;
12809 		isl_int_set_si(bmap->div[k][0], 0);
12810 	}
12811 	for (i = 0; i < eq->n_row; ++i) {
12812 		l = isl_basic_map_alloc_equality(bmap);
12813 		if (l < 0)
12814 			goto error;
12815 		for (j = 0, pos = 0; j < 5; ++j) {
12816 			int off = isl_basic_map_offset(bmap, c[j]);
12817 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12818 			if (dim < 0)
12819 				goto error;
12820 			for (k = 0; k < dim; ++k) {
12821 				isl_int_set(bmap->eq[l][off + k],
12822 					    eq->row[i][pos]);
12823 				++pos;
12824 			}
12825 		}
12826 	}
12827 	for (i = 0; i < ineq->n_row; ++i) {
12828 		l = isl_basic_map_alloc_inequality(bmap);
12829 		if (l < 0)
12830 			goto error;
12831 		for (j = 0, pos = 0; j < 5; ++j) {
12832 			int off = isl_basic_map_offset(bmap, c[j]);
12833 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12834 			if (dim < 0)
12835 				goto error;
12836 			for (k = 0; k < dim; ++k) {
12837 				isl_int_set(bmap->ineq[l][off + k],
12838 					    ineq->row[i][pos]);
12839 				++pos;
12840 			}
12841 		}
12842 	}
12843 
12844 	isl_space_free(space);
12845 	isl_mat_free(eq);
12846 	isl_mat_free(ineq);
12847 
12848 	bmap = isl_basic_map_simplify(bmap);
12849 	return isl_basic_map_finalize(bmap);
12850 error:
12851 	isl_space_free(space);
12852 	isl_mat_free(eq);
12853 	isl_mat_free(ineq);
12854 	isl_basic_map_free(bmap);
12855 	return NULL;
12856 }
12857 
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)12858 __isl_give isl_mat *isl_basic_set_equalities_matrix(
12859 	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12860 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12861 {
12862 	return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12863 						c1, c2, c3, c4, isl_dim_in);
12864 }
12865 
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)12866 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12867 	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12868 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12869 {
12870 	return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12871 						 c1, c2, c3, c4, isl_dim_in);
12872 }
12873 
isl_basic_set_from_constraint_matrices(__isl_take isl_space * space,__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)12874 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12875 	__isl_take isl_space *space,
12876 	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12877 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12878 {
12879 	isl_basic_map *bmap;
12880 	bmap = isl_basic_map_from_constraint_matrices(space, eq, ineq,
12881 						   c1, c2, c3, c4, isl_dim_in);
12882 	return bset_from_bmap(bmap);
12883 }
12884 
isl_basic_map_can_zip(__isl_keep isl_basic_map * bmap)12885 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12886 {
12887 	if (!bmap)
12888 		return isl_bool_error;
12889 
12890 	return isl_space_can_zip(bmap->dim);
12891 }
12892 
isl_map_can_zip(__isl_keep isl_map * map)12893 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12894 {
12895 	if (!map)
12896 		return isl_bool_error;
12897 
12898 	return isl_space_can_zip(map->dim);
12899 }
12900 
12901 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12902  * (A -> C) -> (B -> D).
12903  */
isl_basic_map_zip(__isl_take isl_basic_map * bmap)12904 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12905 {
12906 	unsigned pos;
12907 	isl_size n_in;
12908 	isl_size n1;
12909 	isl_size n2;
12910 
12911 	if (!bmap)
12912 		return NULL;
12913 
12914 	if (!isl_basic_map_can_zip(bmap))
12915 		isl_die(bmap->ctx, isl_error_invalid,
12916 			"basic map cannot be zipped", goto error);
12917 	n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12918 	n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12919 	n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12920 	if (n_in < 0 || n1 < 0 || n2 < 0)
12921 		return isl_basic_map_free(bmap);
12922 	pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
12923 	bmap = isl_basic_map_cow(bmap);
12924 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12925 	if (!bmap)
12926 		return NULL;
12927 	bmap->dim = isl_space_zip(bmap->dim);
12928 	if (!bmap->dim)
12929 		goto error;
12930 	bmap = isl_basic_map_mark_final(bmap);
12931 	return bmap;
12932 error:
12933 	isl_basic_map_free(bmap);
12934 	return NULL;
12935 }
12936 
12937 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12938  * (A -> C) -> (B -> D).
12939  */
isl_map_zip(__isl_take isl_map * map)12940 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12941 {
12942 	if (!map)
12943 		return NULL;
12944 
12945 	if (!isl_map_can_zip(map))
12946 		isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12947 			goto error);
12948 
12949 	return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);
12950 error:
12951 	isl_map_free(map);
12952 	return NULL;
12953 }
12954 
12955 /* Can we apply isl_basic_map_curry to "bmap"?
12956  * That is, does it have a nested relation in its domain?
12957  */
isl_basic_map_can_curry(__isl_keep isl_basic_map * bmap)12958 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12959 {
12960 	if (!bmap)
12961 		return isl_bool_error;
12962 
12963 	return isl_space_can_curry(bmap->dim);
12964 }
12965 
12966 /* Can we apply isl_map_curry to "map"?
12967  * That is, does it have a nested relation in its domain?
12968  */
isl_map_can_curry(__isl_keep isl_map * map)12969 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12970 {
12971 	if (!map)
12972 		return isl_bool_error;
12973 
12974 	return isl_space_can_curry(map->dim);
12975 }
12976 
12977 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12978  * A -> (B -> C).
12979  */
isl_basic_map_curry(__isl_take isl_basic_map * bmap)12980 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12981 {
12982 
12983 	if (!bmap)
12984 		return NULL;
12985 
12986 	if (!isl_basic_map_can_curry(bmap))
12987 		isl_die(bmap->ctx, isl_error_invalid,
12988 			"basic map cannot be curried", goto error);
12989 	bmap = isl_basic_map_cow(bmap);
12990 	if (!bmap)
12991 		return NULL;
12992 	bmap->dim = isl_space_curry(bmap->dim);
12993 	if (!bmap->dim)
12994 		goto error;
12995 	bmap = isl_basic_map_mark_final(bmap);
12996 	return bmap;
12997 error:
12998 	isl_basic_map_free(bmap);
12999 	return NULL;
13000 }
13001 
13002 /* Given a map (A -> B) -> C, return the corresponding map
13003  * A -> (B -> C).
13004  */
isl_map_curry(__isl_take isl_map * map)13005 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
13006 {
13007 	return isl_map_change_space(map, &isl_map_can_curry,
13008 				    "map cannot be curried", &isl_space_curry);
13009 }
13010 
13011 /* Can isl_map_range_curry be applied to "map"?
13012  * That is, does it have a nested relation in its range,
13013  * the domain of which is itself a nested relation?
13014  */
isl_map_can_range_curry(__isl_keep isl_map * map)13015 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
13016 {
13017 	if (!map)
13018 		return isl_bool_error;
13019 
13020 	return isl_space_can_range_curry(map->dim);
13021 }
13022 
13023 /* Given a map A -> ((B -> C) -> D), return the corresponding map
13024  * A -> (B -> (C -> D)).
13025  */
isl_map_range_curry(__isl_take isl_map * map)13026 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
13027 {
13028 	return isl_map_change_space(map, &isl_map_can_range_curry,
13029 				    "map range cannot be curried",
13030 				    &isl_space_range_curry);
13031 }
13032 
13033 /* Can we apply isl_basic_map_uncurry to "bmap"?
13034  * That is, does it have a nested relation in its domain?
13035  */
isl_basic_map_can_uncurry(__isl_keep isl_basic_map * bmap)13036 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
13037 {
13038 	if (!bmap)
13039 		return isl_bool_error;
13040 
13041 	return isl_space_can_uncurry(bmap->dim);
13042 }
13043 
13044 /* Can we apply isl_map_uncurry to "map"?
13045  * That is, does it have a nested relation in its domain?
13046  */
isl_map_can_uncurry(__isl_keep isl_map * map)13047 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
13048 {
13049 	if (!map)
13050 		return isl_bool_error;
13051 
13052 	return isl_space_can_uncurry(map->dim);
13053 }
13054 
13055 /* Given a basic map A -> (B -> C), return the corresponding basic map
13056  * (A -> B) -> C.
13057  */
isl_basic_map_uncurry(__isl_take isl_basic_map * bmap)13058 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
13059 {
13060 
13061 	if (!bmap)
13062 		return NULL;
13063 
13064 	if (!isl_basic_map_can_uncurry(bmap))
13065 		isl_die(bmap->ctx, isl_error_invalid,
13066 			"basic map cannot be uncurried",
13067 			return isl_basic_map_free(bmap));
13068 	bmap = isl_basic_map_cow(bmap);
13069 	if (!bmap)
13070 		return NULL;
13071 	bmap->dim = isl_space_uncurry(bmap->dim);
13072 	if (!bmap->dim)
13073 		return isl_basic_map_free(bmap);
13074 	bmap = isl_basic_map_mark_final(bmap);
13075 	return bmap;
13076 }
13077 
13078 /* Given a map A -> (B -> C), return the corresponding map
13079  * (A -> B) -> C.
13080  */
isl_map_uncurry(__isl_take isl_map * map)13081 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
13082 {
13083 	return isl_map_change_space(map, &isl_map_can_uncurry,
13084 				"map cannot be uncurried", &isl_space_uncurry);
13085 }
13086 
isl_set_equate(__isl_take isl_set * set,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13087 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
13088 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13089 {
13090 	return isl_map_equate(set, type1, pos1, type2, pos2);
13091 }
13092 
13093 /* Construct a basic map where the given dimensions are equal to each other.
13094  */
equator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13095 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
13096 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13097 {
13098 	isl_basic_map *bmap = NULL;
13099 	int i;
13100 	isl_size total;
13101 
13102 	total = isl_space_dim(space, isl_dim_all);
13103 	if (total < 0 ||
13104 	    isl_space_check_range(space, type1, pos1, 1) < 0 ||
13105 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13106 		goto error;
13107 
13108 	if (type1 == type2 && pos1 == pos2)
13109 		return isl_basic_map_universe(space);
13110 
13111 	bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
13112 	i = isl_basic_map_alloc_equality(bmap);
13113 	if (i < 0)
13114 		goto error;
13115 	isl_seq_clr(bmap->eq[i], 1 + total);
13116 	pos1 += isl_basic_map_offset(bmap, type1);
13117 	pos2 += isl_basic_map_offset(bmap, type2);
13118 	isl_int_set_si(bmap->eq[i][pos1], -1);
13119 	isl_int_set_si(bmap->eq[i][pos2], 1);
13120 	bmap = isl_basic_map_finalize(bmap);
13121 	isl_space_free(space);
13122 	return bmap;
13123 error:
13124 	isl_space_free(space);
13125 	isl_basic_map_free(bmap);
13126 	return NULL;
13127 }
13128 
13129 /* Add a constraint imposing that the given two dimensions are equal.
13130  */
isl_basic_map_equate(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13131 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
13132 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13133 {
13134 	isl_basic_map *eq;
13135 
13136 	eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13137 
13138 	bmap = isl_basic_map_intersect(bmap, eq);
13139 
13140 	return bmap;
13141 }
13142 
13143 /* Add a constraint imposing that the given two dimensions are equal.
13144  */
isl_map_equate(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13145 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
13146 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13147 {
13148 	isl_basic_map *bmap;
13149 
13150 	bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
13151 
13152 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13153 
13154 	return map;
13155 }
13156 
13157 /* Add a constraint imposing that the given two dimensions have opposite values.
13158  */
isl_map_oppose(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13159 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
13160 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13161 {
13162 	isl_basic_map *bmap = NULL;
13163 	int i;
13164 	isl_size total;
13165 
13166 	if (isl_map_check_range(map, type1, pos1, 1) < 0)
13167 		return isl_map_free(map);
13168 	if (isl_map_check_range(map, type2, pos2, 1) < 0)
13169 		return isl_map_free(map);
13170 
13171 	total = isl_map_dim(map, isl_dim_all);
13172 	if (total < 0)
13173 		return isl_map_free(map);
13174 	bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
13175 	i = isl_basic_map_alloc_equality(bmap);
13176 	if (i < 0)
13177 		goto error;
13178 	isl_seq_clr(bmap->eq[i], 1 + total);
13179 	pos1 += isl_basic_map_offset(bmap, type1);
13180 	pos2 += isl_basic_map_offset(bmap, type2);
13181 	isl_int_set_si(bmap->eq[i][pos1], 1);
13182 	isl_int_set_si(bmap->eq[i][pos2], 1);
13183 	bmap = isl_basic_map_finalize(bmap);
13184 
13185 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13186 
13187 	return map;
13188 error:
13189 	isl_basic_map_free(bmap);
13190 	isl_map_free(map);
13191 	return NULL;
13192 }
13193 
13194 /* Construct a constraint imposing that the value of the first dimension is
13195  * greater than or equal to that of the second.
13196  */
constraint_order_ge(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13197 static __isl_give isl_constraint *constraint_order_ge(
13198 	__isl_take isl_space *space, enum isl_dim_type type1, int pos1,
13199 	enum isl_dim_type type2, int pos2)
13200 {
13201 	isl_constraint *c;
13202 
13203 	if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13204 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13205 		space = isl_space_free(space);
13206 	if (!space)
13207 		return NULL;
13208 
13209 	c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
13210 
13211 	if (type1 == type2 && pos1 == pos2)
13212 		return c;
13213 
13214 	c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
13215 	c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
13216 
13217 	return c;
13218 }
13219 
13220 /* Add a constraint imposing that the value of the first dimension is
13221  * greater than or equal to that of the second.
13222  */
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)13223 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
13224 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13225 {
13226 	isl_constraint *c;
13227 	isl_space *space;
13228 
13229 	if (type1 == type2 && pos1 == pos2)
13230 		return bmap;
13231 	space = isl_basic_map_get_space(bmap);
13232 	c = constraint_order_ge(space, type1, pos1, type2, pos2);
13233 	bmap = isl_basic_map_add_constraint(bmap, c);
13234 
13235 	return bmap;
13236 }
13237 
13238 /* Add a constraint imposing that the value of the first dimension is
13239  * greater than or equal to that of the second.
13240  */
isl_map_order_ge(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13241 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
13242 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13243 {
13244 	isl_constraint *c;
13245 	isl_space *space;
13246 
13247 	if (type1 == type2 && pos1 == pos2)
13248 		return map;
13249 	space = isl_map_get_space(map);
13250 	c = constraint_order_ge(space, type1, pos1, type2, pos2);
13251 	map = isl_map_add_constraint(map, c);
13252 
13253 	return map;
13254 }
13255 
13256 /* Add a constraint imposing that the value of the first dimension is
13257  * less than or equal to that of the second.
13258  */
isl_map_order_le(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13259 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
13260 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13261 {
13262 	return isl_map_order_ge(map, type2, pos2, type1, pos1);
13263 }
13264 
13265 /* Construct a basic map where the value of the first dimension is
13266  * greater than that of the second.
13267  */
greator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13268 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
13269 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13270 {
13271 	isl_basic_map *bmap = NULL;
13272 	int i;
13273 	isl_size total;
13274 
13275 	if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13276 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13277 		goto error;
13278 
13279 	if (type1 == type2 && pos1 == pos2)
13280 		return isl_basic_map_empty(space);
13281 
13282 	bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
13283 	total = isl_basic_map_dim(bmap, isl_dim_all);
13284 	i = isl_basic_map_alloc_inequality(bmap);
13285 	if (total < 0 || i < 0)
13286 		return isl_basic_map_free(bmap);
13287 	isl_seq_clr(bmap->ineq[i], 1 + total);
13288 	pos1 += isl_basic_map_offset(bmap, type1);
13289 	pos2 += isl_basic_map_offset(bmap, type2);
13290 	isl_int_set_si(bmap->ineq[i][pos1], 1);
13291 	isl_int_set_si(bmap->ineq[i][pos2], -1);
13292 	isl_int_set_si(bmap->ineq[i][0], -1);
13293 	bmap = isl_basic_map_finalize(bmap);
13294 
13295 	return bmap;
13296 error:
13297 	isl_space_free(space);
13298 	isl_basic_map_free(bmap);
13299 	return NULL;
13300 }
13301 
13302 /* Add a constraint imposing that the value of the first dimension is
13303  * greater than that of the second.
13304  */
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)13305 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
13306 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13307 {
13308 	isl_basic_map *gt;
13309 
13310 	gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13311 
13312 	bmap = isl_basic_map_intersect(bmap, gt);
13313 
13314 	return bmap;
13315 }
13316 
13317 /* Add a constraint imposing that the value of the first dimension is
13318  * greater than that of the second.
13319  */
isl_map_order_gt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13320 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
13321 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13322 {
13323 	isl_basic_map *bmap;
13324 
13325 	bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
13326 
13327 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13328 
13329 	return map;
13330 }
13331 
13332 /* Add a constraint imposing that the value of the first dimension is
13333  * smaller than that of the second.
13334  */
isl_map_order_lt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13335 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
13336 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13337 {
13338 	return isl_map_order_gt(map, type2, pos2, type1, pos1);
13339 }
13340 
isl_basic_map_get_div(__isl_keep isl_basic_map * bmap,int pos)13341 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
13342 	int pos)
13343 {
13344 	isl_aff *div;
13345 	isl_local_space *ls;
13346 
13347 	if (!bmap)
13348 		return NULL;
13349 
13350 	if (!isl_basic_map_divs_known(bmap))
13351 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13352 			"some divs are unknown", return NULL);
13353 
13354 	ls = isl_basic_map_get_local_space(bmap);
13355 	div = isl_local_space_get_div(ls, pos);
13356 	isl_local_space_free(ls);
13357 
13358 	return div;
13359 }
13360 
isl_basic_set_get_div(__isl_keep isl_basic_set * bset,int pos)13361 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
13362 	int pos)
13363 {
13364 	return isl_basic_map_get_div(bset, pos);
13365 }
13366 
13367 /* Plug in "subs" for dimension "type", "pos" of "bset".
13368  *
13369  * Let i be the dimension to replace and let "subs" be of the form
13370  *
13371  *	f/d
13372  *
13373  * Any integer division with a non-zero coefficient for i,
13374  *
13375  *	floor((a i + g)/m)
13376  *
13377  * is replaced by
13378  *
13379  *	floor((a f + d g)/(m d))
13380  *
13381  * Constraints of the form
13382  *
13383  *	a i + g
13384  *
13385  * are replaced by
13386  *
13387  *	a f + d g
13388  *
13389  * We currently require that "subs" is an integral expression.
13390  * Handling rational expressions may require us to add stride constraints
13391  * as we do in isl_basic_set_preimage_multi_aff.
13392  */
isl_basic_set_substitute(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)13393 __isl_give isl_basic_set *isl_basic_set_substitute(
13394 	__isl_take isl_basic_set *bset,
13395 	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13396 {
13397 	int i;
13398 	isl_int v;
13399 	isl_ctx *ctx;
13400 	isl_size n_div;
13401 
13402 	if (bset && isl_basic_set_plain_is_empty(bset))
13403 		return bset;
13404 
13405 	bset = isl_basic_set_cow(bset);
13406 	if (!bset || !subs)
13407 		goto error;
13408 
13409 	ctx = isl_basic_set_get_ctx(bset);
13410 	if (!isl_space_is_equal(bset->dim, subs->ls->dim))
13411 		isl_die(ctx, isl_error_invalid,
13412 			"spaces don't match", goto error);
13413 	n_div = isl_local_space_dim(subs->ls, isl_dim_div);
13414 	if (n_div < 0)
13415 		goto error;
13416 	if (n_div != 0)
13417 		isl_die(ctx, isl_error_unsupported,
13418 			"cannot handle divs yet", goto error);
13419 	if (!isl_int_is_one(subs->v->el[0]))
13420 		isl_die(ctx, isl_error_invalid,
13421 			"can only substitute integer expressions", goto error);
13422 
13423 	pos += isl_basic_set_offset(bset, type);
13424 
13425 	isl_int_init(v);
13426 
13427 	for (i = 0; i < bset->n_eq; ++i) {
13428 		if (isl_int_is_zero(bset->eq[i][pos]))
13429 			continue;
13430 		isl_int_set(v, bset->eq[i][pos]);
13431 		isl_int_set_si(bset->eq[i][pos], 0);
13432 		isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
13433 				v, subs->v->el + 1, subs->v->size - 1);
13434 	}
13435 
13436 	for (i = 0; i < bset->n_ineq; ++i) {
13437 		if (isl_int_is_zero(bset->ineq[i][pos]))
13438 			continue;
13439 		isl_int_set(v, bset->ineq[i][pos]);
13440 		isl_int_set_si(bset->ineq[i][pos], 0);
13441 		isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
13442 				v, subs->v->el + 1, subs->v->size - 1);
13443 	}
13444 
13445 	for (i = 0; i < bset->n_div; ++i) {
13446 		if (isl_int_is_zero(bset->div[i][1 + pos]))
13447 			continue;
13448 		isl_int_set(v, bset->div[i][1 + pos]);
13449 		isl_int_set_si(bset->div[i][1 + pos], 0);
13450 		isl_seq_combine(bset->div[i] + 1,
13451 				subs->v->el[0], bset->div[i] + 1,
13452 				v, subs->v->el + 1, subs->v->size - 1);
13453 		isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
13454 	}
13455 
13456 	isl_int_clear(v);
13457 
13458 	bset = isl_basic_set_simplify(bset);
13459 	return isl_basic_set_finalize(bset);
13460 error:
13461 	isl_basic_set_free(bset);
13462 	return NULL;
13463 }
13464 
13465 /* Plug in "subs" for dimension "type", "pos" of "set".
13466  */
isl_set_substitute(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)13467 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
13468 	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13469 {
13470 	int i;
13471 
13472 	if (set && isl_set_plain_is_empty(set))
13473 		return set;
13474 
13475 	set = isl_set_cow(set);
13476 	if (!set || !subs)
13477 		goto error;
13478 
13479 	for (i = set->n - 1; i >= 0; --i) {
13480 		set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
13481 		set = set_from_map(remove_if_empty(set_to_map(set), i));
13482 		if (!set)
13483 			return NULL;
13484 	}
13485 
13486 	return set;
13487 error:
13488 	isl_set_free(set);
13489 	return NULL;
13490 }
13491 
13492 /* Check if the range of "ma" is compatible with the domain or range
13493  * (depending on "type") of "bmap".
13494  */
check_basic_map_compatible_range_multi_aff(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13495 static isl_stat check_basic_map_compatible_range_multi_aff(
13496 	__isl_keep isl_basic_map *bmap, enum isl_dim_type type,
13497 	__isl_keep isl_multi_aff *ma)
13498 {
13499 	isl_bool m;
13500 	isl_space *ma_space;
13501 
13502 	ma_space = isl_multi_aff_get_space(ma);
13503 
13504 	m = isl_space_has_equal_params(bmap->dim, ma_space);
13505 	if (m < 0)
13506 		goto error;
13507 	if (!m)
13508 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13509 			"parameters don't match", goto error);
13510 	m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
13511 	if (m < 0)
13512 		goto error;
13513 	if (!m)
13514 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13515 			"spaces don't match", goto error);
13516 
13517 	isl_space_free(ma_space);
13518 	return isl_stat_ok;
13519 error:
13520 	isl_space_free(ma_space);
13521 	return isl_stat_error;
13522 }
13523 
13524 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
13525  * coefficients before the transformed range of dimensions,
13526  * the "n_after" coefficients after the transformed range of dimensions
13527  * and the coefficients of the other divs in "bmap".
13528  */
set_ma_divs(__isl_take isl_basic_map * bmap,__isl_keep isl_multi_aff * ma,int n_before,int n_after,int n_div)13529 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
13530 	__isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
13531 {
13532 	int i;
13533 	isl_size n_param;
13534 	isl_size n_set;
13535 	isl_local_space *ls;
13536 
13537 	if (n_div == 0)
13538 		return bmap;
13539 
13540 	ls = isl_aff_get_domain_local_space(ma->u.p[0]);
13541 	n_param = isl_local_space_dim(ls, isl_dim_param);
13542 	n_set = isl_local_space_dim(ls, isl_dim_set);
13543 	if (n_param < 0 || n_set < 0)
13544 		return isl_basic_map_free(bmap);
13545 
13546 	for (i = 0; i < n_div; ++i) {
13547 		int o_bmap = 0, o_ls = 0;
13548 
13549 		isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
13550 		o_bmap += 1 + 1 + n_param;
13551 		o_ls += 1 + 1 + n_param;
13552 		isl_seq_clr(bmap->div[i] + o_bmap, n_before);
13553 		o_bmap += n_before;
13554 		isl_seq_cpy(bmap->div[i] + o_bmap,
13555 			    ls->div->row[i] + o_ls, n_set);
13556 		o_bmap += n_set;
13557 		o_ls += n_set;
13558 		isl_seq_clr(bmap->div[i] + o_bmap, n_after);
13559 		o_bmap += n_after;
13560 		isl_seq_cpy(bmap->div[i] + o_bmap,
13561 			    ls->div->row[i] + o_ls, n_div);
13562 		o_bmap += n_div;
13563 		o_ls += n_div;
13564 		isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
13565 		bmap = isl_basic_map_add_div_constraints(bmap, i);
13566 		if (!bmap)
13567 			goto error;
13568 	}
13569 
13570 	isl_local_space_free(ls);
13571 	return bmap;
13572 error:
13573 	isl_local_space_free(ls);
13574 	return isl_basic_map_free(bmap);
13575 }
13576 
13577 /* How many stride constraints does "ma" enforce?
13578  * That is, how many of the affine expressions have a denominator
13579  * different from one?
13580  */
multi_aff_strides(__isl_keep isl_multi_aff * ma)13581 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
13582 {
13583 	int i;
13584 	int strides = 0;
13585 
13586 	for (i = 0; i < ma->n; ++i)
13587 		if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
13588 			strides++;
13589 
13590 	return strides;
13591 }
13592 
13593 /* For each affine expression in ma of the form
13594  *
13595  *	x_i = (f_i y + h_i)/m_i
13596  *
13597  * with m_i different from one, add a constraint to "bmap"
13598  * of the form
13599  *
13600  *	f_i y + h_i = m_i alpha_i
13601  *
13602  * with alpha_i an additional existentially quantified variable.
13603  *
13604  * The input variables of "ma" correspond to a subset of the variables
13605  * of "bmap".  There are "n_before" variables in "bmap" before this
13606  * subset and "n_after" variables after this subset.
13607  * The integer divisions of the affine expressions in "ma" are assumed
13608  * to have been aligned.  There are "n_div_ma" of them and
13609  * they appear first in "bmap", straight after the "n_after" variables.
13610  */
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)13611 static __isl_give isl_basic_map *add_ma_strides(
13612 	__isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
13613 	int n_before, int n_after, int n_div_ma)
13614 {
13615 	int i, k;
13616 	int div;
13617 	isl_size total;
13618 	isl_size n_param;
13619 	isl_size n_in;
13620 
13621 	total = isl_basic_map_dim(bmap, isl_dim_all);
13622 	n_param = isl_multi_aff_dim(ma, isl_dim_param);
13623 	n_in = isl_multi_aff_dim(ma, isl_dim_in);
13624 	if (total < 0 || n_param < 0 || n_in < 0)
13625 		return isl_basic_map_free(bmap);
13626 	for (i = 0; i < ma->n; ++i) {
13627 		int o_bmap = 0, o_ma = 1;
13628 
13629 		if (isl_int_is_one(ma->u.p[i]->v->el[0]))
13630 			continue;
13631 		div = isl_basic_map_alloc_div(bmap);
13632 		k = isl_basic_map_alloc_equality(bmap);
13633 		if (div < 0 || k < 0)
13634 			goto error;
13635 		isl_int_set_si(bmap->div[div][0], 0);
13636 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13637 			    ma->u.p[i]->v->el + o_ma, 1 + n_param);
13638 		o_bmap += 1 + n_param;
13639 		o_ma += 1 + n_param;
13640 		isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
13641 		o_bmap += n_before;
13642 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13643 			    ma->u.p[i]->v->el + o_ma, n_in);
13644 		o_bmap += n_in;
13645 		o_ma += n_in;
13646 		isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
13647 		o_bmap += n_after;
13648 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13649 			    ma->u.p[i]->v->el + o_ma, n_div_ma);
13650 		o_bmap += n_div_ma;
13651 		o_ma += n_div_ma;
13652 		isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
13653 		isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
13654 		total++;
13655 	}
13656 
13657 	return bmap;
13658 error:
13659 	isl_basic_map_free(bmap);
13660 	return NULL;
13661 }
13662 
13663 /* Replace the domain or range space (depending on "type) of "space" by "set".
13664  */
isl_space_set(__isl_take isl_space * space,enum isl_dim_type type,__isl_take isl_space * set)13665 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
13666 	enum isl_dim_type type, __isl_take isl_space *set)
13667 {
13668 	if (type == isl_dim_in) {
13669 		space = isl_space_range(space);
13670 		space = isl_space_map_from_domain_and_range(set, space);
13671 	} else {
13672 		space = isl_space_domain(space);
13673 		space = isl_space_map_from_domain_and_range(space, set);
13674 	}
13675 
13676 	return space;
13677 }
13678 
13679 /* Compute the preimage of the domain or range (depending on "type")
13680  * of "bmap" under the function represented by "ma".
13681  * In other words, plug in "ma" in the domain or range of "bmap".
13682  * The result is a basic map that lives in the same space as "bmap"
13683  * except that the domain or range has been replaced by
13684  * the domain space of "ma".
13685  *
13686  * If bmap is represented by
13687  *
13688  *	A(p) + S u + B x + T v + C(divs) >= 0,
13689  *
13690  * where u and x are input and output dimensions if type == isl_dim_out
13691  * while x and v are input and output dimensions if type == isl_dim_in,
13692  * and ma is represented by
13693  *
13694  *	x = D(p) + F(y) + G(divs')
13695  *
13696  * then the result is
13697  *
13698  *	A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
13699  *
13700  * The divs in the input set are similarly adjusted.
13701  * In particular
13702  *
13703  *	floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
13704  *
13705  * becomes
13706  *
13707  *	floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
13708  *		B_i G(divs') + c_i(divs))/n_i)
13709  *
13710  * If bmap is not a rational map and if F(y) involves any denominators
13711  *
13712  *	x_i = (f_i y + h_i)/m_i
13713  *
13714  * then additional constraints are added to ensure that we only
13715  * map back integer points.  That is we enforce
13716  *
13717  *	f_i y + h_i = m_i alpha_i
13718  *
13719  * with alpha_i an additional existentially quantified variable.
13720  *
13721  * We first copy over the divs from "ma".
13722  * Then we add the modified constraints and divs from "bmap".
13723  * Finally, we add the stride constraints, if needed.
13724  */
isl_basic_map_preimage_multi_aff(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13725 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
13726 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
13727 	__isl_take isl_multi_aff *ma)
13728 {
13729 	int i, k;
13730 	isl_space *space;
13731 	isl_basic_map *res = NULL;
13732 	isl_size n_before, n_after, n_div_bmap, n_div_ma;
13733 	isl_int f, c1, c2, g;
13734 	isl_bool rational;
13735 	int strides;
13736 
13737 	isl_int_init(f);
13738 	isl_int_init(c1);
13739 	isl_int_init(c2);
13740 	isl_int_init(g);
13741 
13742 	ma = isl_multi_aff_align_divs(ma);
13743 	if (!bmap || !ma)
13744 		goto error;
13745 	if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
13746 		goto error;
13747 
13748 	if (type == isl_dim_in) {
13749 		n_before = 0;
13750 		n_after = isl_basic_map_dim(bmap, isl_dim_out);
13751 	} else {
13752 		n_before = isl_basic_map_dim(bmap, isl_dim_in);
13753 		n_after = 0;
13754 	}
13755 	n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
13756 	n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
13757 	if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
13758 		goto error;
13759 
13760 	space = isl_multi_aff_get_domain_space(ma);
13761 	space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
13762 	rational = isl_basic_map_is_rational(bmap);
13763 	strides = rational ? 0 : multi_aff_strides(ma);
13764 	res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
13765 			    bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
13766 	if (rational)
13767 		res = isl_basic_map_set_rational(res);
13768 
13769 	for (i = 0; i < n_div_ma + n_div_bmap; ++i)
13770 		if (isl_basic_map_alloc_div(res) < 0)
13771 			goto error;
13772 
13773 	res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
13774 	if (!res)
13775 		goto error;
13776 
13777 	for (i = 0; i < bmap->n_eq; ++i) {
13778 		k = isl_basic_map_alloc_equality(res);
13779 		if (k < 0)
13780 			goto error;
13781 		if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13782 				    n_after, n_div_ma, n_div_bmap,
13783 				    f, c1, c2, g, 0) < 0)
13784 			goto error;
13785 	}
13786 
13787 	for (i = 0; i < bmap->n_ineq; ++i) {
13788 		k = isl_basic_map_alloc_inequality(res);
13789 		if (k < 0)
13790 			goto error;
13791 		if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13792 				    n_after, n_div_ma, n_div_bmap,
13793 				    f, c1, c2, g, 0) < 0)
13794 			goto error;
13795 	}
13796 
13797 	for (i = 0; i < bmap->n_div; ++i) {
13798 		if (isl_int_is_zero(bmap->div[i][0])) {
13799 			isl_int_set_si(res->div[n_div_ma + i][0], 0);
13800 			continue;
13801 		}
13802 		if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13803 				    n_before, n_after, n_div_ma, n_div_bmap,
13804 				    f, c1, c2, g, 1) < 0)
13805 			goto error;
13806 	}
13807 
13808 	if (strides)
13809 		res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13810 
13811 	isl_int_clear(f);
13812 	isl_int_clear(c1);
13813 	isl_int_clear(c2);
13814 	isl_int_clear(g);
13815 	isl_basic_map_free(bmap);
13816 	isl_multi_aff_free(ma);
13817 	res = isl_basic_map_simplify(res);
13818 	return isl_basic_map_finalize(res);
13819 error:
13820 	isl_int_clear(f);
13821 	isl_int_clear(c1);
13822 	isl_int_clear(c2);
13823 	isl_int_clear(g);
13824 	isl_basic_map_free(bmap);
13825 	isl_multi_aff_free(ma);
13826 	isl_basic_map_free(res);
13827 	return NULL;
13828 }
13829 
13830 /* Compute the preimage of "bset" under the function represented by "ma".
13831  * In other words, plug in "ma" in "bset".  The result is a basic set
13832  * that lives in the domain space of "ma".
13833  */
isl_basic_set_preimage_multi_aff(__isl_take isl_basic_set * bset,__isl_take isl_multi_aff * ma)13834 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13835 	__isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13836 {
13837 	return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13838 }
13839 
13840 /* Compute the preimage of the domain of "bmap" under the function
13841  * represented by "ma".
13842  * In other words, plug in "ma" in the domain of "bmap".
13843  * The result is a basic map that lives in the same space as "bmap"
13844  * except that the domain has been replaced by the domain space of "ma".
13845  */
isl_basic_map_preimage_domain_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13846 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13847 	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13848 {
13849 	return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13850 }
13851 
13852 /* Compute the preimage of the range of "bmap" under the function
13853  * represented by "ma".
13854  * In other words, plug in "ma" in the range of "bmap".
13855  * The result is a basic map that lives in the same space as "bmap"
13856  * except that the range has been replaced by the domain space of "ma".
13857  */
isl_basic_map_preimage_range_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13858 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13859 	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13860 {
13861 	return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13862 }
13863 
13864 /* Check if the range of "ma" is compatible with the domain or range
13865  * (depending on "type") of "map".
13866  * Return isl_stat_error if anything is wrong.
13867  */
check_map_compatible_range_multi_aff(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13868 static isl_stat check_map_compatible_range_multi_aff(
13869 	__isl_keep isl_map *map, enum isl_dim_type type,
13870 	__isl_keep isl_multi_aff *ma)
13871 {
13872 	isl_bool m;
13873 	isl_space *ma_space;
13874 
13875 	ma_space = isl_multi_aff_get_space(ma);
13876 	m = isl_map_space_tuple_is_equal(map, type, ma_space, isl_dim_out);
13877 	isl_space_free(ma_space);
13878 	if (m < 0)
13879 		return isl_stat_error;
13880 	if (!m)
13881 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
13882 			"spaces don't match", return isl_stat_error);
13883 	return isl_stat_ok;
13884 }
13885 
13886 /* Compute the preimage of the domain or range (depending on "type")
13887  * of "map" under the function represented by "ma".
13888  * In other words, plug in "ma" in the domain or range of "map".
13889  * The result is a map that lives in the same space as "map"
13890  * except that the domain or range has been replaced by
13891  * the domain space of "ma".
13892  *
13893  * The parameters are assumed to have been aligned.
13894  */
map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13895 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13896 	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13897 {
13898 	int i;
13899 	isl_space *space;
13900 
13901 	map = isl_map_cow(map);
13902 	ma = isl_multi_aff_align_divs(ma);
13903 	if (!map || !ma)
13904 		goto error;
13905 	if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13906 		goto error;
13907 
13908 	for (i = 0; i < map->n; ++i) {
13909 		map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13910 							isl_multi_aff_copy(ma));
13911 		if (!map->p[i])
13912 			goto error;
13913 	}
13914 
13915 	space = isl_multi_aff_get_domain_space(ma);
13916 	space = isl_space_set(isl_map_get_space(map), type, space);
13917 
13918 	isl_space_free(isl_map_take_space(map));
13919 	map = isl_map_restore_space(map, space);
13920 	if (!map)
13921 		goto error;
13922 
13923 	isl_multi_aff_free(ma);
13924 	if (map->n > 1)
13925 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
13926 	ISL_F_CLR(map, ISL_SET_NORMALIZED);
13927 	return map;
13928 error:
13929 	isl_multi_aff_free(ma);
13930 	isl_map_free(map);
13931 	return NULL;
13932 }
13933 
13934 /* Compute the preimage of the domain or range (depending on "type")
13935  * of "map" under the function represented by "ma".
13936  * In other words, plug in "ma" in the domain or range of "map".
13937  * The result is a map that lives in the same space as "map"
13938  * except that the domain or range has been replaced by
13939  * the domain space of "ma".
13940  */
isl_map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13941 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13942 	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13943 {
13944 	isl_bool aligned;
13945 
13946 	if (!map || !ma)
13947 		goto error;
13948 
13949 	aligned = isl_map_space_has_equal_params(map, ma->space);
13950 	if (aligned < 0)
13951 		goto error;
13952 	if (aligned)
13953 		return map_preimage_multi_aff(map, type, ma);
13954 
13955 	if (isl_map_check_named_params(map) < 0)
13956 		goto error;
13957 	if (!isl_space_has_named_params(ma->space))
13958 		isl_die(map->ctx, isl_error_invalid,
13959 			"unaligned unnamed parameters", goto error);
13960 	map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13961 	ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13962 
13963 	return map_preimage_multi_aff(map, type, ma);
13964 error:
13965 	isl_multi_aff_free(ma);
13966 	return isl_map_free(map);
13967 }
13968 
13969 /* Compute the preimage of "set" under the function represented by "ma".
13970  * In other words, plug in "ma" in "set".  The result is a set
13971  * that lives in the domain space of "ma".
13972  */
isl_set_preimage_multi_aff(__isl_take isl_set * set,__isl_take isl_multi_aff * ma)13973 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13974 	__isl_take isl_multi_aff *ma)
13975 {
13976 	return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13977 }
13978 
13979 /* Compute the preimage of the domain of "map" under the function
13980  * represented by "ma".
13981  * In other words, plug in "ma" in the domain of "map".
13982  * The result is a map that lives in the same space as "map"
13983  * except that the domain has been replaced by the domain space of "ma".
13984  */
isl_map_preimage_domain_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)13985 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13986 	__isl_take isl_multi_aff *ma)
13987 {
13988 	return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13989 }
13990 
13991 /* Compute the preimage of the range of "map" under the function
13992  * represented by "ma".
13993  * In other words, plug in "ma" in the range of "map".
13994  * The result is a map that lives in the same space as "map"
13995  * except that the range has been replaced by the domain space of "ma".
13996  */
isl_map_preimage_range_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)13997 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13998 	__isl_take isl_multi_aff *ma)
13999 {
14000 	return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
14001 }
14002 
14003 /* Compute the preimage of "map" under the function represented by "pma".
14004  * In other words, plug in "pma" in the domain or range of "map".
14005  * The result is a map that lives in the same space as "map",
14006  * except that the space of type "type" has been replaced by
14007  * the domain space of "pma".
14008  *
14009  * The parameters of "map" and "pma" are assumed to have been aligned.
14010  */
isl_map_preimage_pw_multi_aff_aligned(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14011 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
14012 	__isl_take isl_map *map, enum isl_dim_type type,
14013 	__isl_take isl_pw_multi_aff *pma)
14014 {
14015 	int i;
14016 	isl_map *res;
14017 
14018 	if (!pma)
14019 		goto error;
14020 
14021 	if (pma->n == 0) {
14022 		isl_pw_multi_aff_free(pma);
14023 		res = isl_map_empty(isl_map_get_space(map));
14024 		isl_map_free(map);
14025 		return res;
14026 	}
14027 
14028 	res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14029 					isl_multi_aff_copy(pma->p[0].maff));
14030 	if (type == isl_dim_in)
14031 		res = isl_map_intersect_domain(res,
14032 						isl_map_copy(pma->p[0].set));
14033 	else
14034 		res = isl_map_intersect_range(res,
14035 						isl_map_copy(pma->p[0].set));
14036 
14037 	for (i = 1; i < pma->n; ++i) {
14038 		isl_map *res_i;
14039 
14040 		res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14041 					isl_multi_aff_copy(pma->p[i].maff));
14042 		if (type == isl_dim_in)
14043 			res_i = isl_map_intersect_domain(res_i,
14044 						isl_map_copy(pma->p[i].set));
14045 		else
14046 			res_i = isl_map_intersect_range(res_i,
14047 						isl_map_copy(pma->p[i].set));
14048 		res = isl_map_union(res, res_i);
14049 	}
14050 
14051 	isl_pw_multi_aff_free(pma);
14052 	isl_map_free(map);
14053 	return res;
14054 error:
14055 	isl_pw_multi_aff_free(pma);
14056 	isl_map_free(map);
14057 	return NULL;
14058 }
14059 
14060 /* Compute the preimage of "map" under the function represented by "pma".
14061  * In other words, plug in "pma" in the domain or range of "map".
14062  * The result is a map that lives in the same space as "map",
14063  * except that the space of type "type" has been replaced by
14064  * the domain space of "pma".
14065  */
isl_map_preimage_pw_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14066 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
14067 	enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
14068 {
14069 	isl_bool aligned;
14070 
14071 	if (!map || !pma)
14072 		goto error;
14073 
14074 	aligned = isl_map_space_has_equal_params(map, pma->dim);
14075 	if (aligned < 0)
14076 		goto error;
14077 	if (aligned)
14078 		return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14079 
14080 	if (isl_map_check_named_params(map) < 0)
14081 		goto error;
14082 	if (isl_pw_multi_aff_check_named_params(pma) < 0)
14083 		goto error;
14084 	map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
14085 	pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
14086 
14087 	return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14088 error:
14089 	isl_pw_multi_aff_free(pma);
14090 	return isl_map_free(map);
14091 }
14092 
14093 /* Compute the preimage of "set" under the function represented by "pma".
14094  * In other words, plug in "pma" in "set".  The result is a set
14095  * that lives in the domain space of "pma".
14096  */
isl_set_preimage_pw_multi_aff(__isl_take isl_set * set,__isl_take isl_pw_multi_aff * pma)14097 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
14098 	__isl_take isl_pw_multi_aff *pma)
14099 {
14100 	return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
14101 }
14102 
14103 /* Compute the preimage of the domain of "map" under the function
14104  * represented by "pma".
14105  * In other words, plug in "pma" in the domain of "map".
14106  * The result is a map that lives in the same space as "map",
14107  * except that domain space has been replaced by the domain space of "pma".
14108  */
isl_map_preimage_domain_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14109 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
14110 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14111 {
14112 	return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
14113 }
14114 
14115 /* Compute the preimage of the range of "map" under the function
14116  * represented by "pma".
14117  * In other words, plug in "pma" in the range of "map".
14118  * The result is a map that lives in the same space as "map",
14119  * except that range space has been replaced by the domain space of "pma".
14120  */
isl_map_preimage_range_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14121 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
14122 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14123 {
14124 	return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
14125 }
14126 
14127 /* Compute the preimage of "map" under the function represented by "mpa".
14128  * In other words, plug in "mpa" in the domain or range of "map".
14129  * The result is a map that lives in the same space as "map",
14130  * except that the space of type "type" has been replaced by
14131  * the domain space of "mpa".
14132  *
14133  * If the map does not involve any constraints that refer to the
14134  * dimensions of the substituted space, then the only possible
14135  * effect of "mpa" on the map is to map the space to a different space.
14136  * We create a separate isl_multi_aff to effectuate this change
14137  * in order to avoid spurious splitting of the map along the pieces
14138  * of "mpa".
14139  * If "mpa" has a non-trivial explicit domain, however,
14140  * then the full substitution should be performed.
14141  */
isl_map_preimage_multi_pw_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_pw_aff * mpa)14142 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
14143 	enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
14144 {
14145 	isl_size n;
14146 	isl_bool full;
14147 	isl_pw_multi_aff *pma;
14148 
14149 	n = isl_map_dim(map, type);
14150 	if (n < 0 || !mpa)
14151 		goto error;
14152 
14153 	full = isl_map_involves_dims(map, type, 0, n);
14154 	if (full >= 0 && !full)
14155 		full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
14156 	if (full < 0)
14157 		goto error;
14158 	if (!full) {
14159 		isl_space *space;
14160 		isl_multi_aff *ma;
14161 
14162 		space = isl_multi_pw_aff_get_space(mpa);
14163 		isl_multi_pw_aff_free(mpa);
14164 		ma = isl_multi_aff_zero(space);
14165 		return isl_map_preimage_multi_aff(map, type, ma);
14166 	}
14167 
14168 	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
14169 	return isl_map_preimage_pw_multi_aff(map, type, pma);
14170 error:
14171 	isl_map_free(map);
14172 	isl_multi_pw_aff_free(mpa);
14173 	return NULL;
14174 }
14175 
14176 /* Compute the preimage of "map" under the function represented by "mpa".
14177  * In other words, plug in "mpa" in the domain "map".
14178  * The result is a map that lives in the same space as "map",
14179  * except that domain space has been replaced by the domain space of "mpa".
14180  */
isl_map_preimage_domain_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * mpa)14181 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
14182 	__isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
14183 {
14184 	return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
14185 }
14186 
14187 /* Compute the preimage of "set" by the function represented by "mpa".
14188  * In other words, plug in "mpa" in "set".
14189  */
isl_set_preimage_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * mpa)14190 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
14191 	__isl_take isl_multi_pw_aff *mpa)
14192 {
14193 	return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
14194 }
14195 
14196 /* Return a copy of the equality constraints of "bset" as a matrix.
14197  */
isl_basic_set_extract_equalities(__isl_keep isl_basic_set * bset)14198 __isl_give isl_mat *isl_basic_set_extract_equalities(
14199 	__isl_keep isl_basic_set *bset)
14200 {
14201 	isl_ctx *ctx;
14202 	isl_size total;
14203 
14204 	total = isl_basic_set_dim(bset, isl_dim_all);
14205 	if (total < 0)
14206 		return NULL;
14207 
14208 	ctx = isl_basic_set_get_ctx(bset);
14209 	return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
14210 }
14211 
14212 /* Are the "n" "coefficients" starting at "first" of the integer division
14213  * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
14214  * to each other?
14215  * The "coefficient" at position 0 is the denominator.
14216  * The "coefficient" at position 1 is the constant term.
14217  */
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)14218 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
14219 	int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
14220 	unsigned first, unsigned n)
14221 {
14222 	if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
14223 		return isl_bool_error;
14224 	if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
14225 		return isl_bool_error;
14226 	return isl_seq_eq(bmap1->div[pos1] + first,
14227 			  bmap2->div[pos2] + first, n);
14228 }
14229 
14230 /* Are the integer division expressions at position "pos1" in "bmap1" and
14231  * "pos2" in "bmap2" equal to each other, except that the constant terms
14232  * are different?
14233  */
isl_basic_map_equal_div_expr_except_constant(__isl_keep isl_basic_map * bmap1,int pos1,__isl_keep isl_basic_map * bmap2,int pos2)14234 isl_bool isl_basic_map_equal_div_expr_except_constant(
14235 	__isl_keep isl_basic_map *bmap1, int pos1,
14236 	__isl_keep isl_basic_map *bmap2, int pos2)
14237 {
14238 	isl_bool equal;
14239 	isl_size total, total2;
14240 
14241 	total = isl_basic_map_dim(bmap1, isl_dim_all);
14242 	total2 = isl_basic_map_dim(bmap2, isl_dim_all);
14243 	if (total < 0 || total2 < 0)
14244 		return isl_bool_error;
14245 	if (total != total2)
14246 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
14247 			"incomparable div expressions", return isl_bool_error);
14248 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14249 						0, 1);
14250 	if (equal < 0 || !equal)
14251 		return equal;
14252 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14253 						1, 1);
14254 	if (equal < 0 || equal)
14255 		return isl_bool_not(equal);
14256 	return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14257 						2, total);
14258 }
14259 
14260 /* Replace the numerator of the constant term of the integer division
14261  * expression at position "div" in "bmap" by "value".
14262  * The caller guarantees that this does not change the meaning
14263  * of the input.
14264  */
isl_basic_map_set_div_expr_constant_num_si_inplace(__isl_take isl_basic_map * bmap,int div,int value)14265 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
14266 	__isl_take isl_basic_map *bmap, int div, int value)
14267 {
14268 	if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
14269 		return isl_basic_map_free(bmap);
14270 
14271 	isl_int_set_si(bmap->div[div][1], value);
14272 
14273 	return bmap;
14274 }
14275 
14276 /* Is the point "inner" internal to inequality constraint "ineq"
14277  * of "bset"?
14278  * The point is considered to be internal to the inequality constraint,
14279  * if it strictly lies on the positive side of the inequality constraint,
14280  * or if it lies on the constraint and the constraint is lexico-positive.
14281  */
is_internal(__isl_keep isl_vec * inner,__isl_keep isl_basic_set * bset,int ineq)14282 static isl_bool is_internal(__isl_keep isl_vec *inner,
14283 	__isl_keep isl_basic_set *bset, int ineq)
14284 {
14285 	isl_ctx *ctx;
14286 	int pos;
14287 	isl_size total;
14288 
14289 	if (!inner || !bset)
14290 		return isl_bool_error;
14291 
14292 	ctx = isl_basic_set_get_ctx(bset);
14293 	isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
14294 				&ctx->normalize_gcd);
14295 	if (!isl_int_is_zero(ctx->normalize_gcd))
14296 		return isl_int_is_nonneg(ctx->normalize_gcd);
14297 
14298 	total = isl_basic_set_dim(bset, isl_dim_all);
14299 	if (total < 0)
14300 		return isl_bool_error;
14301 	pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
14302 	return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
14303 }
14304 
14305 /* Tighten the inequality constraints of "bset" that are outward with respect
14306  * to the point "vec".
14307  * That is, tighten the constraints that are not satisfied by "vec".
14308  *
14309  * "vec" is a point internal to some superset S of "bset" that is used
14310  * to make the subsets of S disjoint, by tightening one half of the constraints
14311  * that separate two subsets.  In particular, the constraints of S
14312  * are all satisfied by "vec" and should not be tightened.
14313  * Of the internal constraints, those that have "vec" on the outside
14314  * are tightened.  The shared facet is included in the adjacent subset
14315  * with the opposite constraint.
14316  * For constraints that saturate "vec", this criterion cannot be used
14317  * to determine which of the two sides should be tightened.
14318  * Instead, the sign of the first non-zero coefficient is used
14319  * to make this choice.  Note that this second criterion is never used
14320  * on the constraints of S since "vec" is interior to "S".
14321  */
isl_basic_set_tighten_outward(__isl_take isl_basic_set * bset,__isl_keep isl_vec * vec)14322 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
14323 	__isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
14324 {
14325 	int j;
14326 
14327 	bset = isl_basic_set_cow(bset);
14328 	if (!bset)
14329 		return NULL;
14330 	for (j = 0; j < bset->n_ineq; ++j) {
14331 		isl_bool internal;
14332 
14333 		internal = is_internal(vec, bset, j);
14334 		if (internal < 0)
14335 			return isl_basic_set_free(bset);
14336 		if (internal)
14337 			continue;
14338 		isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
14339 	}
14340 
14341 	return bset;
14342 }
14343 
14344 /* Replace the variables x of type "type" starting at "first" in "bmap"
14345  * by x' with x = M x' with M the matrix trans.
14346  * That is, replace the corresponding coefficients c by c M.
14347  *
14348  * The transformation matrix should be a square matrix.
14349  */
isl_basic_map_transform_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14350 __isl_give isl_basic_map *isl_basic_map_transform_dims(
14351 	__isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
14352 	__isl_take isl_mat *trans)
14353 {
14354 	unsigned pos;
14355 
14356 	bmap = isl_basic_map_cow(bmap);
14357 	if (!bmap || !trans)
14358 		goto error;
14359 
14360 	if (trans->n_row != trans->n_col)
14361 		isl_die(trans->ctx, isl_error_invalid,
14362 			"expecting square transformation matrix", goto error);
14363 	if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
14364 		goto error;
14365 
14366 	pos = isl_basic_map_offset(bmap, type) + first;
14367 
14368 	if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
14369 			isl_mat_copy(trans)) < 0)
14370 		goto error;
14371 	if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
14372 		      isl_mat_copy(trans)) < 0)
14373 		goto error;
14374 	if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
14375 		      isl_mat_copy(trans)) < 0)
14376 		goto error;
14377 
14378 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
14379 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
14380 
14381 	isl_mat_free(trans);
14382 	return bmap;
14383 error:
14384 	isl_mat_free(trans);
14385 	isl_basic_map_free(bmap);
14386 	return NULL;
14387 }
14388 
14389 /* Replace the variables x of type "type" starting at "first" in "bset"
14390  * by x' with x = M x' with M the matrix trans.
14391  * That is, replace the corresponding coefficients c by c M.
14392  *
14393  * The transformation matrix should be a square matrix.
14394  */
isl_basic_set_transform_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14395 __isl_give isl_basic_set *isl_basic_set_transform_dims(
14396 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
14397 	__isl_take isl_mat *trans)
14398 {
14399 	return isl_basic_map_transform_dims(bset, type, first, trans);
14400 }
14401