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 /* If "mv" has an explicit domain, then intersect the domain of "map"
6868  * with this explicit domain.
6869  *
6870  * An isl_multi_val object never has an explicit domain,
6871  * so simply return "map".
6872  */
isl_map_intersect_multi_val_explicit_domain(__isl_take isl_map * map,__isl_keep isl_multi_val * mv)6873 static __isl_give isl_map *isl_map_intersect_multi_val_explicit_domain(
6874 	__isl_take isl_map *map, __isl_keep isl_multi_val *mv)
6875 {
6876 	return map;
6877 }
6878 
6879 #undef BASE
6880 #define BASE	val
6881 #include "isl_map_bound_templ.c"
6882 
6883 /* Apply "map_bound" to "set" with the corresponding value in "bound"
6884  * for each set dimension, by treating the set as a map.
6885  */
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))6886 static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,
6887 	__isl_take isl_multi_val *bound,
6888 	__isl_give isl_map *map_bound(__isl_take isl_map *map,
6889 		unsigned pos, __isl_take isl_val *value))
6890 {
6891 	isl_map *map;
6892 
6893 	map = set_to_map(set);
6894 	return set_from_map(map_bound_multi_val(map, bound, map_bound));
6895 }
6896 
6897 #undef BASE
6898 #define BASE	pw_aff
6899 #include "isl_map_bound_templ.c"
6900 
6901 /* Apply "map_bound" to "set" with the corresponding value in "bound"
6902  * for each set dimension, by converting the set and the bound
6903  * to objects living in a map space.
6904  */
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))6905 static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,
6906 	__isl_take isl_multi_pw_aff *bound,
6907 	__isl_give isl_map *set_bound(__isl_take isl_map *map,
6908 		unsigned pos, __isl_take TYPE *value))
6909 {
6910 	isl_map *map;
6911 
6912 	map = isl_map_from_range(set);
6913 	bound = isl_multi_pw_aff_from_range(bound);
6914 	map = map_bound_multi_pw_aff(map, bound, set_bound);
6915 	return isl_map_range(map);
6916 }
6917 
6918 /* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,
6919  * setting a bound on the given output dimension.
6920  */
map_lower_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)6921 static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,
6922 	unsigned pos, __isl_take isl_val *v)
6923 {
6924 	return isl_map_lower_bound_val(map, isl_dim_out, pos, v);
6925 }
6926 
6927 /* Force the values of the set dimensions of "set"
6928  * to be no smaller than the corresponding values in "lower".
6929  */
isl_set_lower_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * lower)6930 __isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
6931 	__isl_take isl_multi_val *lower)
6932 {
6933 	return set_bound_multi_val(set, lower, &map_lower_bound_val);
6934 }
6935 
6936 /* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,
6937  * setting a bound on the given output dimension.
6938  */
map_upper_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)6939 static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,
6940 	unsigned pos, __isl_take isl_val *v)
6941 {
6942 	return isl_map_upper_bound_val(map, isl_dim_out, pos, v);
6943 }
6944 
6945 /* Force the values of the set dimensions of "set"
6946  * to be no greater than the corresponding values in "upper".
6947  */
isl_set_upper_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * upper)6948 __isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
6949 	__isl_take isl_multi_val *upper)
6950 {
6951 	return set_bound_multi_val(set, upper, &map_upper_bound_val);
6952 }
6953 
6954 /* Force the symbolic constant expression "bound"
6955  * to satisfy the relation "order" with respect to
6956  * the output variable at position "pos" of "map".
6957  *
6958  * Create an affine expression representing the output variable
6959  * in terms of the range and
6960  * compare it using "order" to "bound" (defined on the domain).
6961  * The result is a relation between elements in domain and range that
6962  * can be intersected with "map".
6963  */
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))6964 static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,
6965 	unsigned pos, __isl_take isl_pw_aff *bound,
6966 	__isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,
6967 		__isl_take isl_pw_aff *pa2))
6968 {
6969 	isl_space *space;
6970 	isl_local_space *ls;
6971 	isl_pw_aff *var;
6972 
6973 	space = isl_space_range(isl_map_get_space(map));
6974 	ls = isl_local_space_from_space(space);
6975 	var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);
6976 	map = isl_map_intersect(map, order(bound, var));
6977 	return map;
6978 }
6979 
6980 /* Force the values of the output variable at position "pos" of "map"
6981  * to be no smaller than the symbolic constant expression "lower".
6982  */
map_lower_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * lower)6983 static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,
6984 	unsigned pos, __isl_take isl_pw_aff *lower)
6985 {
6986 	return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);
6987 }
6988 
6989 /* Force the values of the output variable at position "pos" of "map"
6990  * to be no greater than the symbolic constant expression "upper".
6991  */
map_upper_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * upper)6992 static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,
6993 	unsigned pos, __isl_take isl_pw_aff *upper)
6994 {
6995 	return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);
6996 }
6997 
6998 /* Force the values of the set dimensions of "set"
6999  * to be no smaller than the corresponding constant symbolic expressions
7000  * in "lower".
7001  */
isl_set_lower_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * lower)7002 __isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
7003 	__isl_take isl_multi_pw_aff *lower)
7004 {
7005 	return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);
7006 }
7007 
7008 /* Force the values of the set dimensions of "set"
7009  * to be no greater than the corresponding constant symbolic expressions
7010  * in "upper".
7011  */
isl_set_upper_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * upper)7012 __isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
7013 	__isl_take isl_multi_pw_aff *upper)
7014 {
7015 	return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);
7016 }
7017 
7018 /* Force the values of the output dimensions of "map"
7019  * to be no smaller than the corresponding constant symbolic expressions
7020  * in "lower".
7021  */
isl_map_lower_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * lower)7022 __isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
7023 	__isl_take isl_multi_pw_aff *lower)
7024 {
7025 	return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);
7026 }
7027 
7028 /* Force the values of the output dimensions of "map"
7029  * to be no greater than the corresponding constant symbolic expressions
7030  * in "upper".
7031  */
isl_map_upper_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * upper)7032 __isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
7033 	__isl_take isl_multi_pw_aff *upper)
7034 {
7035 	return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);
7036 }
7037 
7038 /* Bound the given variable of "bset" from below (or above is "upper"
7039  * is set) to "value".
7040  */
isl_basic_set_bound(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value,int upper)7041 static __isl_give isl_basic_set *isl_basic_set_bound(
7042 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7043 	isl_int value, int upper)
7044 {
7045 	return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
7046 						type, pos, value, upper));
7047 }
7048 
7049 /* Bound the given variable of "bset" from below (or above is "upper"
7050  * is set) to "value".
7051  */
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)7052 static __isl_give isl_basic_set *isl_basic_set_bound_val(
7053 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7054 	__isl_take isl_val *value, int upper)
7055 {
7056 	if (!value)
7057 		goto error;
7058 	if (!isl_val_is_int(value))
7059 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
7060 			"expecting integer value", goto error);
7061 	bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
7062 	isl_val_free(value);
7063 	return bset;
7064 error:
7065 	isl_val_free(value);
7066 	isl_basic_set_free(bset);
7067 	return NULL;
7068 }
7069 
7070 /* Bound the given variable of "bset" from below to "value".
7071  */
isl_basic_set_lower_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7072 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
7073 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7074 	__isl_take isl_val *value)
7075 {
7076 	return isl_basic_set_bound_val(bset, type, pos, value, 0);
7077 }
7078 
7079 /* Bound the given variable of "bset" from above to "value".
7080  */
isl_basic_set_upper_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7081 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
7082 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7083 	__isl_take isl_val *value)
7084 {
7085 	return isl_basic_set_bound_val(bset, type, pos, value, 1);
7086 }
7087 
isl_map_reverse(__isl_take isl_map * map)7088 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
7089 {
7090 	return isl_map_transform(map, &isl_space_reverse,
7091 					&isl_basic_map_reverse);
7092 }
7093 
7094 /* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).
7095  */
isl_map_range_reverse(__isl_take isl_map * map)7096 __isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)
7097 {
7098 	return isl_map_transform(map, &isl_space_range_reverse,
7099 					&isl_basic_map_range_reverse);
7100 }
7101 
7102 #undef TYPE
7103 #define TYPE	isl_pw_multi_aff
7104 #undef SUFFIX
7105 #define SUFFIX	_pw_multi_aff
7106 #undef EMPTY
7107 #define EMPTY	isl_pw_multi_aff_empty
7108 #undef ADD
7109 #define ADD	isl_pw_multi_aff_union_add
7110 #include "isl_map_lexopt_templ.c"
7111 
7112 /* Given a map "map", compute the lexicographically minimal
7113  * (or maximal) image element for each domain element in dom,
7114  * in the form of an isl_pw_multi_aff.
7115  * If "empty" is not NULL, then set *empty to those elements in dom that
7116  * do not have an image element.
7117  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7118  * should be computed over the domain of "map".  "empty" is also NULL
7119  * in this case.
7120  *
7121  * We first compute the lexicographically minimal or maximal element
7122  * in the first basic map.  This results in a partial solution "res"
7123  * and a subset "todo" of dom that still need to be handled.
7124  * We then consider each of the remaining maps in "map" and successively
7125  * update both "res" and "todo".
7126  * If "empty" is NULL, then the todo sets are not needed and therefore
7127  * also not computed.
7128  */
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)7129 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
7130 	__isl_take isl_map *map, __isl_take isl_set *dom,
7131 	__isl_give isl_set **empty, unsigned flags)
7132 {
7133 	int i;
7134 	int full;
7135 	isl_pw_multi_aff *res;
7136 	isl_set *todo;
7137 
7138 	full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7139 	if (!map || (!full && !dom))
7140 		goto error;
7141 
7142 	if (isl_map_plain_is_empty(map)) {
7143 		if (empty)
7144 			*empty = dom;
7145 		else
7146 			isl_set_free(dom);
7147 		return isl_pw_multi_aff_from_map(map);
7148 	}
7149 
7150 	res = basic_map_partial_lexopt_pw_multi_aff(
7151 					    isl_basic_map_copy(map->p[0]),
7152 					    isl_set_copy(dom), empty, flags);
7153 
7154 	if (empty)
7155 		todo = *empty;
7156 	for (i = 1; i < map->n; ++i) {
7157 		isl_pw_multi_aff *res_i;
7158 
7159 		res_i = basic_map_partial_lexopt_pw_multi_aff(
7160 					    isl_basic_map_copy(map->p[i]),
7161 					    isl_set_copy(dom), empty, flags);
7162 
7163 		if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
7164 			res = isl_pw_multi_aff_union_lexmax(res, res_i);
7165 		else
7166 			res = isl_pw_multi_aff_union_lexmin(res, res_i);
7167 
7168 		if (empty)
7169 			todo = isl_set_intersect(todo, *empty);
7170 	}
7171 
7172 	isl_set_free(dom);
7173 	isl_map_free(map);
7174 
7175 	if (empty)
7176 		*empty = todo;
7177 
7178 	return res;
7179 error:
7180 	if (empty)
7181 		*empty = NULL;
7182 	isl_set_free(dom);
7183 	isl_map_free(map);
7184 	return NULL;
7185 }
7186 
7187 #undef TYPE
7188 #define TYPE	isl_map
7189 #undef SUFFIX
7190 #define SUFFIX
7191 #undef EMPTY
7192 #define EMPTY	isl_map_empty
7193 #undef ADD
7194 #define ADD	isl_map_union_disjoint
7195 #include "isl_map_lexopt_templ.c"
7196 
7197 /* Given a map "map", compute the lexicographically minimal
7198  * (or maximal) image element for each domain element in "dom",
7199  * in the form of an isl_map.
7200  * If "empty" is not NULL, then set *empty to those elements in "dom" that
7201  * do not have an image element.
7202  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7203  * should be computed over the domain of "map".  "empty" is also NULL
7204  * in this case.
7205  *
7206  * If the input consists of more than one disjunct, then first
7207  * compute the desired result in the form of an isl_pw_multi_aff and
7208  * then convert that into an isl_map.
7209  *
7210  * This function used to have an explicit implementation in terms
7211  * of isl_maps, but it would continually intersect the domains of
7212  * partial results with the complement of the domain of the next
7213  * partial solution, potentially leading to an explosion in the number
7214  * of disjuncts if there are several disjuncts in the input.
7215  * An even earlier implementation of this function would look for
7216  * better results in the domain of the partial result and for extra
7217  * results in the complement of this domain, which would lead to
7218  * even more splintering.
7219  */
isl_map_partial_lexopt_aligned(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty,unsigned flags)7220 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
7221 	__isl_take isl_map *map, __isl_take isl_set *dom,
7222 	__isl_give isl_set **empty, unsigned flags)
7223 {
7224 	int full;
7225 	struct isl_map *res;
7226 	isl_pw_multi_aff *pma;
7227 
7228 	full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7229 	if (!map || (!full && !dom))
7230 		goto error;
7231 
7232 	if (isl_map_plain_is_empty(map)) {
7233 		if (empty)
7234 			*empty = dom;
7235 		else
7236 			isl_set_free(dom);
7237 		return map;
7238 	}
7239 
7240 	if (map->n == 1) {
7241 		res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
7242 						dom, empty, flags);
7243 		isl_map_free(map);
7244 		return res;
7245 	}
7246 
7247 	pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
7248 							flags);
7249 	return isl_map_from_pw_multi_aff_internal(pma);
7250 error:
7251 	if (empty)
7252 		*empty = NULL;
7253 	isl_set_free(dom);
7254 	isl_map_free(map);
7255 	return NULL;
7256 }
7257 
isl_map_partial_lexmax(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7258 __isl_give isl_map *isl_map_partial_lexmax(
7259 		__isl_take isl_map *map, __isl_take isl_set *dom,
7260 		__isl_give isl_set **empty)
7261 {
7262 	return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
7263 }
7264 
isl_map_partial_lexmin(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7265 __isl_give isl_map *isl_map_partial_lexmin(
7266 		__isl_take isl_map *map, __isl_take isl_set *dom,
7267 		__isl_give isl_set **empty)
7268 {
7269 	return isl_map_partial_lexopt(map, dom, empty, 0);
7270 }
7271 
isl_set_partial_lexmin(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7272 __isl_give isl_set *isl_set_partial_lexmin(
7273 		__isl_take isl_set *set, __isl_take isl_set *dom,
7274 		__isl_give isl_set **empty)
7275 {
7276 	return set_from_map(isl_map_partial_lexmin(set_to_map(set),
7277 						    dom, empty));
7278 }
7279 
isl_set_partial_lexmax(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7280 __isl_give isl_set *isl_set_partial_lexmax(
7281 		__isl_take isl_set *set, __isl_take isl_set *dom,
7282 		__isl_give isl_set **empty)
7283 {
7284 	return set_from_map(isl_map_partial_lexmax(set_to_map(set),
7285 						    dom, empty));
7286 }
7287 
7288 /* Compute the lexicographic minimum (or maximum if "flags" includes
7289  * ISL_OPT_MAX) of "bset" over its parametric domain.
7290  */
isl_basic_set_lexopt(__isl_take isl_basic_set * bset,unsigned flags)7291 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
7292 	unsigned flags)
7293 {
7294 	return isl_basic_map_lexopt(bset, flags);
7295 }
7296 
isl_basic_map_lexmax(__isl_take isl_basic_map * bmap)7297 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
7298 {
7299 	return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
7300 }
7301 
isl_basic_set_lexmin(__isl_take isl_basic_set * bset)7302 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
7303 {
7304 	return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
7305 }
7306 
isl_basic_set_lexmax(__isl_take isl_basic_set * bset)7307 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
7308 {
7309 	return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
7310 }
7311 
7312 /* Compute the lexicographic minimum of "bset" over its parametric domain
7313  * for the purpose of quantifier elimination.
7314  * That is, find an explicit representation for all the existentially
7315  * quantified variables in "bset" by computing their lexicographic
7316  * minimum.
7317  */
isl_basic_set_lexmin_compute_divs(__isl_take isl_basic_set * bset)7318 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
7319 	__isl_take isl_basic_set *bset)
7320 {
7321 	return isl_basic_set_lexopt(bset, ISL_OPT_QE);
7322 }
7323 
7324 /* Given a basic map with one output dimension, compute the minimum or
7325  * maximum of that dimension as an isl_pw_aff.
7326  *
7327  * Compute the optimum as a lexicographic optimum over the single
7328  * output dimension and extract the single isl_pw_aff from the result.
7329  */
basic_map_dim_opt(__isl_keep isl_basic_map * bmap,int max)7330 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
7331 	int max)
7332 {
7333 	isl_pw_multi_aff *pma;
7334 	isl_pw_aff *pwaff;
7335 
7336 	bmap = isl_basic_map_copy(bmap);
7337 	pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
7338 	pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
7339 	isl_pw_multi_aff_free(pma);
7340 
7341 	return pwaff;
7342 }
7343 
7344 /* Compute the minimum or maximum of the given output dimension
7345  * as a function of the parameters and the input dimensions,
7346  * but independently of the other output dimensions.
7347  *
7348  * We first project out the other output dimension and then compute
7349  * the "lexicographic" maximum in each basic map, combining the results
7350  * using isl_pw_aff_union_max.
7351  */
map_dim_opt(__isl_take isl_map * map,int pos,int max)7352 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
7353 	int max)
7354 {
7355 	int i;
7356 	isl_pw_aff *pwaff;
7357 	isl_size n_out;
7358 
7359 	n_out = isl_map_dim(map, isl_dim_out);
7360 	if (n_out < 0)
7361 		map = isl_map_free(map);
7362 	map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7363 	map = isl_map_project_out(map, isl_dim_out, 0, pos);
7364 	if (!map)
7365 		return NULL;
7366 
7367 	if (map->n == 0) {
7368 		isl_space *space = isl_map_get_space(map);
7369 		isl_map_free(map);
7370 		return isl_pw_aff_empty(space);
7371 	}
7372 
7373 	pwaff = basic_map_dim_opt(map->p[0], max);
7374 	for (i = 1; i < map->n; ++i) {
7375 		isl_pw_aff *pwaff_i;
7376 
7377 		pwaff_i = basic_map_dim_opt(map->p[i], max);
7378 		pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7379 	}
7380 
7381 	isl_map_free(map);
7382 
7383 	return pwaff;
7384 }
7385 
7386 /* Compute the minimum of the given output dimension as a function of the
7387  * parameters and input dimensions, but independently of
7388  * the other output dimensions.
7389  */
isl_map_dim_min(__isl_take isl_map * map,int pos)7390 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7391 {
7392 	return map_dim_opt(map, pos, 0);
7393 }
7394 
7395 /* Compute the maximum of the given output dimension as a function of the
7396  * parameters and input dimensions, but independently of
7397  * the other output dimensions.
7398  */
isl_map_dim_max(__isl_take isl_map * map,int pos)7399 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7400 {
7401 	return map_dim_opt(map, pos, 1);
7402 }
7403 
7404 /* Compute the minimum or maximum of the given set dimension
7405  * as a function of the parameters,
7406  * but independently of the other set dimensions.
7407  */
set_dim_opt(__isl_take isl_set * set,int pos,int max)7408 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7409 	int max)
7410 {
7411 	return map_dim_opt(set, pos, max);
7412 }
7413 
7414 /* Compute the maximum of the given set dimension as a function of the
7415  * parameters, but independently of the other set dimensions.
7416  */
isl_set_dim_max(__isl_take isl_set * set,int pos)7417 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7418 {
7419 	return set_dim_opt(set, pos, 1);
7420 }
7421 
7422 /* Compute the minimum of the given set dimension as a function of the
7423  * parameters, but independently of the other set dimensions.
7424  */
isl_set_dim_min(__isl_take isl_set * set,int pos)7425 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7426 {
7427 	return set_dim_opt(set, pos, 0);
7428 }
7429 
7430 /* Apply a preimage specified by "mat" on the parameters of "bset".
7431  * bset is assumed to have only parameters and divs.
7432  */
basic_set_parameter_preimage(__isl_take isl_basic_set * bset,__isl_take isl_mat * mat)7433 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7434 	__isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7435 {
7436 	isl_size nparam;
7437 
7438 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7439 	if (nparam < 0 || !mat)
7440 		goto error;
7441 
7442 	bset->dim = isl_space_cow(bset->dim);
7443 	if (!bset->dim)
7444 		goto error;
7445 
7446 	isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7447 
7448 	bset->dim->nparam = 0;
7449 	bset->dim->n_out = nparam;
7450 	bset = isl_basic_set_preimage(bset, mat);
7451 	if (bset) {
7452 		bset->dim->nparam = bset->dim->n_out;
7453 		bset->dim->n_out = 0;
7454 	}
7455 	return bset;
7456 error:
7457 	isl_mat_free(mat);
7458 	isl_basic_set_free(bset);
7459 	return NULL;
7460 }
7461 
7462 /* Apply a preimage specified by "mat" on the parameters of "set".
7463  * set is assumed to have only parameters and divs.
7464  */
set_parameter_preimage(__isl_take isl_set * set,__isl_take isl_mat * mat)7465 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7466 	__isl_take isl_mat *mat)
7467 {
7468 	isl_space *space;
7469 	isl_size nparam;
7470 
7471 	nparam = isl_set_dim(set, isl_dim_param);
7472 	if (nparam < 0 || !mat)
7473 		goto error;
7474 
7475 	if (mat->n_row != 1 + nparam)
7476 		isl_die(isl_set_get_ctx(set), isl_error_internal,
7477 			"unexpected number of rows", goto error);
7478 
7479 	space = isl_set_get_space(set);
7480 	space = isl_space_move_dims(space, isl_dim_set, 0,
7481 				    isl_dim_param, 0, nparam);
7482 	set = isl_set_reset_space(set, space);
7483 	set = isl_set_preimage(set, mat);
7484 	nparam = isl_set_dim(set, isl_dim_out);
7485 	if (nparam < 0)
7486 		set = isl_set_free(set);
7487 	space = isl_set_get_space(set);
7488 	space = isl_space_move_dims(space, isl_dim_param, 0,
7489 				    isl_dim_out, 0, nparam);
7490 	set = isl_set_reset_space(set, space);
7491 	return set;
7492 error:
7493 	isl_mat_free(mat);
7494 	isl_set_free(set);
7495 	return NULL;
7496 }
7497 
7498 /* Intersect the basic set "bset" with the affine space specified by the
7499  * equalities in "eq".
7500  */
basic_set_append_equalities(__isl_take isl_basic_set * bset,__isl_take isl_mat * eq)7501 static __isl_give isl_basic_set *basic_set_append_equalities(
7502 	__isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7503 {
7504 	int i, k;
7505 	unsigned len;
7506 
7507 	if (!bset || !eq)
7508 		goto error;
7509 
7510 	bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);
7511 	if (!bset)
7512 		goto error;
7513 
7514 	len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7515 	for (i = 0; i < eq->n_row; ++i) {
7516 		k = isl_basic_set_alloc_equality(bset);
7517 		if (k < 0)
7518 			goto error;
7519 		isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7520 		isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7521 	}
7522 	isl_mat_free(eq);
7523 
7524 	bset = isl_basic_set_gauss(bset, NULL);
7525 	bset = isl_basic_set_finalize(bset);
7526 
7527 	return bset;
7528 error:
7529 	isl_mat_free(eq);
7530 	isl_basic_set_free(bset);
7531 	return NULL;
7532 }
7533 
7534 /* Intersect the set "set" with the affine space specified by the
7535  * equalities in "eq".
7536  */
set_append_equalities(__isl_take isl_set * set,__isl_take isl_mat * eq)7537 static __isl_give isl_set *set_append_equalities(__isl_take isl_set *set,
7538 	__isl_take isl_mat *eq)
7539 {
7540 	int i;
7541 
7542 	if (!set || !eq)
7543 		goto error;
7544 
7545 	for (i = 0; i < set->n; ++i) {
7546 		set->p[i] = basic_set_append_equalities(set->p[i],
7547 					isl_mat_copy(eq));
7548 		if (!set->p[i])
7549 			goto error;
7550 	}
7551 	isl_mat_free(eq);
7552 	return set;
7553 error:
7554 	isl_mat_free(eq);
7555 	isl_set_free(set);
7556 	return NULL;
7557 }
7558 
7559 /* Given a basic set "bset" that only involves parameters and existentially
7560  * quantified variables, return the index of the first equality
7561  * that only involves parameters.  If there is no such equality then
7562  * return bset->n_eq.
7563  *
7564  * This function assumes that isl_basic_set_gauss has been called on "bset".
7565  */
first_parameter_equality(__isl_keep isl_basic_set * bset)7566 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7567 {
7568 	int i, j;
7569 	isl_size nparam, n_div;
7570 
7571 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7572 	n_div = isl_basic_set_dim(bset, isl_dim_div);
7573 	if (nparam < 0 || n_div < 0)
7574 		return -1;
7575 
7576 	for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7577 		if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7578 			++i;
7579 	}
7580 
7581 	return i;
7582 }
7583 
7584 /* Compute an explicit representation for the existentially quantified
7585  * variables in "bset" by computing the "minimal value" of the set
7586  * variables.  Since there are no set variables, the computation of
7587  * the minimal value essentially computes an explicit representation
7588  * of the non-empty part(s) of "bset".
7589  *
7590  * The input only involves parameters and existentially quantified variables.
7591  * All equalities among parameters have been removed.
7592  *
7593  * Since the existentially quantified variables in the result are in general
7594  * going to be different from those in the input, we first replace
7595  * them by the minimal number of variables based on their equalities.
7596  * This should simplify the parametric integer programming.
7597  */
base_compute_divs(__isl_take isl_basic_set * bset)7598 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7599 {
7600 	isl_morph *morph1, *morph2;
7601 	isl_set *set;
7602 	isl_size n;
7603 
7604 	if (!bset)
7605 		return NULL;
7606 	if (bset->n_eq == 0)
7607 		return isl_basic_set_lexmin_compute_divs(bset);
7608 
7609 	morph1 = isl_basic_set_parameter_compression(bset);
7610 	bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7611 	bset = isl_basic_set_lift(bset);
7612 	morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7613 	bset = isl_morph_basic_set(morph2, bset);
7614 	n = isl_basic_set_dim(bset, isl_dim_set);
7615 	if (n < 0)
7616 		bset = isl_basic_set_free(bset);
7617 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7618 
7619 	set = isl_basic_set_lexmin_compute_divs(bset);
7620 
7621 	set = isl_morph_set(isl_morph_inverse(morph1), set);
7622 
7623 	return set;
7624 }
7625 
7626 /* Project the given basic set onto its parameter domain, possibly introducing
7627  * new, explicit, existential variables in the constraints.
7628  * The input has parameters and (possibly implicit) existential variables.
7629  * The output has the same parameters, but only
7630  * explicit existentially quantified variables.
7631  *
7632  * The actual projection is performed by pip, but pip doesn't seem
7633  * to like equalities very much, so we first remove the equalities
7634  * among the parameters by performing a variable compression on
7635  * the parameters.  Afterward, an inverse transformation is performed
7636  * and the equalities among the parameters are inserted back in.
7637  *
7638  * The variable compression on the parameters may uncover additional
7639  * equalities that were only implicit before.  We therefore check
7640  * if there are any new parameter equalities in the result and
7641  * if so recurse.  The removal of parameter equalities is required
7642  * for the parameter compression performed by base_compute_divs.
7643  */
parameter_compute_divs(__isl_take isl_basic_set * bset)7644 static __isl_give isl_set *parameter_compute_divs(
7645 	__isl_take isl_basic_set *bset)
7646 {
7647 	int i;
7648 	struct isl_mat *eq;
7649 	struct isl_mat *T, *T2;
7650 	struct isl_set *set;
7651 	isl_size nparam;
7652 
7653 	bset = isl_basic_set_cow(bset);
7654 	if (!bset)
7655 		return NULL;
7656 
7657 	if (bset->n_eq == 0)
7658 		return base_compute_divs(bset);
7659 
7660 	bset = isl_basic_set_gauss(bset, NULL);
7661 	if (!bset)
7662 		return NULL;
7663 	if (isl_basic_set_plain_is_empty(bset))
7664 		return isl_set_from_basic_set(bset);
7665 
7666 	i = first_parameter_equality(bset);
7667 	if (i == bset->n_eq)
7668 		return base_compute_divs(bset);
7669 
7670 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7671 	if (nparam < 0)
7672 		return isl_set_from_basic_set(isl_basic_set_free(bset));
7673 	eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7674 		0, 1 + nparam);
7675 	eq = isl_mat_cow(eq);
7676 	T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7677 	if (T && T->n_col == 0) {
7678 		isl_mat_free(T);
7679 		isl_mat_free(T2);
7680 		isl_mat_free(eq);
7681 		bset = isl_basic_set_set_to_empty(bset);
7682 		return isl_set_from_basic_set(bset);
7683 	}
7684 	bset = basic_set_parameter_preimage(bset, T);
7685 
7686 	i = first_parameter_equality(bset);
7687 	if (!bset)
7688 		set = NULL;
7689 	else if (i == bset->n_eq)
7690 		set = base_compute_divs(bset);
7691 	else
7692 		set = parameter_compute_divs(bset);
7693 	set = set_parameter_preimage(set, T2);
7694 	set = set_append_equalities(set, eq);
7695 	return set;
7696 }
7697 
7698 /* Insert the divs from "ls" before those of "bmap".
7699  *
7700  * The number of columns is not changed, which means that the last
7701  * dimensions of "bmap" are being reintepreted as the divs from "ls".
7702  * The caller is responsible for removing the same number of dimensions
7703  * from the space of "bmap".
7704  */
insert_divs_from_local_space(__isl_take isl_basic_map * bmap,__isl_keep isl_local_space * ls)7705 static __isl_give isl_basic_map *insert_divs_from_local_space(
7706 	__isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7707 {
7708 	int i;
7709 	isl_size n_div;
7710 	int old_n_div;
7711 
7712 	n_div = isl_local_space_dim(ls, isl_dim_div);
7713 	if (n_div < 0)
7714 		return isl_basic_map_free(bmap);
7715 	if (n_div == 0)
7716 		return bmap;
7717 
7718 	old_n_div = bmap->n_div;
7719 	bmap = insert_div_rows(bmap, n_div);
7720 	if (!bmap)
7721 		return NULL;
7722 
7723 	for (i = 0; i < n_div; ++i) {
7724 		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7725 		isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7726 	}
7727 
7728 	return bmap;
7729 }
7730 
7731 /* Replace the space of "bmap" by the space and divs of "ls".
7732  *
7733  * If "ls" has any divs, then we simplify the result since we may
7734  * have discovered some additional equalities that could simplify
7735  * the div expressions.
7736  */
basic_replace_space_by_local_space(__isl_take isl_basic_map * bmap,__isl_take isl_local_space * ls)7737 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7738 	__isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7739 {
7740 	isl_size n_div;
7741 
7742 	bmap = isl_basic_map_cow(bmap);
7743 	n_div = isl_local_space_dim(ls, isl_dim_div);
7744 	if (!bmap || n_div < 0)
7745 		goto error;
7746 
7747 	bmap = insert_divs_from_local_space(bmap, ls);
7748 	if (!bmap)
7749 		goto error;
7750 
7751 	isl_space_free(bmap->dim);
7752 	bmap->dim = isl_local_space_get_space(ls);
7753 	if (!bmap->dim)
7754 		goto error;
7755 
7756 	isl_local_space_free(ls);
7757 	if (n_div > 0)
7758 		bmap = isl_basic_map_simplify(bmap);
7759 	bmap = isl_basic_map_finalize(bmap);
7760 	return bmap;
7761 error:
7762 	isl_basic_map_free(bmap);
7763 	isl_local_space_free(ls);
7764 	return NULL;
7765 }
7766 
7767 /* Replace the space of "map" by the space and divs of "ls".
7768  */
replace_space_by_local_space(__isl_take isl_map * map,__isl_take isl_local_space * ls)7769 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7770 	__isl_take isl_local_space *ls)
7771 {
7772 	int i;
7773 
7774 	map = isl_map_cow(map);
7775 	if (!map || !ls)
7776 		goto error;
7777 
7778 	for (i = 0; i < map->n; ++i) {
7779 		map->p[i] = basic_replace_space_by_local_space(map->p[i],
7780 						    isl_local_space_copy(ls));
7781 		if (!map->p[i])
7782 			goto error;
7783 	}
7784 	isl_space_free(isl_map_take_space(map));
7785 	map = isl_map_restore_space(map, isl_local_space_get_space(ls));
7786 
7787 	isl_local_space_free(ls);
7788 	return map;
7789 error:
7790 	isl_local_space_free(ls);
7791 	isl_map_free(map);
7792 	return NULL;
7793 }
7794 
7795 /* Compute an explicit representation for the existentially
7796  * quantified variables for which do not know any explicit representation yet.
7797  *
7798  * We first sort the existentially quantified variables so that the
7799  * existentially quantified variables for which we already have an explicit
7800  * representation are placed before those for which we do not.
7801  * The input dimensions, the output dimensions and the existentially
7802  * quantified variables for which we already have an explicit
7803  * representation are then turned into parameters.
7804  * compute_divs returns a map with the same parameters and
7805  * no input or output dimensions and the dimension specification
7806  * is reset to that of the input, including the existentially quantified
7807  * variables for which we already had an explicit representation.
7808  */
compute_divs(__isl_take isl_basic_map * bmap)7809 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7810 {
7811 	struct isl_basic_set *bset;
7812 	struct isl_set *set;
7813 	struct isl_map *map;
7814 	isl_space *space;
7815 	isl_local_space *ls;
7816 	isl_size nparam;
7817 	isl_size n_in;
7818 	isl_size n_out;
7819 	int n_known;
7820 	int i;
7821 
7822 	bmap = isl_basic_map_sort_divs(bmap);
7823 	bmap = isl_basic_map_cow(bmap);
7824 	if (!bmap)
7825 		return NULL;
7826 
7827 	n_known = isl_basic_map_first_unknown_div(bmap);
7828 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
7829 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
7830 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
7831 	if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
7832 		return isl_map_from_basic_map(isl_basic_map_free(bmap));
7833 
7834 	space = isl_space_set_alloc(bmap->ctx,
7835 				    nparam + n_in + n_out + n_known, 0);
7836 	if (!space)
7837 		goto error;
7838 
7839 	ls = isl_basic_map_get_local_space(bmap);
7840 	ls = isl_local_space_drop_dims(ls, isl_dim_div,
7841 					n_known, bmap->n_div - n_known);
7842 	if (n_known > 0) {
7843 		for (i = n_known; i < bmap->n_div; ++i)
7844 			swap_div(bmap, i - n_known, i);
7845 		bmap->n_div -= n_known;
7846 		bmap->extra -= n_known;
7847 	}
7848 	bmap = isl_basic_map_reset_space(bmap, space);
7849 	bset = bset_from_bmap(bmap);
7850 
7851 	set = parameter_compute_divs(bset);
7852 	map = set_to_map(set);
7853 	map = replace_space_by_local_space(map, ls);
7854 
7855 	return map;
7856 error:
7857 	isl_basic_map_free(bmap);
7858 	return NULL;
7859 }
7860 
7861 /* Remove the explicit representation of local variable "div",
7862  * if there is any.
7863  */
isl_basic_map_mark_div_unknown(__isl_take isl_basic_map * bmap,int div)7864 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7865 	__isl_take isl_basic_map *bmap, int div)
7866 {
7867 	isl_bool unknown;
7868 
7869 	unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7870 	if (unknown < 0)
7871 		return isl_basic_map_free(bmap);
7872 	if (unknown)
7873 		return bmap;
7874 
7875 	bmap = isl_basic_map_cow(bmap);
7876 	if (!bmap)
7877 		return NULL;
7878 	isl_int_set_si(bmap->div[div][0], 0);
7879 	return bmap;
7880 }
7881 
7882 /* Is local variable "div" of "bmap" marked as not having an explicit
7883  * representation?
7884  * Note that even if "div" is not marked in this way and therefore
7885  * has an explicit representation, this representation may still
7886  * depend (indirectly) on other local variables that do not
7887  * have an explicit representation.
7888  */
isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map * bmap,int div)7889 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7890 	int div)
7891 {
7892 	if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7893 		return isl_bool_error;
7894 	return isl_int_is_zero(bmap->div[div][0]);
7895 }
7896 
7897 /* Return the position of the first local variable that does not
7898  * have an explicit representation.
7899  * Return the total number of local variables if they all have
7900  * an explicit representation.
7901  * Return -1 on error.
7902  */
isl_basic_map_first_unknown_div(__isl_keep isl_basic_map * bmap)7903 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7904 {
7905 	int i;
7906 
7907 	if (!bmap)
7908 		return -1;
7909 
7910 	for (i = 0; i < bmap->n_div; ++i) {
7911 		if (!isl_basic_map_div_is_known(bmap, i))
7912 			return i;
7913 	}
7914 	return bmap->n_div;
7915 }
7916 
7917 /* Return the position of the first local variable that does not
7918  * have an explicit representation.
7919  * Return the total number of local variables if they all have
7920  * an explicit representation.
7921  * Return -1 on error.
7922  */
isl_basic_set_first_unknown_div(__isl_keep isl_basic_set * bset)7923 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7924 {
7925 	return isl_basic_map_first_unknown_div(bset);
7926 }
7927 
7928 /* Does "bmap" have an explicit representation for all local variables?
7929  */
isl_basic_map_divs_known(__isl_keep isl_basic_map * bmap)7930 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7931 {
7932 	int first;
7933 	isl_size n;
7934 
7935 	n = isl_basic_map_dim(bmap, isl_dim_div);
7936 	first = isl_basic_map_first_unknown_div(bmap);
7937 	if (n < 0 || first < 0)
7938 		return isl_bool_error;
7939 	return first == n;
7940 }
7941 
7942 /* Do all basic maps in "map" have an explicit representation
7943  * for all local variables?
7944  */
isl_map_divs_known(__isl_keep isl_map * map)7945 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7946 {
7947 	int i;
7948 
7949 	if (!map)
7950 		return isl_bool_error;
7951 
7952 	for (i = 0; i < map->n; ++i) {
7953 		int known = isl_basic_map_divs_known(map->p[i]);
7954 		if (known <= 0)
7955 			return known;
7956 	}
7957 
7958 	return isl_bool_true;
7959 }
7960 
7961 /* If bmap contains any unknown divs, then compute explicit
7962  * expressions for them.  However, this computation may be
7963  * quite expensive, so first try to remove divs that aren't
7964  * strictly needed.
7965  */
isl_basic_map_compute_divs(__isl_take isl_basic_map * bmap)7966 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7967 {
7968 	int known;
7969 	struct isl_map *map;
7970 
7971 	known = isl_basic_map_divs_known(bmap);
7972 	if (known < 0)
7973 		goto error;
7974 	if (known)
7975 		return isl_map_from_basic_map(bmap);
7976 
7977 	bmap = isl_basic_map_drop_redundant_divs(bmap);
7978 
7979 	known = isl_basic_map_divs_known(bmap);
7980 	if (known < 0)
7981 		goto error;
7982 	if (known)
7983 		return isl_map_from_basic_map(bmap);
7984 
7985 	map = compute_divs(bmap);
7986 	return map;
7987 error:
7988 	isl_basic_map_free(bmap);
7989 	return NULL;
7990 }
7991 
isl_map_compute_divs(__isl_take isl_map * map)7992 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7993 {
7994 	int i;
7995 	int known;
7996 	struct isl_map *res;
7997 
7998 	if (!map)
7999 		return NULL;
8000 	if (map->n == 0)
8001 		return map;
8002 
8003 	known = isl_map_divs_known(map);
8004 	if (known < 0) {
8005 		isl_map_free(map);
8006 		return NULL;
8007 	}
8008 	if (known)
8009 		return map;
8010 
8011 	res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
8012 	for (i = 1 ; i < map->n; ++i) {
8013 		struct isl_map *r2;
8014 		r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
8015 		if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
8016 			res = isl_map_union_disjoint(res, r2);
8017 		else
8018 			res = isl_map_union(res, r2);
8019 	}
8020 	isl_map_free(map);
8021 
8022 	return res;
8023 }
8024 
isl_basic_set_compute_divs(__isl_take isl_basic_set * bset)8025 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
8026 {
8027 	return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
8028 }
8029 
isl_set_compute_divs(__isl_take isl_set * set)8030 __isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set)
8031 {
8032 	return set_from_map(isl_map_compute_divs(set_to_map(set)));
8033 }
8034 
isl_map_domain(__isl_take isl_map * map)8035 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
8036 {
8037 	isl_space *space;
8038 	isl_size n_out;
8039 
8040 	n_out = isl_map_dim(map, isl_dim_out);
8041 	if (n_out < 0)
8042 		return set_from_map(isl_map_free(map));
8043 	space = isl_space_domain(isl_map_get_space(map));
8044 
8045 	map = isl_map_project_out(map, isl_dim_out, 0, n_out);
8046 
8047 	return set_from_map(isl_map_reset_space(map, space));
8048 }
8049 
8050 /* Return the union of "map1" and "map2", where we assume for now that
8051  * "map1" and "map2" are disjoint.  Note that the basic maps inside
8052  * "map1" or "map2" may not be disjoint from each other.
8053  * Also note that this function is also called from isl_map_union,
8054  * which takes care of handling the situation where "map1" and "map2"
8055  * may not be disjoint.
8056  *
8057  * If one of the inputs is empty, we can simply return the other input.
8058  * Similarly, if one of the inputs is universal, then it is equal to the union.
8059  */
map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8060 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
8061 	__isl_take isl_map *map2)
8062 {
8063 	int i;
8064 	unsigned flags = 0;
8065 	struct isl_map *map = NULL;
8066 	int is_universe;
8067 
8068 	if (isl_map_check_equal_space(map1, map2) < 0)
8069 		goto error;
8070 
8071 	if (map1->n == 0) {
8072 		isl_map_free(map1);
8073 		return map2;
8074 	}
8075 	if (map2->n == 0) {
8076 		isl_map_free(map2);
8077 		return map1;
8078 	}
8079 
8080 	is_universe = isl_map_plain_is_universe(map1);
8081 	if (is_universe < 0)
8082 		goto error;
8083 	if (is_universe) {
8084 		isl_map_free(map2);
8085 		return map1;
8086 	}
8087 
8088 	is_universe = isl_map_plain_is_universe(map2);
8089 	if (is_universe < 0)
8090 		goto error;
8091 	if (is_universe) {
8092 		isl_map_free(map1);
8093 		return map2;
8094 	}
8095 
8096 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
8097 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
8098 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8099 
8100 	map = isl_map_alloc_space(isl_space_copy(map1->dim),
8101 				map1->n + map2->n, flags);
8102 	if (!map)
8103 		goto error;
8104 	for (i = 0; i < map1->n; ++i) {
8105 		map = isl_map_add_basic_map(map,
8106 				  isl_basic_map_copy(map1->p[i]));
8107 		if (!map)
8108 			goto error;
8109 	}
8110 	for (i = 0; i < map2->n; ++i) {
8111 		map = isl_map_add_basic_map(map,
8112 				  isl_basic_map_copy(map2->p[i]));
8113 		if (!map)
8114 			goto error;
8115 	}
8116 	isl_map_free(map1);
8117 	isl_map_free(map2);
8118 	return map;
8119 error:
8120 	isl_map_free(map);
8121 	isl_map_free(map1);
8122 	isl_map_free(map2);
8123 	return NULL;
8124 }
8125 
8126 /* Return the union of "map1" and "map2", where "map1" and "map2" are
8127  * guaranteed to be disjoint by the caller.
8128  *
8129  * Note that this functions is called from within isl_map_make_disjoint,
8130  * so we have to be careful not to touch the constraints of the inputs
8131  * in any way.
8132  */
isl_map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8133 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
8134 	__isl_take isl_map *map2)
8135 {
8136 	isl_map_align_params_bin(&map1, &map2);
8137 	return map_union_disjoint(map1, map2);
8138 }
8139 
8140 /* Return the union of "map1" and "map2", where "map1" and "map2" may
8141  * not be disjoint.
8142  *
8143  * We currently simply call map_union_disjoint, the internal operation
8144  * of which does not really depend on the inputs being disjoint.
8145  * If the result contains more than one basic map, then we clear
8146  * the disjoint flag since the result may contain basic maps from
8147  * both inputs and these are not guaranteed to be disjoint.
8148  *
8149  * As a special case, if "map1" and "map2" are obviously equal,
8150  * then we simply return "map1".
8151  */
isl_map_union(__isl_take isl_map * map1,__isl_take isl_map * map2)8152 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
8153 	__isl_take isl_map *map2)
8154 {
8155 	int equal;
8156 
8157 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8158 		goto error;
8159 
8160 	equal = isl_map_plain_is_equal(map1, map2);
8161 	if (equal < 0)
8162 		goto error;
8163 	if (equal) {
8164 		isl_map_free(map2);
8165 		return map1;
8166 	}
8167 
8168 	map1 = map_union_disjoint(map1, map2);
8169 	if (!map1)
8170 		return NULL;
8171 	if (map1->n > 1)
8172 		ISL_F_CLR(map1, ISL_MAP_DISJOINT);
8173 	return map1;
8174 error:
8175 	isl_map_free(map1);
8176 	isl_map_free(map2);
8177 	return NULL;
8178 }
8179 
isl_set_union_disjoint(__isl_take isl_set * set1,__isl_take isl_set * set2)8180 __isl_give isl_set *isl_set_union_disjoint(
8181 	__isl_take isl_set *set1, __isl_take isl_set *set2)
8182 {
8183 	return set_from_map(isl_map_union_disjoint(set_to_map(set1),
8184 						    set_to_map(set2)));
8185 }
8186 
isl_set_union(__isl_take isl_set * set1,__isl_take isl_set * set2)8187 __isl_give isl_set *isl_set_union(__isl_take isl_set *set1,
8188 	__isl_take isl_set *set2)
8189 {
8190 	return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
8191 }
8192 
8193 /* Apply "fn" to pairs of elements from "map" and "set" and collect
8194  * the results in a map living in "space".
8195  *
8196  * "map" and "set" are assumed to be compatible and non-NULL.
8197  */
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))8198 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
8199 	__isl_take isl_space *space, __isl_take isl_set *set,
8200 	__isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
8201 		__isl_take isl_basic_set *bset))
8202 {
8203 	unsigned flags = 0;
8204 	struct isl_map *result;
8205 	int i, j;
8206 
8207 	if (isl_set_plain_is_universe(set)) {
8208 		isl_set_free(set);
8209 		return isl_map_reset_equal_dim_space(map, space);
8210 	}
8211 
8212 	if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
8213 	    ISL_F_ISSET(set, ISL_MAP_DISJOINT))
8214 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8215 
8216 	result = isl_map_alloc_space(space, map->n * set->n, flags);
8217 	for (i = 0; result && i < map->n; ++i)
8218 		for (j = 0; j < set->n; ++j) {
8219 			result = isl_map_add_basic_map(result,
8220 					fn(isl_basic_map_copy(map->p[i]),
8221 					    isl_basic_set_copy(set->p[j])));
8222 			if (!result)
8223 				break;
8224 		}
8225 
8226 	isl_map_free(map);
8227 	isl_set_free(set);
8228 	return result;
8229 }
8230 
isl_map_intersect_range(__isl_take isl_map * map,__isl_take isl_set * set)8231 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
8232 	__isl_take isl_set *set)
8233 {
8234 	isl_bool ok;
8235 	isl_space *space;
8236 
8237 	isl_map_align_params_set(&map, &set);
8238 	ok = isl_map_compatible_range(map, set);
8239 	if (ok < 0)
8240 		goto error;
8241 	if (!ok)
8242 		isl_die(set->ctx, isl_error_invalid,
8243 			"incompatible spaces", goto error);
8244 
8245 	space = isl_map_get_space(map);
8246 	return map_intersect_set(map, space, set,
8247 				&isl_basic_map_intersect_range);
8248 error:
8249 	isl_map_free(map);
8250 	isl_set_free(set);
8251 	return NULL;
8252 }
8253 
8254 /* Intersect the domain of "map" with "set".
8255  *
8256  * If the domain dimensions of "map" do not have any identifiers,
8257  * then copy them over from "set".
8258  */
isl_map_intersect_domain(__isl_take isl_map * map,__isl_take isl_set * set)8259 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
8260 	__isl_take isl_set *set)
8261 {
8262 	isl_bool ok;
8263 	isl_space *space;
8264 
8265 	isl_map_align_params_set(&map, &set);
8266 	ok = isl_map_compatible_domain(map, set);
8267 	if (ok < 0)
8268 		goto error;
8269 	if (!ok)
8270 		isl_die(set->ctx, isl_error_invalid,
8271 			"incompatible spaces", goto error);
8272 
8273 	space = isl_map_get_space(map);
8274 	space = isl_space_copy_ids_if_unset(space, isl_dim_in,
8275 					isl_set_peek_space(set), isl_dim_set);
8276 	return map_intersect_set(map, space, set,
8277 				&isl_basic_map_intersect_domain);
8278 error:
8279 	isl_map_free(map);
8280 	isl_set_free(set);
8281 	return NULL;
8282 }
8283 
8284 #undef TYPE
8285 #define TYPE isl_map
8286 static
8287 #include "isl_copy_tuple_id_templ.c"
8288 
8289 /* Data structure that specifies how isl_map_intersect_factor
8290  * should operate.
8291  *
8292  * "preserve_type" is the tuple where the factor differs from
8293  * the input map and of which the identifiers needs
8294  * to be preserved explicitly.
8295  * "other_factor" is used to extract the space of the other factor
8296  * from the space of the product ("map").
8297  * "product" is used to combine the given factor and a universe map
8298  * in the space returned by "other_factor" to produce a map
8299  * that lives in the same space as the input map.
8300  */
8301 struct isl_intersect_factor_control {
8302 	enum isl_dim_type preserve_type;
8303 	__isl_give isl_space *(*other_factor)(__isl_take isl_space *space);
8304 	__isl_give isl_map *(*product)(__isl_take isl_map *factor,
8305 		__isl_take isl_map *other);
8306 };
8307 
8308 /* Given a map "map" in some product space and a map "factor"
8309  * living in some factor space, return the intersection.
8310  *
8311  * After aligning the parameters,
8312  * the map "factor" is first extended to a map living in the same space
8313  * as "map" and then a regular intersection is computed.
8314  *
8315  * Note that the extension is computed as a product, which is anonymous
8316  * by default.  If "map" has an identifier on the corresponding tuple,
8317  * then this identifier needs to be set on the product
8318  * before the intersection is computed.
8319  */
isl_map_intersect_factor(__isl_take isl_map * map,__isl_take isl_map * factor,struct isl_intersect_factor_control * control)8320 static __isl_give isl_map *isl_map_intersect_factor(
8321 	__isl_take isl_map *map, __isl_take isl_map *factor,
8322 	struct isl_intersect_factor_control *control)
8323 {
8324 	isl_bool equal;
8325 	isl_space *space;
8326 	isl_map *other, *product;
8327 
8328 	equal = isl_map_has_equal_params(map, factor);
8329 	if (equal < 0)
8330 		goto error;
8331 	if (!equal) {
8332 		map = isl_map_align_params(map, isl_map_get_space(factor));
8333 		factor = isl_map_align_params(factor, isl_map_get_space(map));
8334 	}
8335 
8336 	space = isl_map_get_space(map);
8337 	other = isl_map_universe(control->other_factor(space));
8338 	product = control->product(factor, other);
8339 
8340 	space = isl_map_peek_space(map);
8341 	product = isl_map_copy_tuple_id(product, control->preserve_type,
8342 					space, control->preserve_type);
8343 	return map_intersect(map, product);
8344 error:
8345 	isl_map_free(map);
8346 	isl_map_free(factor);
8347 	return NULL;
8348 }
8349 
8350 /* Return the domain product of "map2" and "map1".
8351  */
isl_map_reverse_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8352 static __isl_give isl_map *isl_map_reverse_domain_product(
8353 	__isl_take isl_map *map1, __isl_take isl_map *map2)
8354 {
8355 	return isl_map_domain_product(map2, map1);
8356 }
8357 
8358 /* Return the range product of "map2" and "map1".
8359  */
isl_map_reverse_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8360 static __isl_give isl_map *isl_map_reverse_range_product(
8361 	__isl_take isl_map *map1, __isl_take isl_map *map2)
8362 {
8363 	return isl_map_range_product(map2, map1);
8364 }
8365 
8366 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8367  * in the space A -> C, return the intersection.
8368  */
isl_map_intersect_domain_factor_domain(__isl_take isl_map * map,__isl_take isl_map * factor)8369 __isl_give isl_map *isl_map_intersect_domain_factor_domain(
8370 	__isl_take isl_map *map, __isl_take isl_map *factor)
8371 {
8372 	struct isl_intersect_factor_control control = {
8373 		.preserve_type = isl_dim_in,
8374 		.other_factor = isl_space_domain_factor_range,
8375 		.product = isl_map_domain_product,
8376 	};
8377 
8378 	return isl_map_intersect_factor(map, factor, &control);
8379 }
8380 
8381 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8382  * in the space B -> C, return the intersection.
8383  */
isl_map_intersect_domain_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8384 __isl_give isl_map *isl_map_intersect_domain_factor_range(
8385 	__isl_take isl_map *map, __isl_take isl_map *factor)
8386 {
8387 	struct isl_intersect_factor_control control = {
8388 		.preserve_type = isl_dim_in,
8389 		.other_factor = isl_space_domain_factor_domain,
8390 		.product = isl_map_reverse_domain_product,
8391 	};
8392 
8393 	return isl_map_intersect_factor(map, factor, &control);
8394 }
8395 
8396 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8397  * in the space A -> B, return the intersection.
8398  */
isl_map_intersect_range_factor_domain(__isl_take isl_map * map,__isl_take isl_map * factor)8399 __isl_give isl_map *isl_map_intersect_range_factor_domain(
8400 	__isl_take isl_map *map, __isl_take isl_map *factor)
8401 {
8402 	struct isl_intersect_factor_control control = {
8403 		.preserve_type = isl_dim_out,
8404 		.other_factor = isl_space_range_factor_range,
8405 		.product = isl_map_range_product,
8406 	};
8407 
8408 	return isl_map_intersect_factor(map, factor, &control);
8409 }
8410 
8411 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8412  * in the space A -> C, return the intersection.
8413  */
isl_map_intersect_range_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8414 __isl_give isl_map *isl_map_intersect_range_factor_range(
8415 	__isl_take isl_map *map, __isl_take isl_map *factor)
8416 {
8417 	struct isl_intersect_factor_control control = {
8418 		.preserve_type = isl_dim_out,
8419 		.other_factor = isl_space_range_factor_domain,
8420 		.product = isl_map_reverse_range_product,
8421 	};
8422 
8423 	return isl_map_intersect_factor(map, factor, &control);
8424 }
8425 
8426 /* Given a set "set" in a space [A -> B] and a set "domain"
8427  * in the space A, return the intersection.
8428  *
8429  * The set "domain" is first extended to a set living in the space
8430  * [A -> B] and then a regular intersection is computed.
8431  */
isl_set_intersect_factor_domain(__isl_take isl_set * set,__isl_take isl_set * domain)8432 __isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
8433 	__isl_take isl_set *domain)
8434 {
8435 	struct isl_intersect_factor_control control = {
8436 		.preserve_type = isl_dim_set,
8437 		.other_factor = isl_space_factor_range,
8438 		.product = isl_map_range_product,
8439 	};
8440 
8441 	return set_from_map(isl_map_intersect_factor(set_to_map(set),
8442 						set_to_map(domain), &control));
8443 }
8444 
8445 /* Given a set "set" in a space [A -> B] and a set "range"
8446  * in the space B, return the intersection.
8447  *
8448  * The set "range" is first extended to a set living in the space
8449  * [A -> B] and then a regular intersection is computed.
8450  */
isl_set_intersect_factor_range(__isl_take isl_set * set,__isl_take isl_set * range)8451 __isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
8452 	__isl_take isl_set *range)
8453 {
8454 	struct isl_intersect_factor_control control = {
8455 		.preserve_type = isl_dim_set,
8456 		.other_factor = isl_space_factor_domain,
8457 		.product = isl_map_reverse_range_product,
8458 	};
8459 
8460 	return set_from_map(isl_map_intersect_factor(set_to_map(set),
8461 						set_to_map(range), &control));
8462 }
8463 
isl_map_apply_domain(__isl_take isl_map * map1,__isl_take isl_map * map2)8464 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8465 	__isl_take isl_map *map2)
8466 {
8467 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8468 		goto error;
8469 	map1 = isl_map_reverse(map1);
8470 	map1 = isl_map_apply_range(map1, map2);
8471 	return isl_map_reverse(map1);
8472 error:
8473 	isl_map_free(map1);
8474 	isl_map_free(map2);
8475 	return NULL;
8476 }
8477 
isl_map_apply_range(__isl_take isl_map * map1,__isl_take isl_map * map2)8478 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8479 	__isl_take isl_map *map2)
8480 {
8481 	isl_space *space;
8482 	struct isl_map *result;
8483 	int i, j;
8484 
8485 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8486 		goto error;
8487 
8488 	space = isl_space_join(isl_space_copy(map1->dim),
8489 				  isl_space_copy(map2->dim));
8490 
8491 	result = isl_map_alloc_space(space, map1->n * map2->n, 0);
8492 	if (!result)
8493 		goto error;
8494 	for (i = 0; i < map1->n; ++i)
8495 		for (j = 0; j < map2->n; ++j) {
8496 			result = isl_map_add_basic_map(result,
8497 			    isl_basic_map_apply_range(
8498 				isl_basic_map_copy(map1->p[i]),
8499 				isl_basic_map_copy(map2->p[j])));
8500 			if (!result)
8501 				goto error;
8502 		}
8503 	isl_map_free(map1);
8504 	isl_map_free(map2);
8505 	if (result && result->n <= 1)
8506 		ISL_F_SET(result, ISL_MAP_DISJOINT);
8507 	return result;
8508 error:
8509 	isl_map_free(map1);
8510 	isl_map_free(map2);
8511 	return NULL;
8512 }
8513 
8514 /* Is "bmap" a transformation, i.e.,
8515  * does it relate elements from the same space.
8516  */
isl_basic_map_is_transformation(__isl_keep isl_basic_map * bmap)8517 isl_bool isl_basic_map_is_transformation(__isl_keep isl_basic_map *bmap)
8518 {
8519 	isl_space *space;
8520 
8521 	space = isl_basic_map_peek_space(bmap);
8522 	return isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8523 }
8524 
8525 /* Check that "bmap" is a transformation, i.e.,
8526  * that it relates elements from the same space.
8527  */
isl_basic_map_check_transformation(__isl_keep isl_basic_map * bmap)8528 static isl_stat isl_basic_map_check_transformation(
8529 	__isl_keep isl_basic_map *bmap)
8530 {
8531 	isl_bool equal;
8532 
8533 	equal = isl_basic_map_is_transformation(bmap);
8534 	if (equal < 0)
8535 		return isl_stat_error;
8536 	if (!equal)
8537 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
8538 			"domain and range don't match", return isl_stat_error);
8539 	return isl_stat_ok;
8540 }
8541 
8542 /*
8543  * returns range - domain
8544  */
isl_basic_map_deltas(__isl_take isl_basic_map * bmap)8545 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8546 {
8547 	isl_space *target_space;
8548 	struct isl_basic_set *bset;
8549 	isl_size dim;
8550 	isl_size nparam;
8551 	isl_size total;
8552 	int i;
8553 
8554 	if (isl_basic_map_check_transformation(bmap) < 0)
8555 		return isl_basic_map_free(bmap);
8556 	dim = isl_basic_map_dim(bmap, isl_dim_in);
8557 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
8558 	if (dim < 0 || nparam < 0)
8559 		goto error;
8560 	target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8561 	bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8562 	bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8563 	total = isl_basic_map_dim(bmap, isl_dim_all);
8564 	if (total < 0)
8565 		bmap = isl_basic_map_free(bmap);
8566 	bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8567 	for (i = 0; i < dim; ++i) {
8568 		int j = isl_basic_map_alloc_equality(bmap);
8569 		if (j < 0) {
8570 			bmap = isl_basic_map_free(bmap);
8571 			break;
8572 		}
8573 		isl_seq_clr(bmap->eq[j], 1 + total);
8574 		isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8575 		isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8576 		isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8577 	}
8578 	bset = isl_basic_map_domain(bmap);
8579 	bset = isl_basic_set_reset_space(bset, target_space);
8580 	return bset;
8581 error:
8582 	isl_basic_map_free(bmap);
8583 	return NULL;
8584 }
8585 
8586 /* Is the tuple of type "type1" of "map" the same as
8587  * the tuple of type "type2" of "space"?
8588  */
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)8589 isl_bool isl_map_space_tuple_is_equal(__isl_keep isl_map *map,
8590 	enum isl_dim_type type1, __isl_keep isl_space *space,
8591 	enum isl_dim_type type2)
8592 {
8593 	isl_space *map_space;
8594 
8595 	map_space = isl_map_peek_space(map);
8596 	return isl_space_tuple_is_equal(map_space, type1, space, type2);
8597 }
8598 
8599 /* Is the tuple of type "type1" of "map1" the same as
8600  * the tuple of type "type2" of "map2"?
8601  */
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)8602 isl_bool isl_map_tuple_is_equal(__isl_keep isl_map *map1,
8603 	enum isl_dim_type type1, __isl_keep isl_map *map2,
8604 	enum isl_dim_type type2)
8605 {
8606 	isl_space *space1, *space2;
8607 
8608 	space1 = isl_map_peek_space(map1);
8609 	space2 = isl_map_peek_space(map2);
8610 	return isl_space_tuple_is_equal(space1, type1, space2, type2);
8611 }
8612 
8613 /* Is the space of "obj" equal to "space", ignoring parameters?
8614  */
isl_map_has_space_tuples(__isl_keep isl_map * map,__isl_keep isl_space * space)8615 isl_bool isl_map_has_space_tuples(__isl_keep isl_map *map,
8616 	__isl_keep isl_space *space)
8617 {
8618 	isl_space *map_space;
8619 
8620 	map_space = isl_map_peek_space(map);
8621 	return isl_space_has_equal_tuples(map_space, space);
8622 }
8623 
8624 /* Check that "map" is a transformation, i.e.,
8625  * that it relates elements from the same space.
8626  */
isl_map_check_transformation(__isl_keep isl_map * map)8627 isl_stat isl_map_check_transformation(__isl_keep isl_map *map)
8628 {
8629 	isl_bool equal;
8630 
8631 	equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
8632 	if (equal < 0)
8633 		return isl_stat_error;
8634 	if (!equal)
8635 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
8636 			"domain and range don't match", return isl_stat_error);
8637 	return isl_stat_ok;
8638 }
8639 
8640 /*
8641  * returns range - domain
8642  */
isl_map_deltas(__isl_take isl_map * map)8643 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8644 {
8645 	int i;
8646 	isl_space *space;
8647 	struct isl_set *result;
8648 
8649 	if (isl_map_check_transformation(map) < 0)
8650 		goto error;
8651 	space = isl_map_get_space(map);
8652 	space = isl_space_domain(space);
8653 	result = isl_set_alloc_space(space, map->n, 0);
8654 	if (!result)
8655 		goto error;
8656 	for (i = 0; i < map->n; ++i)
8657 		result = isl_set_add_basic_set(result,
8658 			  isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8659 	isl_map_free(map);
8660 	return result;
8661 error:
8662 	isl_map_free(map);
8663 	return NULL;
8664 }
8665 
8666 /*
8667  * returns [domain -> range] -> range - domain
8668  */
isl_basic_map_deltas_map(__isl_take isl_basic_map * bmap)8669 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8670 	__isl_take isl_basic_map *bmap)
8671 {
8672 	int i, k;
8673 	isl_space *space;
8674 	isl_basic_map *domain;
8675 	isl_size nparam, n;
8676 	isl_size total;
8677 
8678 	if (isl_basic_map_check_transformation(bmap) < 0)
8679 		return isl_basic_map_free(bmap);
8680 
8681 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
8682 	n = isl_basic_map_dim(bmap, isl_dim_in);
8683 	if (nparam < 0 || n < 0)
8684 		return isl_basic_map_free(bmap);
8685 
8686 	space = isl_basic_map_get_space(bmap);
8687 	space = isl_space_from_range(isl_space_domain(space));
8688 	domain = isl_basic_map_universe(space);
8689 
8690 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8691 	bmap = isl_basic_map_apply_range(bmap, domain);
8692 	bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8693 
8694 	total = isl_basic_map_dim(bmap, isl_dim_all);
8695 	if (total < 0)
8696 		return isl_basic_map_free(bmap);
8697 
8698 	for (i = 0; i < n; ++i) {
8699 		k = isl_basic_map_alloc_equality(bmap);
8700 		if (k < 0)
8701 			goto error;
8702 		isl_seq_clr(bmap->eq[k], 1 + total);
8703 		isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8704 		isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8705 		isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8706 	}
8707 
8708 	bmap = isl_basic_map_gauss(bmap, NULL);
8709 	return isl_basic_map_finalize(bmap);
8710 error:
8711 	isl_basic_map_free(bmap);
8712 	return NULL;
8713 }
8714 
8715 /*
8716  * returns [domain -> range] -> range - domain
8717  */
isl_map_deltas_map(__isl_take isl_map * map)8718 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8719 {
8720 	if (isl_map_check_transformation(map) < 0)
8721 		return isl_map_free(map);
8722 
8723 	return isl_map_transform(map, &isl_space_range_map,
8724 					&isl_basic_map_deltas_map);
8725 }
8726 
8727 /* Return pairs of elements { x -> y } such that y - x is in "deltas".
8728  */
isl_set_translation(__isl_take isl_set * deltas)8729 __isl_give isl_map *isl_set_translation(__isl_take isl_set *deltas)
8730 {
8731 	isl_space *space;
8732 	isl_map *map;
8733 
8734 	space = isl_space_map_from_set(isl_set_get_space(deltas));
8735 	map = isl_map_deltas_map(isl_map_universe(space));
8736 	map = isl_map_intersect_range(map, deltas);
8737 
8738 	return isl_set_unwrap(isl_map_domain(map));
8739 }
8740 
isl_basic_map_identity(__isl_take isl_space * space)8741 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8742 {
8743 	isl_size n_in, n_out;
8744 
8745 	n_in = isl_space_dim(space, isl_dim_in);
8746 	n_out = isl_space_dim(space, isl_dim_out);
8747 	if (n_in < 0 || n_out < 0)
8748 		goto error;
8749 	if (n_in != n_out)
8750 		isl_die(space->ctx, isl_error_invalid,
8751 			"number of input and output dimensions needs to be "
8752 			"the same", goto error);
8753 	return isl_basic_map_equal(space, n_in);
8754 error:
8755 	isl_space_free(space);
8756 	return NULL;
8757 }
8758 
isl_map_identity(__isl_take isl_space * space)8759 __isl_give isl_map *isl_map_identity(__isl_take isl_space *space)
8760 {
8761 	return isl_map_from_basic_map(isl_basic_map_identity(space));
8762 }
8763 
isl_set_identity(__isl_take isl_set * set)8764 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8765 {
8766 	isl_space *space = isl_set_get_space(set);
8767 	isl_map *id;
8768 	id = isl_map_identity(isl_space_map_from_set(space));
8769 	return isl_map_intersect_range(id, set);
8770 }
8771 
8772 /* Construct a basic set with all set dimensions having only non-negative
8773  * values.
8774  */
isl_basic_set_positive_orthant(__isl_take isl_space * space)8775 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8776 	__isl_take isl_space *space)
8777 {
8778 	int i;
8779 	isl_size nparam;
8780 	isl_size dim;
8781 	isl_size total;
8782 	struct isl_basic_set *bset;
8783 
8784 	nparam = isl_space_dim(space, isl_dim_param);
8785 	dim = isl_space_dim(space, isl_dim_set);
8786 	total = isl_space_dim(space, isl_dim_all);
8787 	if (nparam < 0 || dim < 0 || total < 0)
8788 		space = isl_space_free(space);
8789 	bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8790 	if (!bset)
8791 		return NULL;
8792 	for (i = 0; i < dim; ++i) {
8793 		int k = isl_basic_set_alloc_inequality(bset);
8794 		if (k < 0)
8795 			goto error;
8796 		isl_seq_clr(bset->ineq[k], 1 + total);
8797 		isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8798 	}
8799 	return bset;
8800 error:
8801 	isl_basic_set_free(bset);
8802 	return NULL;
8803 }
8804 
8805 /* Construct the half-space x_pos >= 0.
8806  */
nonneg_halfspace(__isl_take isl_space * space,int pos)8807 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8808 	int pos)
8809 {
8810 	int k;
8811 	isl_size total;
8812 	isl_basic_set *nonneg;
8813 
8814 	total = isl_space_dim(space, isl_dim_all);
8815 	if (total < 0)
8816 		space = isl_space_free(space);
8817 	nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8818 	k = isl_basic_set_alloc_inequality(nonneg);
8819 	if (k < 0)
8820 		goto error;
8821 	isl_seq_clr(nonneg->ineq[k], 1 + total);
8822 	isl_int_set_si(nonneg->ineq[k][pos], 1);
8823 
8824 	return isl_basic_set_finalize(nonneg);
8825 error:
8826 	isl_basic_set_free(nonneg);
8827 	return NULL;
8828 }
8829 
8830 /* Construct the half-space x_pos <= -1.
8831  */
neg_halfspace(__isl_take isl_space * space,int pos)8832 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8833 	int pos)
8834 {
8835 	int k;
8836 	isl_size total;
8837 	isl_basic_set *neg;
8838 
8839 	total = isl_space_dim(space, isl_dim_all);
8840 	if (total < 0)
8841 		space = isl_space_free(space);
8842 	neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8843 	k = isl_basic_set_alloc_inequality(neg);
8844 	if (k < 0)
8845 		goto error;
8846 	isl_seq_clr(neg->ineq[k], 1 + total);
8847 	isl_int_set_si(neg->ineq[k][0], -1);
8848 	isl_int_set_si(neg->ineq[k][pos], -1);
8849 
8850 	return isl_basic_set_finalize(neg);
8851 error:
8852 	isl_basic_set_free(neg);
8853 	return NULL;
8854 }
8855 
isl_set_split_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)8856 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8857 	enum isl_dim_type type, unsigned first, unsigned n)
8858 {
8859 	int i;
8860 	unsigned offset;
8861 	isl_basic_set *nonneg;
8862 	isl_basic_set *neg;
8863 
8864 	if (n == 0)
8865 		return set;
8866 
8867 	if (isl_set_check_range(set, type, first, n) < 0)
8868 		return isl_set_free(set);
8869 
8870 	offset = pos(set->dim, type);
8871 	for (i = 0; i < n; ++i) {
8872 		nonneg = nonneg_halfspace(isl_set_get_space(set),
8873 					  offset + first + i);
8874 		neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8875 
8876 		set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8877 	}
8878 
8879 	return set;
8880 }
8881 
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)8882 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8883 	int len,
8884 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8885 	void *user)
8886 {
8887 	isl_set *half;
8888 
8889 	if (!set)
8890 		return isl_stat_error;
8891 	if (isl_set_plain_is_empty(set)) {
8892 		isl_set_free(set);
8893 		return isl_stat_ok;
8894 	}
8895 	if (first == len)
8896 		return fn(set, signs, user);
8897 
8898 	signs[first] = 1;
8899 	half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8900 							1 + first));
8901 	half = isl_set_intersect(half, isl_set_copy(set));
8902 	if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8903 		goto error;
8904 
8905 	signs[first] = -1;
8906 	half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8907 							1 + first));
8908 	half = isl_set_intersect(half, set);
8909 	return foreach_orthant(half, signs, first + 1, len, fn, user);
8910 error:
8911 	isl_set_free(set);
8912 	return isl_stat_error;
8913 }
8914 
8915 /* Call "fn" on the intersections of "set" with each of the orthants
8916  * (except for obviously empty intersections).  The orthant is identified
8917  * by the signs array, with each entry having value 1 or -1 according
8918  * to the sign of the corresponding variable.
8919  */
isl_set_foreach_orthant(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_set * orthant,int * signs,void * user),void * user)8920 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8921 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8922 	void *user)
8923 {
8924 	isl_size nparam;
8925 	isl_size nvar;
8926 	int *signs;
8927 	isl_stat r;
8928 
8929 	if (!set)
8930 		return isl_stat_error;
8931 	if (isl_set_plain_is_empty(set))
8932 		return isl_stat_ok;
8933 
8934 	nparam = isl_set_dim(set, isl_dim_param);
8935 	nvar = isl_set_dim(set, isl_dim_set);
8936 	if (nparam < 0 || nvar < 0)
8937 		return isl_stat_error;
8938 
8939 	signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8940 
8941 	r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8942 			    fn, user);
8943 
8944 	free(signs);
8945 
8946 	return r;
8947 }
8948 
isl_set_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)8949 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8950 {
8951 	return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8952 }
8953 
isl_basic_map_is_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8954 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8955 	__isl_keep isl_basic_map *bmap2)
8956 {
8957 	isl_bool is_subset;
8958 	struct isl_map *map1;
8959 	struct isl_map *map2;
8960 
8961 	if (!bmap1 || !bmap2)
8962 		return isl_bool_error;
8963 
8964 	map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8965 	map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8966 
8967 	is_subset = isl_map_is_subset(map1, map2);
8968 
8969 	isl_map_free(map1);
8970 	isl_map_free(map2);
8971 
8972 	return is_subset;
8973 }
8974 
isl_basic_set_is_subset(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8975 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8976 	__isl_keep isl_basic_set *bset2)
8977 {
8978 	return isl_basic_map_is_subset(bset1, bset2);
8979 }
8980 
isl_basic_map_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8981 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8982 	__isl_keep isl_basic_map *bmap2)
8983 {
8984 	isl_bool is_subset;
8985 
8986 	if (!bmap1 || !bmap2)
8987 		return isl_bool_error;
8988 	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8989 	if (is_subset != isl_bool_true)
8990 		return is_subset;
8991 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8992 	return is_subset;
8993 }
8994 
isl_basic_set_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8995 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8996 	__isl_keep isl_basic_set *bset2)
8997 {
8998 	return isl_basic_map_is_equal(
8999 		bset_to_bmap(bset1), bset_to_bmap(bset2));
9000 }
9001 
isl_map_is_empty(__isl_keep isl_map * map)9002 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
9003 {
9004 	int i;
9005 	int is_empty;
9006 
9007 	if (!map)
9008 		return isl_bool_error;
9009 	for (i = 0; i < map->n; ++i) {
9010 		is_empty = isl_basic_map_is_empty(map->p[i]);
9011 		if (is_empty < 0)
9012 			return isl_bool_error;
9013 		if (!is_empty)
9014 			return isl_bool_false;
9015 	}
9016 	return isl_bool_true;
9017 }
9018 
isl_map_plain_is_empty(__isl_keep isl_map * map)9019 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
9020 {
9021 	return map ? map->n == 0 : isl_bool_error;
9022 }
9023 
isl_set_plain_is_empty(__isl_keep isl_set * set)9024 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
9025 {
9026 	return set ? set->n == 0 : isl_bool_error;
9027 }
9028 
isl_set_is_empty(__isl_keep isl_set * set)9029 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
9030 {
9031 	return isl_map_is_empty(set_to_map(set));
9032 }
9033 
9034 #undef TYPE
9035 #define TYPE	isl_basic_map
9036 
9037 static
9038 #include "isl_type_has_equal_space_bin_templ.c"
9039 #include "isl_type_check_equal_space_templ.c"
9040 
9041 /* Check that "bset1" and "bset2" live in the same space,
9042  * reporting an error if they do not.
9043  */
isl_basic_set_check_equal_space(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9044 isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
9045 	__isl_keep isl_basic_set *bset2)
9046 {
9047 	return isl_basic_map_check_equal_space(bset_to_bmap(bset1),
9048 						bset_to_bmap(bset1));
9049 }
9050 
9051 #undef TYPE
9052 #define TYPE	isl_map
9053 
9054 #include "isl_type_has_equal_space_bin_templ.c"
9055 #include "isl_type_check_equal_space_templ.c"
9056 #include "isl_type_has_space_templ.c"
9057 
isl_set_has_equal_space(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9058 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
9059 	__isl_keep isl_set *set2)
9060 {
9061 	return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));
9062 }
9063 
9064 #undef TYPE1
9065 #define TYPE1		isl_map
9066 #undef TYPE2
9067 #define TYPE2		isl_basic_map
9068 #undef TYPE_PAIR
9069 #define TYPE_PAIR	isl_map_basic_map
9070 
9071 static
9072 #include "isl_type_has_equal_space_templ.c"
9073 #include "isl_type_check_equal_space_templ.c"
9074 
9075 /* Check that "set" and "bset" live in the same space,
9076  * reporting an error if they do not.
9077  */
isl_set_basic_set_check_equal_space(__isl_keep isl_set * set,__isl_keep isl_basic_set * bset)9078 isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
9079 	__isl_keep isl_basic_set *bset)
9080 {
9081 	return isl_map_basic_map_check_equal_space(set_to_map(set),
9082 						    bset_to_bmap(bset));
9083 }
9084 
map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9085 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9086 {
9087 	isl_bool is_subset;
9088 
9089 	if (!map1 || !map2)
9090 		return isl_bool_error;
9091 	is_subset = isl_map_is_subset(map1, map2);
9092 	if (is_subset != isl_bool_true)
9093 		return is_subset;
9094 	is_subset = isl_map_is_subset(map2, map1);
9095 	return is_subset;
9096 }
9097 
9098 /* Is "map1" equal to "map2"?
9099  *
9100  * First check if they are obviously equal.
9101  * If not, then perform a more detailed analysis.
9102  */
isl_map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9103 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9104 {
9105 	isl_bool equal;
9106 
9107 	equal = isl_map_plain_is_equal(map1, map2);
9108 	if (equal < 0 || equal)
9109 		return equal;
9110 	return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
9111 }
9112 
isl_basic_map_is_strict_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9113 isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
9114 	__isl_keep isl_basic_map *bmap2)
9115 {
9116 	isl_bool is_subset;
9117 
9118 	if (!bmap1 || !bmap2)
9119 		return isl_bool_error;
9120 	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9121 	if (is_subset != isl_bool_true)
9122 		return is_subset;
9123 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9124 	return isl_bool_not(is_subset);
9125 }
9126 
isl_map_is_strict_subset(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9127 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
9128 	__isl_keep isl_map *map2)
9129 {
9130 	isl_bool is_subset;
9131 
9132 	if (!map1 || !map2)
9133 		return isl_bool_error;
9134 	is_subset = isl_map_is_subset(map1, map2);
9135 	if (is_subset != isl_bool_true)
9136 		return is_subset;
9137 	is_subset = isl_map_is_subset(map2, map1);
9138 	return isl_bool_not(is_subset);
9139 }
9140 
isl_set_is_strict_subset(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9141 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
9142 	__isl_keep isl_set *set2)
9143 {
9144 	return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
9145 }
9146 
9147 /* Is "bmap" obviously equal to the universe with the same space?
9148  *
9149  * That is, does it not have any constraints?
9150  */
isl_basic_map_plain_is_universe(__isl_keep isl_basic_map * bmap)9151 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
9152 {
9153 	if (!bmap)
9154 		return isl_bool_error;
9155 	return bmap->n_eq == 0 && bmap->n_ineq == 0;
9156 }
9157 
9158 /* Is "bset" obviously equal to the universe with the same space?
9159  */
isl_basic_set_plain_is_universe(__isl_keep isl_basic_set * bset)9160 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
9161 {
9162 	return isl_basic_map_plain_is_universe(bset);
9163 }
9164 
9165 /* If "c" does not involve any existentially quantified variables,
9166  * then set *univ to false and abort
9167  */
involves_divs(__isl_take isl_constraint * c,void * user)9168 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
9169 {
9170 	isl_bool *univ = user;
9171 	isl_size n;
9172 
9173 	n = isl_constraint_dim(c, isl_dim_div);
9174 	if (n < 0)
9175 		c = isl_constraint_free(c);
9176 	*univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
9177 	isl_constraint_free(c);
9178 	if (*univ < 0 || !*univ)
9179 		return isl_stat_error;
9180 	return isl_stat_ok;
9181 }
9182 
9183 /* Is "bmap" equal to the universe with the same space?
9184  *
9185  * First check if it is obviously equal to the universe.
9186  * If not and if there are any constraints not involving
9187  * existentially quantified variables, then it is certainly
9188  * not equal to the universe.
9189  * Otherwise, check if the universe is a subset of "bmap".
9190  */
isl_basic_map_is_universe(__isl_keep isl_basic_map * bmap)9191 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
9192 {
9193 	isl_size n_div;
9194 	isl_bool univ;
9195 	isl_basic_map *test;
9196 
9197 	univ = isl_basic_map_plain_is_universe(bmap);
9198 	if (univ < 0 || univ)
9199 		return univ;
9200 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
9201 	if (n_div < 0)
9202 		return isl_bool_error;
9203 	if (n_div == 0)
9204 		return isl_bool_false;
9205 	univ = isl_bool_true;
9206 	if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
9207 	    univ)
9208 		return isl_bool_error;
9209 	if (univ < 0 || !univ)
9210 		return univ;
9211 	test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
9212 	univ = isl_basic_map_is_subset(test, bmap);
9213 	isl_basic_map_free(test);
9214 	return univ;
9215 }
9216 
9217 /* Is "bset" equal to the universe with the same space?
9218  */
isl_basic_set_is_universe(__isl_keep isl_basic_set * bset)9219 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
9220 {
9221 	return isl_basic_map_is_universe(bset);
9222 }
9223 
isl_map_plain_is_universe(__isl_keep isl_map * map)9224 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
9225 {
9226 	int i;
9227 
9228 	if (!map)
9229 		return isl_bool_error;
9230 
9231 	for (i = 0; i < map->n; ++i) {
9232 		isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
9233 		if (r < 0 || r)
9234 			return r;
9235 	}
9236 
9237 	return isl_bool_false;
9238 }
9239 
isl_set_plain_is_universe(__isl_keep isl_set * set)9240 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
9241 {
9242 	return isl_map_plain_is_universe(set_to_map(set));
9243 }
9244 
isl_basic_map_is_empty(__isl_keep isl_basic_map * bmap)9245 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
9246 {
9247 	struct isl_basic_set *bset = NULL;
9248 	struct isl_vec *sample = NULL;
9249 	isl_bool empty, non_empty;
9250 
9251 	if (!bmap)
9252 		return isl_bool_error;
9253 
9254 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
9255 		return isl_bool_true;
9256 
9257 	if (isl_basic_map_plain_is_universe(bmap))
9258 		return isl_bool_false;
9259 
9260 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
9261 		struct isl_basic_map *copy = isl_basic_map_copy(bmap);
9262 		copy = isl_basic_map_remove_redundancies(copy);
9263 		empty = isl_basic_map_plain_is_empty(copy);
9264 		isl_basic_map_free(copy);
9265 		return empty;
9266 	}
9267 
9268 	non_empty = isl_basic_map_plain_is_non_empty(bmap);
9269 	if (non_empty < 0)
9270 		return isl_bool_error;
9271 	if (non_empty)
9272 		return isl_bool_false;
9273 	isl_vec_free(bmap->sample);
9274 	bmap->sample = NULL;
9275 	bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
9276 	if (!bset)
9277 		return isl_bool_error;
9278 	sample = isl_basic_set_sample_vec(bset);
9279 	if (!sample)
9280 		return isl_bool_error;
9281 	empty = sample->size == 0;
9282 	isl_vec_free(bmap->sample);
9283 	bmap->sample = sample;
9284 	if (empty)
9285 		ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
9286 
9287 	return empty;
9288 }
9289 
isl_basic_map_plain_is_empty(__isl_keep isl_basic_map * bmap)9290 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
9291 {
9292 	if (!bmap)
9293 		return isl_bool_error;
9294 	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
9295 }
9296 
isl_basic_set_plain_is_empty(__isl_keep isl_basic_set * bset)9297 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
9298 {
9299 	if (!bset)
9300 		return isl_bool_error;
9301 	return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
9302 }
9303 
9304 /* Is "bmap" known to be non-empty?
9305  *
9306  * That is, is the cached sample still valid?
9307  */
isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map * bmap)9308 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
9309 {
9310 	isl_size total;
9311 
9312 	if (!bmap)
9313 		return isl_bool_error;
9314 	if (!bmap->sample)
9315 		return isl_bool_false;
9316 	total = isl_basic_map_dim(bmap, isl_dim_all);
9317 	if (total < 0)
9318 		return isl_bool_error;
9319 	if (bmap->sample->size != 1 + total)
9320 		return isl_bool_false;
9321 	return isl_basic_map_contains(bmap, bmap->sample);
9322 }
9323 
isl_basic_set_is_empty(__isl_keep isl_basic_set * bset)9324 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
9325 {
9326 	return isl_basic_map_is_empty(bset_to_bmap(bset));
9327 }
9328 
isl_basic_map_union(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)9329 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
9330 	__isl_take isl_basic_map *bmap2)
9331 {
9332 	struct isl_map *map;
9333 
9334 	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
9335 		goto error;
9336 
9337 	map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
9338 	if (!map)
9339 		goto error;
9340 	map = isl_map_add_basic_map(map, bmap1);
9341 	map = isl_map_add_basic_map(map, bmap2);
9342 	return map;
9343 error:
9344 	isl_basic_map_free(bmap1);
9345 	isl_basic_map_free(bmap2);
9346 	return NULL;
9347 }
9348 
isl_basic_set_union(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)9349 __isl_give isl_set *isl_basic_set_union(__isl_take isl_basic_set *bset1,
9350 	__isl_take isl_basic_set *bset2)
9351 {
9352 	return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
9353 						bset_to_bmap(bset2)));
9354 }
9355 
9356 /* Order divs such that any div only depends on previous divs */
isl_basic_map_order_divs(__isl_take isl_basic_map * bmap)9357 __isl_give isl_basic_map *isl_basic_map_order_divs(
9358 	__isl_take isl_basic_map *bmap)
9359 {
9360 	int i;
9361 	isl_size off;
9362 
9363 	off = isl_basic_map_var_offset(bmap, isl_dim_div);
9364 	if (off < 0)
9365 		return isl_basic_map_free(bmap);
9366 
9367 	for (i = 0; i < bmap->n_div; ++i) {
9368 		int pos;
9369 		if (isl_int_is_zero(bmap->div[i][0]))
9370 			continue;
9371 		pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
9372 							    bmap->n_div-i);
9373 		if (pos == -1)
9374 			continue;
9375 		if (pos == 0)
9376 			isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
9377 				"integer division depends on itself",
9378 				return isl_basic_map_free(bmap));
9379 		bmap = isl_basic_map_swap_div(bmap, i, i + pos);
9380 		if (!bmap)
9381 			return NULL;
9382 		--i;
9383 	}
9384 	return bmap;
9385 }
9386 
isl_map_order_divs(__isl_take isl_map * map)9387 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
9388 {
9389 	int i;
9390 
9391 	if (!map)
9392 		return 0;
9393 
9394 	for (i = 0; i < map->n; ++i) {
9395 		map->p[i] = isl_basic_map_order_divs(map->p[i]);
9396 		if (!map->p[i])
9397 			goto error;
9398 	}
9399 
9400 	return map;
9401 error:
9402 	isl_map_free(map);
9403 	return NULL;
9404 }
9405 
9406 /* Sort the local variables of "bset".
9407  */
isl_basic_set_sort_divs(__isl_take isl_basic_set * bset)9408 __isl_give isl_basic_set *isl_basic_set_sort_divs(
9409 	__isl_take isl_basic_set *bset)
9410 {
9411 	return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
9412 }
9413 
9414 /* Apply the expansion computed by isl_merge_divs.
9415  * The expansion itself is given by "exp" while the resulting
9416  * list of divs is given by "div".
9417  *
9418  * Move the integer divisions of "bmap" into the right position
9419  * according to "exp" and then introduce the additional integer
9420  * divisions, adding div constraints.
9421  * The moving should be done first to avoid moving coefficients
9422  * in the definitions of the extra integer divisions.
9423  */
isl_basic_map_expand_divs(__isl_take isl_basic_map * bmap,__isl_take isl_mat * div,int * exp)9424 __isl_give isl_basic_map *isl_basic_map_expand_divs(
9425 	__isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
9426 {
9427 	int i, j;
9428 	int n_div;
9429 
9430 	bmap = isl_basic_map_cow(bmap);
9431 	if (!bmap || !div)
9432 		goto error;
9433 
9434 	if (div->n_row < bmap->n_div)
9435 		isl_die(isl_mat_get_ctx(div), isl_error_invalid,
9436 			"not an expansion", goto error);
9437 
9438 	n_div = bmap->n_div;
9439 	bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,
9440 					    2 * (div->n_row - n_div));
9441 
9442 	for (i = n_div; i < div->n_row; ++i)
9443 		if (isl_basic_map_alloc_div(bmap) < 0)
9444 			goto error;
9445 
9446 	for (j = n_div - 1; j >= 0; --j) {
9447 		if (exp[j] == j)
9448 			break;
9449 		bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
9450 		if (!bmap)
9451 			goto error;
9452 	}
9453 	j = 0;
9454 	for (i = 0; i < div->n_row; ++i) {
9455 		if (j < n_div && exp[j] == i) {
9456 			j++;
9457 		} else {
9458 			isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
9459 			if (isl_basic_map_div_is_marked_unknown(bmap, i))
9460 				continue;
9461 			bmap = isl_basic_map_add_div_constraints(bmap, i);
9462 			if (!bmap)
9463 				goto error;
9464 		}
9465 	}
9466 
9467 	isl_mat_free(div);
9468 	return bmap;
9469 error:
9470 	isl_basic_map_free(bmap);
9471 	isl_mat_free(div);
9472 	return NULL;
9473 }
9474 
9475 /* Apply the expansion computed by isl_merge_divs.
9476  * The expansion itself is given by "exp" while the resulting
9477  * list of divs is given by "div".
9478  */
isl_basic_set_expand_divs(__isl_take isl_basic_set * bset,__isl_take isl_mat * div,int * exp)9479 __isl_give isl_basic_set *isl_basic_set_expand_divs(
9480 	__isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
9481 {
9482 	return isl_basic_map_expand_divs(bset, div, exp);
9483 }
9484 
9485 /* Look for a div in dst that corresponds to the div "div" in src.
9486  * The divs before "div" in src and dst are assumed to be the same.
9487  *
9488  * Return the position of the corresponding div in dst
9489  * if there is one.  Otherwise, return a position beyond the integer divisions.
9490  * Return -1 on error.
9491  */
find_div(__isl_keep isl_basic_map * dst,__isl_keep isl_basic_map * src,unsigned div)9492 static int find_div(__isl_keep isl_basic_map *dst,
9493 	__isl_keep isl_basic_map *src, unsigned div)
9494 {
9495 	int i;
9496 	isl_size n_div;
9497 	isl_size v_div;
9498 
9499 	v_div = isl_basic_map_var_offset(src, isl_dim_div);
9500 	n_div = isl_basic_map_dim(dst, isl_dim_div);
9501 	if (n_div < 0 || v_div < 0)
9502 		return -1;
9503 	isl_assert(dst->ctx, div <= n_div, return -1);
9504 	for (i = div; i < n_div; ++i)
9505 		if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
9506 		    isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
9507 						n_div - div) == -1)
9508 			return i;
9509 	return n_div;
9510 }
9511 
9512 /* Align the divs of "dst" to those of "src", adding divs from "src"
9513  * if needed.  That is, make sure that the first src->n_div divs
9514  * of the result are equal to those of src.
9515  * The integer division of "src" are assumed to be ordered.
9516  *
9517  * The integer divisions are swapped into the right position
9518  * (possibly after adding them first).  This may result
9519  * in the remaining integer divisions appearing in the wrong order,
9520  * i.e., with some integer division appearing before
9521  * some other integer division on which it depends.
9522  * The integer divisions therefore need to be ordered.
9523  * This will not affect the integer divisions aligned to those of "src",
9524  * since "src" is assumed to have ordered integer divisions.
9525  *
9526  * The result is not finalized as by design it will have redundant
9527  * divs if any divs from "src" were copied.
9528  */
isl_basic_map_align_divs(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)9529 __isl_give isl_basic_map *isl_basic_map_align_divs(
9530 	__isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
9531 {
9532 	int i;
9533 	isl_bool known;
9534 	int extended;
9535 	isl_size v_div;
9536 	isl_size dst_n_div;
9537 
9538 	if (!dst || !src)
9539 		return isl_basic_map_free(dst);
9540 
9541 	if (src->n_div == 0)
9542 		return dst;
9543 
9544 	known = isl_basic_map_divs_known(src);
9545 	if (known < 0)
9546 		return isl_basic_map_free(dst);
9547 	if (!known)
9548 		isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9549 			"some src divs are unknown",
9550 			return isl_basic_map_free(dst));
9551 
9552 	v_div = isl_basic_map_var_offset(src, isl_dim_div);
9553 	if (v_div < 0)
9554 		return isl_basic_map_free(dst);
9555 
9556 	extended = 0;
9557 	dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
9558 	if (dst_n_div < 0)
9559 		dst = isl_basic_map_free(dst);
9560 	for (i = 0; i < src->n_div; ++i) {
9561 		int j = find_div(dst, src, i);
9562 		if (j < 0)
9563 			dst = isl_basic_map_free(dst);
9564 		if (j == dst_n_div) {
9565 			if (!extended) {
9566 				int extra = src->n_div - i;
9567 				dst = isl_basic_map_cow(dst);
9568 				if (!dst)
9569 					return isl_basic_map_free(dst);
9570 				dst = isl_basic_map_extend(dst,
9571 						extra, 0, 2 * extra);
9572 				extended = 1;
9573 			}
9574 			j = isl_basic_map_alloc_div(dst);
9575 			if (j < 0)
9576 				return isl_basic_map_free(dst);
9577 			isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
9578 			isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
9579 			dst_n_div++;
9580 			dst = isl_basic_map_add_div_constraints(dst, j);
9581 			if (!dst)
9582 				return isl_basic_map_free(dst);
9583 		}
9584 		if (j != i)
9585 			dst = isl_basic_map_swap_div(dst, i, j);
9586 		if (!dst)
9587 			return isl_basic_map_free(dst);
9588 	}
9589 	return isl_basic_map_order_divs(dst);
9590 }
9591 
isl_map_align_divs_internal(__isl_take isl_map * map)9592 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9593 {
9594 	int i;
9595 
9596 	if (!map)
9597 		return NULL;
9598 	if (map->n == 0)
9599 		return map;
9600 	map = isl_map_compute_divs(map);
9601 	map = isl_map_order_divs(map);
9602 	map = isl_map_cow(map);
9603 	if (!map)
9604 		return NULL;
9605 
9606 	for (i = 1; i < map->n; ++i)
9607 		map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9608 	for (i = 1; i < map->n; ++i) {
9609 		map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9610 		if (!map->p[i])
9611 			return isl_map_free(map);
9612 	}
9613 
9614 	map = isl_map_unmark_normalized(map);
9615 	return map;
9616 }
9617 
isl_map_align_divs(__isl_take isl_map * map)9618 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9619 {
9620 	return isl_map_align_divs_internal(map);
9621 }
9622 
isl_set_align_divs(__isl_take isl_set * set)9623 __isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set)
9624 {
9625 	return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9626 }
9627 
9628 /* Align the divs of the basic maps in "map" to those
9629  * of the basic maps in "list", as well as to the other basic maps in "map".
9630  * The elements in "list" are assumed to have known divs.
9631  */
isl_map_align_divs_to_basic_map_list(__isl_take isl_map * map,__isl_keep isl_basic_map_list * list)9632 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9633 	__isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9634 {
9635 	int i;
9636 	isl_size n;
9637 
9638 	n = isl_basic_map_list_n_basic_map(list);
9639 	map = isl_map_compute_divs(map);
9640 	map = isl_map_cow(map);
9641 	if (!map || n < 0)
9642 		return isl_map_free(map);
9643 	if (map->n == 0)
9644 		return map;
9645 
9646 	for (i = 0; i < n; ++i) {
9647 		isl_basic_map *bmap;
9648 
9649 		bmap = isl_basic_map_list_get_basic_map(list, i);
9650 		bmap = isl_basic_map_order_divs(bmap);
9651 		map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9652 		isl_basic_map_free(bmap);
9653 	}
9654 	if (!map->p[0])
9655 		return isl_map_free(map);
9656 
9657 	return isl_map_align_divs_internal(map);
9658 }
9659 
9660 /* Align the divs of each element of "list" to those of "bmap".
9661  * Both "bmap" and the elements of "list" are assumed to have known divs.
9662  */
isl_basic_map_list_align_divs_to_basic_map(__isl_take isl_basic_map_list * list,__isl_keep isl_basic_map * bmap)9663 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9664 	__isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9665 {
9666 	int i;
9667 	isl_size n;
9668 
9669 	n = isl_basic_map_list_n_basic_map(list);
9670 	if (n < 0 || !bmap)
9671 		return isl_basic_map_list_free(list);
9672 
9673 	for (i = 0; i < n; ++i) {
9674 		isl_basic_map *bmap_i;
9675 
9676 		bmap_i = isl_basic_map_list_get_basic_map(list, i);
9677 		bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9678 		list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9679 	}
9680 
9681 	return list;
9682 }
9683 
isl_set_apply(__isl_take isl_set * set,__isl_take isl_map * map)9684 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9685 	__isl_take isl_map *map)
9686 {
9687 	isl_bool ok;
9688 
9689 	isl_map_align_params_set(&map, &set);
9690 	ok = isl_map_compatible_domain(map, set);
9691 	if (ok < 0)
9692 		goto error;
9693 	if (!ok)
9694 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
9695 			"incompatible spaces", goto error);
9696 	map = isl_map_intersect_domain(map, set);
9697 	set = isl_map_range(map);
9698 	return set;
9699 error:
9700 	isl_set_free(set);
9701 	isl_map_free(map);
9702 	return NULL;
9703 }
9704 
9705 /* There is no need to cow as removing empty parts doesn't change
9706  * the meaning of the set.
9707  */
isl_map_remove_empty_parts(__isl_take isl_map * map)9708 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9709 {
9710 	int i;
9711 
9712 	if (!map)
9713 		return NULL;
9714 
9715 	for (i = map->n - 1; i >= 0; --i)
9716 		map = remove_if_empty(map, i);
9717 
9718 	return map;
9719 }
9720 
isl_set_remove_empty_parts(__isl_take isl_set * set)9721 __isl_give isl_set *isl_set_remove_empty_parts(__isl_take isl_set *set)
9722 {
9723 	return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9724 }
9725 
9726 /* Create a binary relation that maps the shared initial "pos" dimensions
9727  * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9728  */
join_initial(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9729 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9730 	__isl_keep isl_basic_set *bset2, int pos)
9731 {
9732 	isl_basic_map *bmap1;
9733 	isl_basic_map *bmap2;
9734 
9735 	bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9736 	bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9737 	bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9738 					isl_dim_out, 0, pos);
9739 	bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9740 					isl_dim_out, 0, pos);
9741 	return isl_basic_map_range_product(bmap1, bmap2);
9742 }
9743 
9744 /* Given two basic sets bset1 and bset2, compute the maximal difference
9745  * between the values of dimension pos in bset1 and those in bset2
9746  * for any common value of the parameters and dimensions preceding pos.
9747  */
basic_set_maximal_difference_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos,isl_int * opt)9748 static enum isl_lp_result basic_set_maximal_difference_at(
9749 	__isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9750 	int pos, isl_int *opt)
9751 {
9752 	isl_basic_map *bmap1;
9753 	struct isl_ctx *ctx;
9754 	struct isl_vec *obj;
9755 	isl_size total;
9756 	isl_size nparam;
9757 	isl_size dim1;
9758 	enum isl_lp_result res;
9759 
9760 	nparam = isl_basic_set_dim(bset1, isl_dim_param);
9761 	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9762 	if (nparam < 0 || dim1 < 0 || !bset2)
9763 		return isl_lp_error;
9764 
9765 	bmap1 = join_initial(bset1, bset2, pos);
9766 	total = isl_basic_map_dim(bmap1, isl_dim_all);
9767 	if (total < 0)
9768 		return isl_lp_error;
9769 
9770 	ctx = bmap1->ctx;
9771 	obj = isl_vec_alloc(ctx, 1 + total);
9772 	if (!obj)
9773 		goto error;
9774 	isl_seq_clr(obj->block.data, 1 + total);
9775 	isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9776 	isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9777 	res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9778 					opt, NULL, NULL);
9779 	isl_basic_map_free(bmap1);
9780 	isl_vec_free(obj);
9781 	return res;
9782 error:
9783 	isl_basic_map_free(bmap1);
9784 	return isl_lp_error;
9785 }
9786 
9787 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9788  * for any common value of the parameters and dimensions preceding pos
9789  * in both basic sets, the values of dimension pos in bset1 are
9790  * smaller or larger than those in bset2.
9791  *
9792  * Returns
9793  *	 1 if bset1 follows bset2
9794  *	-1 if bset1 precedes bset2
9795  *	 0 if bset1 and bset2 are incomparable
9796  *	-2 if some error occurred.
9797  */
isl_basic_set_compare_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9798 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9799 	__isl_keep isl_basic_set *bset2, int pos)
9800 {
9801 	isl_int opt;
9802 	enum isl_lp_result res;
9803 	int cmp;
9804 
9805 	isl_int_init(opt);
9806 
9807 	res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9808 
9809 	if (res == isl_lp_empty)
9810 		cmp = 0;
9811 	else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9812 		  res == isl_lp_unbounded)
9813 		cmp = 1;
9814 	else if (res == isl_lp_ok && isl_int_is_neg(opt))
9815 		cmp = -1;
9816 	else
9817 		cmp = -2;
9818 
9819 	isl_int_clear(opt);
9820 	return cmp;
9821 }
9822 
9823 /* Given two basic sets bset1 and bset2, check whether
9824  * for any common value of the parameters and dimensions preceding pos
9825  * there is a value of dimension pos in bset1 that is larger
9826  * than a value of the same dimension in bset2.
9827  *
9828  * Return
9829  *	 1 if there exists such a pair
9830  *	 0 if there is no such pair, but there is a pair of equal values
9831  *	-1 otherwise
9832  *	-2 if some error occurred.
9833  */
isl_basic_set_follows_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9834 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9835 	__isl_keep isl_basic_set *bset2, int pos)
9836 {
9837 	isl_bool empty;
9838 	isl_basic_map *bmap;
9839 	isl_size dim1;
9840 
9841 	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9842 	if (dim1 < 0)
9843 		return -2;
9844 	bmap = join_initial(bset1, bset2, pos);
9845 	bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9846 					    isl_dim_out, dim1 - pos);
9847 	empty = isl_basic_map_is_empty(bmap);
9848 	if (empty < 0)
9849 		goto error;
9850 	if (empty) {
9851 		isl_basic_map_free(bmap);
9852 		return -1;
9853 	}
9854 	bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9855 					    isl_dim_out, dim1 - pos);
9856 	empty = isl_basic_map_is_empty(bmap);
9857 	if (empty < 0)
9858 		goto error;
9859 	isl_basic_map_free(bmap);
9860 	if (empty)
9861 		return 0;
9862 	return 1;
9863 error:
9864 	isl_basic_map_free(bmap);
9865 	return -2;
9866 }
9867 
9868 /* Given two sets set1 and set2, check whether
9869  * for any common value of the parameters and dimensions preceding pos
9870  * there is a value of dimension pos in set1 that is larger
9871  * than a value of the same dimension in set2.
9872  *
9873  * Return
9874  *	 1 if there exists such a pair
9875  *	 0 if there is no such pair, but there is a pair of equal values
9876  *	-1 otherwise
9877  *	-2 if some error occurred.
9878  */
isl_set_follows_at(__isl_keep isl_set * set1,__isl_keep isl_set * set2,int pos)9879 int isl_set_follows_at(__isl_keep isl_set *set1,
9880 	__isl_keep isl_set *set2, int pos)
9881 {
9882 	int i, j;
9883 	int follows = -1;
9884 
9885 	if (!set1 || !set2)
9886 		return -2;
9887 
9888 	for (i = 0; i < set1->n; ++i)
9889 		for (j = 0; j < set2->n; ++j) {
9890 			int f;
9891 			f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9892 			if (f == 1 || f == -2)
9893 				return f;
9894 			if (f > follows)
9895 				follows = f;
9896 		}
9897 
9898 	return follows;
9899 }
9900 
isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * val)9901 static isl_bool isl_basic_map_plain_has_fixed_var(
9902 	__isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9903 {
9904 	int i;
9905 	int d;
9906 	isl_size total;
9907 
9908 	total = isl_basic_map_dim(bmap, isl_dim_all);
9909 	if (total < 0)
9910 		return isl_bool_error;
9911 	for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9912 		for (; d+1 > pos; --d)
9913 			if (!isl_int_is_zero(bmap->eq[i][1+d]))
9914 				break;
9915 		if (d != pos)
9916 			continue;
9917 		if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9918 			return isl_bool_false;
9919 		if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9920 			return isl_bool_false;
9921 		if (!isl_int_is_one(bmap->eq[i][1+d]))
9922 			return isl_bool_false;
9923 		if (val)
9924 			isl_int_neg(*val, bmap->eq[i][0]);
9925 		return isl_bool_true;
9926 	}
9927 	return isl_bool_false;
9928 }
9929 
isl_map_plain_has_fixed_var(__isl_keep isl_map * map,unsigned pos,isl_int * val)9930 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9931 	unsigned pos, isl_int *val)
9932 {
9933 	int i;
9934 	isl_int v;
9935 	isl_int tmp;
9936 	isl_bool fixed;
9937 
9938 	if (!map)
9939 		return isl_bool_error;
9940 	if (map->n == 0)
9941 		return isl_bool_false;
9942 	if (map->n == 1)
9943 		return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9944 	isl_int_init(v);
9945 	isl_int_init(tmp);
9946 	fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9947 	for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9948 		fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9949 		if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9950 			fixed = isl_bool_false;
9951 	}
9952 	if (val)
9953 		isl_int_set(*val, v);
9954 	isl_int_clear(tmp);
9955 	isl_int_clear(v);
9956 	return fixed;
9957 }
9958 
isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set * bset,unsigned pos,isl_int * val)9959 static isl_bool isl_basic_set_plain_has_fixed_var(
9960 	__isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9961 {
9962 	return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9963 						pos, val);
9964 }
9965 
isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int * val)9966 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9967 	enum isl_dim_type type, unsigned pos, isl_int *val)
9968 {
9969 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9970 		return isl_bool_error;
9971 	return isl_basic_map_plain_has_fixed_var(bmap,
9972 		isl_basic_map_offset(bmap, type) - 1 + pos, val);
9973 }
9974 
9975 /* If "bmap" obviously lies on a hyperplane where the given dimension
9976  * has a fixed value, then return that value.
9977  * Otherwise return NaN.
9978  */
isl_basic_map_plain_get_val_if_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)9979 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9980 	__isl_keep isl_basic_map *bmap,
9981 	enum isl_dim_type type, unsigned pos)
9982 {
9983 	isl_ctx *ctx;
9984 	isl_val *v;
9985 	isl_bool fixed;
9986 
9987 	if (!bmap)
9988 		return NULL;
9989 	ctx = isl_basic_map_get_ctx(bmap);
9990 	v = isl_val_alloc(ctx);
9991 	if (!v)
9992 		return NULL;
9993 	fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9994 	if (fixed < 0)
9995 		return isl_val_free(v);
9996 	if (fixed) {
9997 		isl_int_set_si(v->d, 1);
9998 		return v;
9999 	}
10000 	isl_val_free(v);
10001 	return isl_val_nan(ctx);
10002 }
10003 
isl_map_plain_is_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_int * val)10004 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
10005 	enum isl_dim_type type, unsigned pos, isl_int *val)
10006 {
10007 	if (isl_map_check_range(map, type, pos, 1) < 0)
10008 		return isl_bool_error;
10009 	return isl_map_plain_has_fixed_var(map,
10010 		map_offset(map, type) - 1 + pos, val);
10011 }
10012 
10013 /* If "map" obviously lies on a hyperplane where the given dimension
10014  * has a fixed value, then return that value.
10015  * Otherwise return NaN.
10016  */
isl_map_plain_get_val_if_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)10017 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
10018 	enum isl_dim_type type, unsigned pos)
10019 {
10020 	isl_ctx *ctx;
10021 	isl_val *v;
10022 	isl_bool fixed;
10023 
10024 	if (!map)
10025 		return NULL;
10026 	ctx = isl_map_get_ctx(map);
10027 	v = isl_val_alloc(ctx);
10028 	if (!v)
10029 		return NULL;
10030 	fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
10031 	if (fixed < 0)
10032 		return isl_val_free(v);
10033 	if (fixed) {
10034 		isl_int_set_si(v->d, 1);
10035 		return v;
10036 	}
10037 	isl_val_free(v);
10038 	return isl_val_nan(ctx);
10039 }
10040 
10041 /* If "set" obviously lies on a hyperplane where the given dimension
10042  * has a fixed value, then return that value.
10043  * Otherwise return NaN.
10044  */
isl_set_plain_get_val_if_fixed(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10045 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
10046 	enum isl_dim_type type, unsigned pos)
10047 {
10048 	return isl_map_plain_get_val_if_fixed(set, type, pos);
10049 }
10050 
10051 /* Return a sequence of values in the same space as "set"
10052  * that are equal to the corresponding set dimensions of "set"
10053  * for those set dimensions that obviously lie on a hyperplane
10054  * where the dimension has a fixed value.
10055  * The other elements are set to NaN.
10056  */
isl_set_get_plain_multi_val_if_fixed(__isl_keep isl_set * set)10057 __isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
10058 	__isl_keep isl_set *set)
10059 {
10060 	int i;
10061 	isl_size n;
10062 	isl_space *space;
10063 	isl_multi_val *mv;
10064 
10065 	space = isl_space_drop_all_params(isl_set_get_space(set));
10066 	mv = isl_multi_val_alloc(space);
10067 	n = isl_multi_val_size(mv);
10068 	if (n < 0)
10069 		return isl_multi_val_free(mv);
10070 
10071 	for (i = 0; i < n; ++i) {
10072 		isl_val *v;
10073 
10074 		v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);
10075 		mv = isl_multi_val_set_val(mv, i, v);
10076 	}
10077 
10078 	return mv;
10079 }
10080 
10081 /* Check if dimension dim has fixed value and if so and if val is not NULL,
10082  * then return this fixed value in *val.
10083  */
isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set * bset,unsigned dim,isl_int * val)10084 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
10085 	unsigned dim, isl_int *val)
10086 {
10087 	isl_size nparam;
10088 
10089 	nparam = isl_basic_set_dim(bset, isl_dim_param);
10090 	if (nparam < 0)
10091 		return isl_bool_error;
10092 	return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
10093 }
10094 
10095 /* Return -1 if the constraint "c1" should be sorted before "c2"
10096  * and 1 if it should be sorted after "c2".
10097  * Return 0 if the two constraints are the same (up to the constant term).
10098  *
10099  * In particular, if a constraint involves later variables than another
10100  * then it is sorted after this other constraint.
10101  * uset_gist depends on constraints without existentially quantified
10102  * variables sorting first.
10103  *
10104  * For constraints that have the same latest variable, those
10105  * with the same coefficient for this latest variable (first in absolute value
10106  * and then in actual value) are grouped together.
10107  * This is useful for detecting pairs of constraints that can
10108  * be chained in their printed representation.
10109  *
10110  * Finally, within a group, constraints are sorted according to
10111  * their coefficients (excluding the constant term).
10112  */
sort_constraint_cmp(const void * p1,const void * p2,void * arg)10113 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
10114 {
10115 	isl_int **c1 = (isl_int **) p1;
10116 	isl_int **c2 = (isl_int **) p2;
10117 	int l1, l2;
10118 	unsigned size = *(unsigned *) arg;
10119 	int cmp;
10120 
10121 	l1 = isl_seq_last_non_zero(*c1 + 1, size);
10122 	l2 = isl_seq_last_non_zero(*c2 + 1, size);
10123 
10124 	if (l1 != l2)
10125 		return l1 - l2;
10126 
10127 	cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10128 	if (cmp != 0)
10129 		return cmp;
10130 	cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10131 	if (cmp != 0)
10132 		return -cmp;
10133 
10134 	return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
10135 }
10136 
10137 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
10138  * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
10139  * and 0 if the two constraints are the same (up to the constant term).
10140  */
isl_basic_map_constraint_cmp(__isl_keep isl_basic_map * bmap,isl_int * c1,isl_int * c2)10141 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
10142 	isl_int *c1, isl_int *c2)
10143 {
10144 	isl_size total;
10145 	unsigned size;
10146 
10147 	total = isl_basic_map_dim(bmap, isl_dim_all);
10148 	if (total < 0)
10149 		return -2;
10150 	size = total;
10151 	return sort_constraint_cmp(&c1, &c2, &size);
10152 }
10153 
isl_basic_map_sort_constraints(__isl_take isl_basic_map * bmap)10154 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
10155 	__isl_take isl_basic_map *bmap)
10156 {
10157 	isl_size total;
10158 	unsigned size;
10159 
10160 	if (!bmap)
10161 		return NULL;
10162 	if (bmap->n_ineq == 0)
10163 		return bmap;
10164 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
10165 		return bmap;
10166 	total = isl_basic_map_dim(bmap, isl_dim_all);
10167 	if (total < 0)
10168 		return isl_basic_map_free(bmap);
10169 	size = total;
10170 	if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
10171 		    &sort_constraint_cmp, &size) < 0)
10172 		return isl_basic_map_free(bmap);
10173 	ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
10174 	return bmap;
10175 }
10176 
isl_basic_set_sort_constraints(__isl_take isl_basic_set * bset)10177 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
10178 	__isl_take isl_basic_set *bset)
10179 {
10180 	isl_basic_map *bmap = bset_to_bmap(bset);
10181 	return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
10182 }
10183 
isl_basic_map_normalize(__isl_take isl_basic_map * bmap)10184 __isl_give isl_basic_map *isl_basic_map_normalize(
10185 	__isl_take isl_basic_map *bmap)
10186 {
10187 	bmap = isl_basic_map_remove_redundancies(bmap);
10188 	bmap = isl_basic_map_sort_constraints(bmap);
10189 	return bmap;
10190 }
isl_basic_map_plain_cmp(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10191 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
10192 	__isl_keep isl_basic_map *bmap2)
10193 {
10194 	int i, cmp;
10195 	isl_size total;
10196 	isl_space *space1, *space2;
10197 
10198 	if (!bmap1 || !bmap2)
10199 		return -1;
10200 
10201 	if (bmap1 == bmap2)
10202 		return 0;
10203 	space1 = isl_basic_map_peek_space(bmap1);
10204 	space2 = isl_basic_map_peek_space(bmap2);
10205 	cmp = isl_space_cmp(space1, space2);
10206 	if (cmp)
10207 		return cmp;
10208 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
10209 	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
10210 		return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
10211 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
10212 	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10213 		return 0;
10214 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
10215 		return 1;
10216 	if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10217 		return -1;
10218 	if (bmap1->n_eq != bmap2->n_eq)
10219 		return bmap1->n_eq - bmap2->n_eq;
10220 	if (bmap1->n_ineq != bmap2->n_ineq)
10221 		return bmap1->n_ineq - bmap2->n_ineq;
10222 	if (bmap1->n_div != bmap2->n_div)
10223 		return bmap1->n_div - bmap2->n_div;
10224 	total = isl_basic_map_dim(bmap1, isl_dim_all);
10225 	if (total < 0)
10226 		return -1;
10227 	for (i = 0; i < bmap1->n_eq; ++i) {
10228 		cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
10229 		if (cmp)
10230 			return cmp;
10231 	}
10232 	for (i = 0; i < bmap1->n_ineq; ++i) {
10233 		cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
10234 		if (cmp)
10235 			return cmp;
10236 	}
10237 	for (i = 0; i < bmap1->n_div; ++i) {
10238 		cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
10239 		if (cmp)
10240 			return cmp;
10241 	}
10242 	return 0;
10243 }
10244 
isl_basic_set_plain_cmp(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10245 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
10246 	__isl_keep isl_basic_set *bset2)
10247 {
10248 	return isl_basic_map_plain_cmp(bset1, bset2);
10249 }
10250 
isl_set_plain_cmp(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10251 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
10252 {
10253 	int i, cmp;
10254 
10255 	if (set1 == set2)
10256 		return 0;
10257 	if (set1->n != set2->n)
10258 		return set1->n - set2->n;
10259 
10260 	for (i = 0; i < set1->n; ++i) {
10261 		cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
10262 		if (cmp)
10263 			return cmp;
10264 	}
10265 
10266 	return 0;
10267 }
10268 
isl_basic_map_plain_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10269 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
10270 	__isl_keep isl_basic_map *bmap2)
10271 {
10272 	if (!bmap1 || !bmap2)
10273 		return isl_bool_error;
10274 	return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
10275 }
10276 
isl_basic_set_plain_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10277 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
10278 	__isl_keep isl_basic_set *bset2)
10279 {
10280 	return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
10281 					    bset_to_bmap(bset2));
10282 }
10283 
qsort_bmap_cmp(const void * p1,const void * p2)10284 static int qsort_bmap_cmp(const void *p1, const void *p2)
10285 {
10286 	isl_basic_map *bmap1 = *(isl_basic_map **) p1;
10287 	isl_basic_map *bmap2 = *(isl_basic_map **) p2;
10288 
10289 	return isl_basic_map_plain_cmp(bmap1, bmap2);
10290 }
10291 
10292 /* Sort the basic maps of "map" and remove duplicate basic maps.
10293  *
10294  * While removing basic maps, we make sure that the basic maps remain
10295  * sorted because isl_map_normalize expects the basic maps of the result
10296  * to be sorted.
10297  */
sort_and_remove_duplicates(__isl_take isl_map * map)10298 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
10299 {
10300 	int i, j;
10301 
10302 	map = isl_map_remove_empty_parts(map);
10303 	if (!map)
10304 		return NULL;
10305 	qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
10306 	for (i = map->n - 1; i >= 1; --i) {
10307 		if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
10308 			continue;
10309 		isl_basic_map_free(map->p[i-1]);
10310 		for (j = i; j < map->n; ++j)
10311 			map->p[j - 1] = map->p[j];
10312 		map->n--;
10313 	}
10314 
10315 	return map;
10316 }
10317 
10318 /* Remove obvious duplicates among the basic maps of "map".
10319  *
10320  * Unlike isl_map_normalize, this function does not remove redundant
10321  * constraints and only removes duplicates that have exactly the same
10322  * constraints in the input.  It does sort the constraints and
10323  * the basic maps to ease the detection of duplicates.
10324  *
10325  * If "map" has already been normalized or if the basic maps are
10326  * disjoint, then there can be no duplicates.
10327  */
isl_map_remove_obvious_duplicates(__isl_take isl_map * map)10328 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
10329 {
10330 	int i;
10331 	isl_basic_map *bmap;
10332 
10333 	if (!map)
10334 		return NULL;
10335 	if (map->n <= 1)
10336 		return map;
10337 	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
10338 		return map;
10339 	for (i = 0; i < map->n; ++i) {
10340 		bmap = isl_basic_map_copy(map->p[i]);
10341 		bmap = isl_basic_map_sort_constraints(bmap);
10342 		if (!bmap)
10343 			return isl_map_free(map);
10344 		isl_basic_map_free(map->p[i]);
10345 		map->p[i] = bmap;
10346 	}
10347 
10348 	map = sort_and_remove_duplicates(map);
10349 	return map;
10350 }
10351 
10352 /* We normalize in place, but if anything goes wrong we need
10353  * to return NULL, so we need to make sure we don't change the
10354  * meaning of any possible other copies of map.
10355  */
isl_map_normalize(__isl_take isl_map * map)10356 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
10357 {
10358 	int i;
10359 	struct isl_basic_map *bmap;
10360 
10361 	if (!map)
10362 		return NULL;
10363 	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
10364 		return map;
10365 	for (i = 0; i < map->n; ++i) {
10366 		bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
10367 		if (!bmap)
10368 			goto error;
10369 		isl_basic_map_free(map->p[i]);
10370 		map->p[i] = bmap;
10371 	}
10372 
10373 	map = sort_and_remove_duplicates(map);
10374 	if (map)
10375 		ISL_F_SET(map, ISL_MAP_NORMALIZED);
10376 	return map;
10377 error:
10378 	isl_map_free(map);
10379 	return NULL;
10380 }
10381 
isl_set_normalize(__isl_take isl_set * set)10382 __isl_give isl_set *isl_set_normalize(__isl_take isl_set *set)
10383 {
10384 	return set_from_map(isl_map_normalize(set_to_map(set)));
10385 }
10386 
isl_map_plain_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)10387 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
10388 	__isl_keep isl_map *map2)
10389 {
10390 	int i;
10391 	isl_bool equal;
10392 
10393 	if (!map1 || !map2)
10394 		return isl_bool_error;
10395 
10396 	if (map1 == map2)
10397 		return isl_bool_true;
10398 	equal = isl_map_has_equal_space(map1, map2);
10399 	if (equal < 0 || !equal)
10400 		return equal;
10401 
10402 	map1 = isl_map_copy(map1);
10403 	map2 = isl_map_copy(map2);
10404 	map1 = isl_map_normalize(map1);
10405 	map2 = isl_map_normalize(map2);
10406 	if (!map1 || !map2)
10407 		goto error;
10408 	equal = map1->n == map2->n;
10409 	for (i = 0; equal && i < map1->n; ++i) {
10410 		equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
10411 		if (equal < 0)
10412 			goto error;
10413 	}
10414 	isl_map_free(map1);
10415 	isl_map_free(map2);
10416 	return equal;
10417 error:
10418 	isl_map_free(map1);
10419 	isl_map_free(map2);
10420 	return isl_bool_error;
10421 }
10422 
isl_set_plain_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10423 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
10424 	__isl_keep isl_set *set2)
10425 {
10426 	return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
10427 }
10428 
10429 /* Return the basic maps in "map" as a list.
10430  */
isl_map_get_basic_map_list(__isl_keep isl_map * map)10431 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
10432 	__isl_keep isl_map *map)
10433 {
10434 	int i;
10435 	isl_ctx *ctx;
10436 	isl_basic_map_list *list;
10437 
10438 	if (!map)
10439 		return NULL;
10440 	ctx = isl_map_get_ctx(map);
10441 	list = isl_basic_map_list_alloc(ctx, map->n);
10442 
10443 	for (i = 0; i < map->n; ++i) {
10444 		isl_basic_map *bmap;
10445 
10446 		bmap = isl_basic_map_copy(map->p[i]);
10447 		list = isl_basic_map_list_add(list, bmap);
10448 	}
10449 
10450 	return list;
10451 }
10452 
10453 /* Return the intersection of the elements in the non-empty list "list".
10454  * All elements are assumed to live in the same space.
10455  */
isl_basic_map_list_intersect(__isl_take isl_basic_map_list * list)10456 __isl_give isl_basic_map *isl_basic_map_list_intersect(
10457 	__isl_take isl_basic_map_list *list)
10458 {
10459 	int i;
10460 	isl_size n;
10461 	isl_basic_map *bmap;
10462 
10463 	n = isl_basic_map_list_n_basic_map(list);
10464 	if (n < 0)
10465 		goto error;
10466 	if (n < 1)
10467 		isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
10468 			"expecting non-empty list", goto error);
10469 
10470 	bmap = isl_basic_map_list_get_basic_map(list, 0);
10471 	for (i = 1; i < n; ++i) {
10472 		isl_basic_map *bmap_i;
10473 
10474 		bmap_i = isl_basic_map_list_get_basic_map(list, i);
10475 		bmap = isl_basic_map_intersect(bmap, bmap_i);
10476 	}
10477 
10478 	isl_basic_map_list_free(list);
10479 	return bmap;
10480 error:
10481 	isl_basic_map_list_free(list);
10482 	return NULL;
10483 }
10484 
10485 /* Return the intersection of the elements in the non-empty list "list".
10486  * All elements are assumed to live in the same space.
10487  */
isl_basic_set_list_intersect(__isl_take isl_basic_set_list * list)10488 __isl_give isl_basic_set *isl_basic_set_list_intersect(
10489 	__isl_take isl_basic_set_list *list)
10490 {
10491 	return isl_basic_map_list_intersect(list);
10492 }
10493 
10494 /* Return the union of the elements of "list".
10495  * The list is required to have at least one element.
10496  */
isl_basic_set_list_union(__isl_take isl_basic_set_list * list)10497 __isl_give isl_set *isl_basic_set_list_union(
10498 	__isl_take isl_basic_set_list *list)
10499 {
10500 	int i;
10501 	isl_size n;
10502 	isl_space *space;
10503 	isl_basic_set *bset;
10504 	isl_set *set;
10505 
10506 	n = isl_basic_set_list_n_basic_set(list);
10507 	if (n < 0)
10508 		goto error;
10509 	if (n < 1)
10510 		isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
10511 			"expecting non-empty list", goto error);
10512 
10513 	bset = isl_basic_set_list_get_basic_set(list, 0);
10514 	space = isl_basic_set_get_space(bset);
10515 	isl_basic_set_free(bset);
10516 
10517 	set = isl_set_alloc_space(space, n, 0);
10518 	for (i = 0; i < n; ++i) {
10519 		bset = isl_basic_set_list_get_basic_set(list, i);
10520 		set = isl_set_add_basic_set(set, bset);
10521 	}
10522 
10523 	isl_basic_set_list_free(list);
10524 	return set;
10525 error:
10526 	isl_basic_set_list_free(list);
10527 	return NULL;
10528 }
10529 
10530 /* Return the union of the elements in the non-empty list "list".
10531  * All elements are assumed to live in the same space.
10532  */
isl_set_list_union(__isl_take isl_set_list * list)10533 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
10534 {
10535 	int i;
10536 	isl_size n;
10537 	isl_set *set;
10538 
10539 	n = isl_set_list_n_set(list);
10540 	if (n < 0)
10541 		goto error;
10542 	if (n < 1)
10543 		isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
10544 			"expecting non-empty list", goto error);
10545 
10546 	set = isl_set_list_get_set(list, 0);
10547 	for (i = 1; i < n; ++i) {
10548 		isl_set *set_i;
10549 
10550 		set_i = isl_set_list_get_set(list, i);
10551 		set = isl_set_union(set, set_i);
10552 	}
10553 
10554 	isl_set_list_free(list);
10555 	return set;
10556 error:
10557 	isl_set_list_free(list);
10558 	return NULL;
10559 }
10560 
isl_basic_map_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10561 __isl_give isl_basic_map *isl_basic_map_product(
10562 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10563 {
10564 	isl_space *space_result = NULL;
10565 	struct isl_basic_map *bmap;
10566 	unsigned in1, in2, out1, out2, nparam, total, pos;
10567 	struct isl_dim_map *dim_map1, *dim_map2;
10568 
10569 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10570 		goto error;
10571 	space_result = isl_space_product(isl_space_copy(bmap1->dim),
10572 						   isl_space_copy(bmap2->dim));
10573 
10574 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10575 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10576 	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10577 	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10578 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10579 
10580 	total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
10581 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10582 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10583 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10584 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10585 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10586 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10587 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10588 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10589 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
10590 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10591 
10592 	bmap = isl_basic_map_alloc_space(space_result,
10593 			bmap1->n_div + bmap2->n_div,
10594 			bmap1->n_eq + bmap2->n_eq,
10595 			bmap1->n_ineq + bmap2->n_ineq);
10596 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10597 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10598 	bmap = isl_basic_map_simplify(bmap);
10599 	return isl_basic_map_finalize(bmap);
10600 error:
10601 	isl_basic_map_free(bmap1);
10602 	isl_basic_map_free(bmap2);
10603 	return NULL;
10604 }
10605 
isl_basic_map_flat_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10606 __isl_give isl_basic_map *isl_basic_map_flat_product(
10607 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10608 {
10609 	isl_basic_map *prod;
10610 
10611 	prod = isl_basic_map_product(bmap1, bmap2);
10612 	prod = isl_basic_map_flatten(prod);
10613 	return prod;
10614 }
10615 
isl_basic_set_flat_product(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)10616 __isl_give isl_basic_set *isl_basic_set_flat_product(
10617 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10618 {
10619 	return isl_basic_map_flat_range_product(bset1, bset2);
10620 }
10621 
isl_basic_map_domain_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10622 __isl_give isl_basic_map *isl_basic_map_domain_product(
10623 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10624 {
10625 	isl_space *space1, *space2;
10626 	isl_space *space_result = NULL;
10627 	isl_basic_map *bmap;
10628 	isl_size in1, in2, out, nparam;
10629 	unsigned total, pos;
10630 	struct isl_dim_map *dim_map1, *dim_map2;
10631 
10632 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10633 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10634 	out = isl_basic_map_dim(bmap1, isl_dim_out);
10635 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10636 	if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
10637 		goto error;
10638 
10639 	space1 = isl_basic_map_get_space(bmap1);
10640 	space2 = isl_basic_map_get_space(bmap2);
10641 	space_result = isl_space_domain_product(space1, space2);
10642 
10643 	total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10644 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10645 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10646 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10647 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10648 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10649 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10650 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10651 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10652 	isl_dim_map_div(dim_map1, bmap1, pos += out);
10653 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10654 
10655 	bmap = isl_basic_map_alloc_space(space_result,
10656 			bmap1->n_div + bmap2->n_div,
10657 			bmap1->n_eq + bmap2->n_eq,
10658 			bmap1->n_ineq + bmap2->n_ineq);
10659 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10660 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10661 	bmap = isl_basic_map_simplify(bmap);
10662 	return isl_basic_map_finalize(bmap);
10663 error:
10664 	isl_basic_map_free(bmap1);
10665 	isl_basic_map_free(bmap2);
10666 	return NULL;
10667 }
10668 
isl_basic_map_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10669 __isl_give isl_basic_map *isl_basic_map_range_product(
10670 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10671 {
10672 	isl_bool rational;
10673 	isl_space *space_result = NULL;
10674 	isl_basic_map *bmap;
10675 	isl_size in, out1, out2, nparam;
10676 	unsigned total, pos;
10677 	struct isl_dim_map *dim_map1, *dim_map2;
10678 
10679 	rational = isl_basic_map_is_rational(bmap1);
10680 	if (rational >= 0 && rational)
10681 		rational = isl_basic_map_is_rational(bmap2);
10682 	in = isl_basic_map_dim(bmap1, isl_dim_in);
10683 	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10684 	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10685 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10686 	if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
10687 		goto error;
10688 
10689 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10690 		goto error;
10691 
10692 	space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10693 					   isl_space_copy(bmap2->dim));
10694 
10695 	total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10696 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10697 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10698 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10699 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10700 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10701 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10702 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10703 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10704 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
10705 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10706 
10707 	bmap = isl_basic_map_alloc_space(space_result,
10708 			bmap1->n_div + bmap2->n_div,
10709 			bmap1->n_eq + bmap2->n_eq,
10710 			bmap1->n_ineq + bmap2->n_ineq);
10711 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10712 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10713 	if (rational)
10714 		bmap = isl_basic_map_set_rational(bmap);
10715 	bmap = isl_basic_map_simplify(bmap);
10716 	return isl_basic_map_finalize(bmap);
10717 error:
10718 	isl_basic_map_free(bmap1);
10719 	isl_basic_map_free(bmap2);
10720 	return NULL;
10721 }
10722 
isl_basic_map_flat_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10723 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10724 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10725 {
10726 	isl_basic_map *prod;
10727 
10728 	prod = isl_basic_map_range_product(bmap1, bmap2);
10729 	prod = isl_basic_map_flatten_range(prod);
10730 	return prod;
10731 }
10732 
10733 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10734  * and collect the results.
10735  * The result live in the space obtained by calling "space_product"
10736  * on the spaces of "map1" and "map2".
10737  * If "remove_duplicates" is set then the result may contain duplicates
10738  * (even if the inputs do not) and so we try and remove the obvious
10739  * duplicates.
10740  */
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)10741 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10742 	__isl_take isl_map *map2,
10743 	__isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10744 					   __isl_take isl_space *right),
10745 	__isl_give isl_basic_map *(*basic_map_product)(
10746 		__isl_take isl_basic_map *left,
10747 		__isl_take isl_basic_map *right),
10748 	int remove_duplicates)
10749 {
10750 	unsigned flags = 0;
10751 	struct isl_map *result;
10752 	int i, j;
10753 	isl_bool m;
10754 
10755 	m = isl_map_has_equal_params(map1, map2);
10756 	if (m < 0)
10757 		goto error;
10758 	if (!m)
10759 		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10760 			"parameters don't match", goto error);
10761 
10762 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10763 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10764 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10765 
10766 	result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10767 					       isl_space_copy(map2->dim)),
10768 				map1->n * map2->n, flags);
10769 	if (!result)
10770 		goto error;
10771 	for (i = 0; i < map1->n; ++i)
10772 		for (j = 0; j < map2->n; ++j) {
10773 			struct isl_basic_map *part;
10774 			part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10775 						 isl_basic_map_copy(map2->p[j]));
10776 			if (isl_basic_map_is_empty(part))
10777 				isl_basic_map_free(part);
10778 			else
10779 				result = isl_map_add_basic_map(result, part);
10780 			if (!result)
10781 				goto error;
10782 		}
10783 	if (remove_duplicates)
10784 		result = isl_map_remove_obvious_duplicates(result);
10785 	isl_map_free(map1);
10786 	isl_map_free(map2);
10787 	return result;
10788 error:
10789 	isl_map_free(map1);
10790 	isl_map_free(map2);
10791 	return NULL;
10792 }
10793 
10794 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10795  */
isl_map_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10796 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10797 	__isl_take isl_map *map2)
10798 {
10799 	isl_map_align_params_bin(&map1, &map2);
10800 	return map_product(map1, map2, &isl_space_product,
10801 			&isl_basic_map_product, 0);
10802 }
10803 
10804 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10805  */
isl_map_flat_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10806 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10807 	__isl_take isl_map *map2)
10808 {
10809 	isl_map *prod;
10810 
10811 	prod = isl_map_product(map1, map2);
10812 	prod = isl_map_flatten(prod);
10813 	return prod;
10814 }
10815 
10816 /* Given two set A and B, construct its Cartesian product A x B.
10817  */
isl_set_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10818 __isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
10819 	__isl_take isl_set *set2)
10820 {
10821 	return isl_map_range_product(set1, set2);
10822 }
10823 
isl_set_flat_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10824 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10825 	__isl_take isl_set *set2)
10826 {
10827 	return isl_map_flat_range_product(set1, set2);
10828 }
10829 
10830 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10831  */
isl_map_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10832 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10833 	__isl_take isl_map *map2)
10834 {
10835 	isl_map_align_params_bin(&map1, &map2);
10836 	return map_product(map1, map2, &isl_space_domain_product,
10837 				&isl_basic_map_domain_product, 1);
10838 }
10839 
10840 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10841  */
isl_map_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10842 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10843 	__isl_take isl_map *map2)
10844 {
10845 	isl_map_align_params_bin(&map1, &map2);
10846 	return map_product(map1, map2, &isl_space_range_product,
10847 				&isl_basic_map_range_product, 1);
10848 }
10849 
10850 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10851  */
isl_map_factor_domain(__isl_take isl_map * map)10852 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10853 {
10854 	isl_space *space;
10855 	isl_size total1, keep1, total2, keep2;
10856 
10857 	total1 = isl_map_dim(map, isl_dim_in);
10858 	total2 = isl_map_dim(map, isl_dim_out);
10859 	if (total1 < 0 || total2 < 0)
10860 		return isl_map_free(map);
10861 	if (!isl_space_domain_is_wrapping(map->dim) ||
10862 	    !isl_space_range_is_wrapping(map->dim))
10863 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10864 			"not a product", return isl_map_free(map));
10865 
10866 	space = isl_map_get_space(map);
10867 	space = isl_space_factor_domain(space);
10868 	keep1 = isl_space_dim(space, isl_dim_in);
10869 	keep2 = isl_space_dim(space, isl_dim_out);
10870 	if (keep1 < 0 || keep2 < 0)
10871 		map = isl_map_free(map);
10872 	map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10873 	map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10874 	map = isl_map_reset_space(map, space);
10875 
10876 	return map;
10877 }
10878 
10879 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10880  */
isl_map_factor_range(__isl_take isl_map * map)10881 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10882 {
10883 	isl_space *space;
10884 	isl_size total1, keep1, total2, keep2;
10885 
10886 	total1 = isl_map_dim(map, isl_dim_in);
10887 	total2 = isl_map_dim(map, isl_dim_out);
10888 	if (total1 < 0 || total2 < 0)
10889 		return isl_map_free(map);
10890 	if (!isl_space_domain_is_wrapping(map->dim) ||
10891 	    !isl_space_range_is_wrapping(map->dim))
10892 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10893 			"not a product", return isl_map_free(map));
10894 
10895 	space = isl_map_get_space(map);
10896 	space = isl_space_factor_range(space);
10897 	keep1 = isl_space_dim(space, isl_dim_in);
10898 	keep2 = isl_space_dim(space, isl_dim_out);
10899 	if (keep1 < 0 || keep2 < 0)
10900 		map = isl_map_free(map);
10901 	map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10902 	map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10903 	map = isl_map_reset_space(map, space);
10904 
10905 	return map;
10906 }
10907 
10908 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10909  */
isl_map_domain_factor_domain(__isl_take isl_map * map)10910 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10911 {
10912 	isl_space *space;
10913 	isl_size total, keep;
10914 
10915 	total = isl_map_dim(map, isl_dim_in);
10916 	if (total < 0)
10917 		return isl_map_free(map);
10918 	if (!isl_space_domain_is_wrapping(map->dim))
10919 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10920 			"domain is not a product", return isl_map_free(map));
10921 
10922 	space = isl_map_get_space(map);
10923 	space = isl_space_domain_factor_domain(space);
10924 	keep = isl_space_dim(space, isl_dim_in);
10925 	if (keep < 0)
10926 		map = isl_map_free(map);
10927 	map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10928 	map = isl_map_reset_space(map, space);
10929 
10930 	return map;
10931 }
10932 
10933 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10934  */
isl_map_domain_factor_range(__isl_take isl_map * map)10935 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10936 {
10937 	isl_space *space;
10938 	isl_size total, keep;
10939 
10940 	total = isl_map_dim(map, isl_dim_in);
10941 	if (total < 0)
10942 		return isl_map_free(map);
10943 	if (!isl_space_domain_is_wrapping(map->dim))
10944 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10945 			"domain is not a product", return isl_map_free(map));
10946 
10947 	space = isl_map_get_space(map);
10948 	space = isl_space_domain_factor_range(space);
10949 	keep = isl_space_dim(space, isl_dim_in);
10950 	if (keep < 0)
10951 		map = isl_map_free(map);
10952 	map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10953 	map = isl_map_reset_space(map, space);
10954 
10955 	return map;
10956 }
10957 
10958 /* Given a map A -> [B -> C], extract the map A -> B.
10959  */
isl_map_range_factor_domain(__isl_take isl_map * map)10960 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10961 {
10962 	isl_space *space;
10963 	isl_size total, keep;
10964 
10965 	total = isl_map_dim(map, isl_dim_out);
10966 	if (total < 0)
10967 		return isl_map_free(map);
10968 	if (!isl_space_range_is_wrapping(map->dim))
10969 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10970 			"range is not a product", return isl_map_free(map));
10971 
10972 	space = isl_map_get_space(map);
10973 	space = isl_space_range_factor_domain(space);
10974 	keep = isl_space_dim(space, isl_dim_out);
10975 	if (keep < 0)
10976 		map = isl_map_free(map);
10977 	map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10978 	map = isl_map_reset_space(map, space);
10979 
10980 	return map;
10981 }
10982 
10983 /* Given a map A -> [B -> C], extract the map A -> C.
10984  */
isl_map_range_factor_range(__isl_take isl_map * map)10985 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10986 {
10987 	isl_space *space;
10988 	isl_size total, keep;
10989 
10990 	total = isl_map_dim(map, isl_dim_out);
10991 	if (total < 0)
10992 		return isl_map_free(map);
10993 	if (!isl_space_range_is_wrapping(map->dim))
10994 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10995 			"range is not a product", return isl_map_free(map));
10996 
10997 	space = isl_map_get_space(map);
10998 	space = isl_space_range_factor_range(space);
10999 	keep = isl_space_dim(space, isl_dim_out);
11000 	if (keep < 0)
11001 		map = isl_map_free(map);
11002 	map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
11003 	map = isl_map_reset_space(map, space);
11004 
11005 	return map;
11006 }
11007 
11008 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
11009  */
isl_map_flat_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)11010 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
11011 	__isl_take isl_map *map2)
11012 {
11013 	isl_map *prod;
11014 
11015 	prod = isl_map_domain_product(map1, map2);
11016 	prod = isl_map_flatten_domain(prod);
11017 	return prod;
11018 }
11019 
11020 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
11021  */
isl_map_flat_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)11022 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
11023 	__isl_take isl_map *map2)
11024 {
11025 	isl_map *prod;
11026 
11027 	prod = isl_map_range_product(map1, map2);
11028 	prod = isl_map_flatten_range(prod);
11029 	return prod;
11030 }
11031 
isl_basic_map_get_hash(__isl_keep isl_basic_map * bmap)11032 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
11033 {
11034 	int i;
11035 	uint32_t hash = isl_hash_init();
11036 	isl_size total;
11037 
11038 	if (!bmap)
11039 		return 0;
11040 	bmap = isl_basic_map_copy(bmap);
11041 	bmap = isl_basic_map_normalize(bmap);
11042 	total = isl_basic_map_dim(bmap, isl_dim_all);
11043 	if (total < 0)
11044 		return 0;
11045 	isl_hash_byte(hash, bmap->n_eq & 0xFF);
11046 	for (i = 0; i < bmap->n_eq; ++i) {
11047 		uint32_t c_hash;
11048 		c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
11049 		isl_hash_hash(hash, c_hash);
11050 	}
11051 	isl_hash_byte(hash, bmap->n_ineq & 0xFF);
11052 	for (i = 0; i < bmap->n_ineq; ++i) {
11053 		uint32_t c_hash;
11054 		c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
11055 		isl_hash_hash(hash, c_hash);
11056 	}
11057 	isl_hash_byte(hash, bmap->n_div & 0xFF);
11058 	for (i = 0; i < bmap->n_div; ++i) {
11059 		uint32_t c_hash;
11060 		if (isl_int_is_zero(bmap->div[i][0]))
11061 			continue;
11062 		isl_hash_byte(hash, i & 0xFF);
11063 		c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
11064 		isl_hash_hash(hash, c_hash);
11065 	}
11066 	isl_basic_map_free(bmap);
11067 	return hash;
11068 }
11069 
isl_basic_set_get_hash(__isl_keep isl_basic_set * bset)11070 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
11071 {
11072 	return isl_basic_map_get_hash(bset_to_bmap(bset));
11073 }
11074 
isl_map_get_hash(__isl_keep isl_map * map)11075 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
11076 {
11077 	int i;
11078 	uint32_t hash;
11079 
11080 	if (!map)
11081 		return 0;
11082 	map = isl_map_copy(map);
11083 	map = isl_map_normalize(map);
11084 	if (!map)
11085 		return 0;
11086 
11087 	hash = isl_hash_init();
11088 	for (i = 0; i < map->n; ++i) {
11089 		uint32_t bmap_hash;
11090 		bmap_hash = isl_basic_map_get_hash(map->p[i]);
11091 		isl_hash_hash(hash, bmap_hash);
11092 	}
11093 
11094 	isl_map_free(map);
11095 
11096 	return hash;
11097 }
11098 
isl_set_get_hash(__isl_keep isl_set * set)11099 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
11100 {
11101 	return isl_map_get_hash(set_to_map(set));
11102 }
11103 
11104 /* Return the number of basic maps in the (current) representation of "map".
11105  */
isl_map_n_basic_map(__isl_keep isl_map * map)11106 isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
11107 {
11108 	return map ? map->n : isl_size_error;
11109 }
11110 
isl_set_n_basic_set(__isl_keep isl_set * set)11111 isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
11112 {
11113 	return set ? set->n : isl_size_error;
11114 }
11115 
isl_map_foreach_basic_map(__isl_keep isl_map * map,isl_stat (* fn)(__isl_take isl_basic_map * bmap,void * user),void * user)11116 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
11117 	isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
11118 {
11119 	int i;
11120 
11121 	if (!map)
11122 		return isl_stat_error;
11123 
11124 	for (i = 0; i < map->n; ++i)
11125 		if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
11126 			return isl_stat_error;
11127 
11128 	return isl_stat_ok;
11129 }
11130 
isl_set_foreach_basic_set(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_basic_set * bset,void * user),void * user)11131 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
11132 	isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
11133 {
11134 	int i;
11135 
11136 	if (!set)
11137 		return isl_stat_error;
11138 
11139 	for (i = 0; i < set->n; ++i)
11140 		if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
11141 			return isl_stat_error;
11142 
11143 	return isl_stat_ok;
11144 }
11145 
11146 /* Does "test" succeed on every basic set in "set"?
11147  */
isl_set_every_basic_set(__isl_keep isl_set * set,isl_bool (* test)(__isl_keep isl_basic_set * bset,void * user),void * user)11148 isl_bool isl_set_every_basic_set(__isl_keep isl_set *set,
11149 	isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),
11150 	void *user)
11151 {
11152 	int i;
11153 
11154 	if (!set)
11155 		return isl_bool_error;
11156 
11157 	for (i = 0; i < set->n; ++i) {
11158 		isl_bool r;
11159 
11160 		r = test(set->p[i], user);
11161 		if (r < 0 || !r)
11162 			return r;
11163 	}
11164 
11165 	return isl_bool_true;
11166 }
11167 
11168 /* Return a list of basic sets, the union of which is equal to "set".
11169  */
isl_set_get_basic_set_list(__isl_keep isl_set * set)11170 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
11171 	__isl_keep isl_set *set)
11172 {
11173 	int i;
11174 	isl_basic_set_list *list;
11175 
11176 	if (!set)
11177 		return NULL;
11178 
11179 	list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
11180 	for (i = 0; i < set->n; ++i) {
11181 		isl_basic_set *bset;
11182 
11183 		bset = isl_basic_set_copy(set->p[i]);
11184 		list = isl_basic_set_list_add(list, bset);
11185 	}
11186 
11187 	return list;
11188 }
11189 
isl_basic_set_lift(__isl_take isl_basic_set * bset)11190 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
11191 {
11192 	isl_space *space;
11193 
11194 	if (!bset)
11195 		return NULL;
11196 
11197 	bset = isl_basic_set_cow(bset);
11198 	if (!bset)
11199 		return NULL;
11200 
11201 	space = isl_basic_set_get_space(bset);
11202 	space = isl_space_lift(space, bset->n_div);
11203 	if (!space)
11204 		goto error;
11205 	isl_space_free(bset->dim);
11206 	bset->dim = space;
11207 	bset->extra -= bset->n_div;
11208 	bset->n_div = 0;
11209 
11210 	bset = isl_basic_set_finalize(bset);
11211 
11212 	return bset;
11213 error:
11214 	isl_basic_set_free(bset);
11215 	return NULL;
11216 }
11217 
isl_set_lift(__isl_take isl_set * set)11218 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
11219 {
11220 	int i;
11221 	isl_space *space;
11222 	unsigned n_div;
11223 
11224 	set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
11225 
11226 	if (!set)
11227 		return NULL;
11228 
11229 	set = isl_set_cow(set);
11230 	if (!set)
11231 		return NULL;
11232 
11233 	n_div = set->p[0]->n_div;
11234 	space = isl_set_get_space(set);
11235 	space = isl_space_lift(space, n_div);
11236 	if (!space)
11237 		goto error;
11238 	isl_space_free(set->dim);
11239 	set->dim = space;
11240 
11241 	for (i = 0; i < set->n; ++i) {
11242 		set->p[i] = isl_basic_set_lift(set->p[i]);
11243 		if (!set->p[i])
11244 			goto error;
11245 	}
11246 
11247 	return set;
11248 error:
11249 	isl_set_free(set);
11250 	return NULL;
11251 }
11252 
isl_basic_set_size(__isl_keep isl_basic_set * bset)11253 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
11254 {
11255 	isl_size dim;
11256 	int size = 0;
11257 
11258 	dim = isl_basic_set_dim(bset, isl_dim_all);
11259 	if (dim < 0)
11260 		return -1;
11261 	size += bset->n_eq * (1 + dim);
11262 	size += bset->n_ineq * (1 + dim);
11263 	size += bset->n_div * (2 + dim);
11264 
11265 	return size;
11266 }
11267 
isl_set_size(__isl_keep isl_set * set)11268 int isl_set_size(__isl_keep isl_set *set)
11269 {
11270 	int i;
11271 	int size = 0;
11272 
11273 	if (!set)
11274 		return -1;
11275 
11276 	for (i = 0; i < set->n; ++i)
11277 		size += isl_basic_set_size(set->p[i]);
11278 
11279 	return size;
11280 }
11281 
11282 /* Check if there is any lower bound (if lower == 0) and/or upper
11283  * bound (if upper == 0) on the specified dim.
11284  */
basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int lower,int upper)11285 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11286 	enum isl_dim_type type, unsigned pos, int lower, int upper)
11287 {
11288 	int i;
11289 
11290 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
11291 		return isl_bool_error;
11292 
11293 	pos += isl_basic_map_offset(bmap, type);
11294 
11295 	for (i = 0; i < bmap->n_div; ++i) {
11296 		if (isl_int_is_zero(bmap->div[i][0]))
11297 			continue;
11298 		if (!isl_int_is_zero(bmap->div[i][1 + pos]))
11299 			return isl_bool_true;
11300 	}
11301 
11302 	for (i = 0; i < bmap->n_eq; ++i)
11303 		if (!isl_int_is_zero(bmap->eq[i][pos]))
11304 			return isl_bool_true;
11305 
11306 	for (i = 0; i < bmap->n_ineq; ++i) {
11307 		int sgn = isl_int_sgn(bmap->ineq[i][pos]);
11308 		if (sgn > 0)
11309 			lower = 1;
11310 		if (sgn < 0)
11311 			upper = 1;
11312 	}
11313 
11314 	return lower && upper;
11315 }
11316 
isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11317 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11318 	enum isl_dim_type type, unsigned pos)
11319 {
11320 	return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
11321 }
11322 
isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11323 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
11324 	enum isl_dim_type type, unsigned pos)
11325 {
11326 	return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
11327 }
11328 
isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11329 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
11330 	enum isl_dim_type type, unsigned pos)
11331 {
11332 	return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
11333 }
11334 
isl_map_dim_is_bounded(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)11335 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
11336 	enum isl_dim_type type, unsigned pos)
11337 {
11338 	int i;
11339 
11340 	if (!map)
11341 		return isl_bool_error;
11342 
11343 	for (i = 0; i < map->n; ++i) {
11344 		isl_bool bounded;
11345 		bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
11346 		if (bounded < 0 || !bounded)
11347 			return bounded;
11348 	}
11349 
11350 	return isl_bool_true;
11351 }
11352 
11353 /* Return true if the specified dim is involved in both an upper bound
11354  * and a lower bound.
11355  */
isl_set_dim_is_bounded(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11356 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
11357 	enum isl_dim_type type, unsigned pos)
11358 {
11359 	return isl_map_dim_is_bounded(set_to_map(set), type, pos);
11360 }
11361 
11362 /* Does "map" have a bound (according to "fn") for any of its basic maps?
11363  */
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))11364 static isl_bool has_any_bound(__isl_keep isl_map *map,
11365 	enum isl_dim_type type, unsigned pos,
11366 	isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11367 		  enum isl_dim_type type, unsigned pos))
11368 {
11369 	int i;
11370 
11371 	if (!map)
11372 		return isl_bool_error;
11373 
11374 	for (i = 0; i < map->n; ++i) {
11375 		isl_bool bounded;
11376 		bounded = fn(map->p[i], type, pos);
11377 		if (bounded < 0 || bounded)
11378 			return bounded;
11379 	}
11380 
11381 	return isl_bool_false;
11382 }
11383 
11384 /* Return 1 if the specified dim is involved in any lower bound.
11385  */
isl_set_dim_has_any_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11386 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
11387 	enum isl_dim_type type, unsigned pos)
11388 {
11389 	return has_any_bound(set, type, pos,
11390 				&isl_basic_map_dim_has_lower_bound);
11391 }
11392 
11393 /* Return 1 if the specified dim is involved in any upper bound.
11394  */
isl_set_dim_has_any_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11395 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
11396 	enum isl_dim_type type, unsigned pos)
11397 {
11398 	return has_any_bound(set, type, pos,
11399 				&isl_basic_map_dim_has_upper_bound);
11400 }
11401 
11402 /* Does "map" have a bound (according to "fn") for all of its basic maps?
11403  */
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))11404 static isl_bool has_bound(__isl_keep isl_map *map,
11405 	enum isl_dim_type type, unsigned pos,
11406 	isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11407 		  enum isl_dim_type type, unsigned pos))
11408 {
11409 	int i;
11410 
11411 	if (!map)
11412 		return isl_bool_error;
11413 
11414 	for (i = 0; i < map->n; ++i) {
11415 		isl_bool bounded;
11416 		bounded = fn(map->p[i], type, pos);
11417 		if (bounded < 0 || !bounded)
11418 			return bounded;
11419 	}
11420 
11421 	return isl_bool_true;
11422 }
11423 
11424 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
11425  */
isl_set_dim_has_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11426 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
11427 	enum isl_dim_type type, unsigned pos)
11428 {
11429 	return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
11430 }
11431 
11432 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
11433  */
isl_set_dim_has_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11434 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
11435 	enum isl_dim_type type, unsigned pos)
11436 {
11437 	return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
11438 }
11439 
11440 /* For each of the "n" variables starting at "first", determine
11441  * the sign of the variable and put the results in the first "n"
11442  * elements of the array "signs".
11443  * Sign
11444  *	1 means that the variable is non-negative
11445  *	-1 means that the variable is non-positive
11446  *	0 means the variable attains both positive and negative values.
11447  */
isl_basic_set_vars_get_sign(__isl_keep isl_basic_set * bset,unsigned first,unsigned n,int * signs)11448 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
11449 	unsigned first, unsigned n, int *signs)
11450 {
11451 	isl_vec *bound = NULL;
11452 	struct isl_tab *tab = NULL;
11453 	struct isl_tab_undo *snap;
11454 	int i;
11455 	isl_size total;
11456 
11457 	total = isl_basic_set_dim(bset, isl_dim_all);
11458 	if (total < 0 || !signs)
11459 		return isl_stat_error;
11460 
11461 	bound = isl_vec_alloc(bset->ctx, 1 + total);
11462 	tab = isl_tab_from_basic_set(bset, 0);
11463 	if (!bound || !tab)
11464 		goto error;
11465 
11466 	isl_seq_clr(bound->el, bound->size);
11467 	isl_int_set_si(bound->el[0], -1);
11468 
11469 	snap = isl_tab_snap(tab);
11470 	for (i = 0; i < n; ++i) {
11471 		int empty;
11472 
11473 		isl_int_set_si(bound->el[1 + first + i], -1);
11474 		if (isl_tab_add_ineq(tab, bound->el) < 0)
11475 			goto error;
11476 		empty = tab->empty;
11477 		isl_int_set_si(bound->el[1 + first + i], 0);
11478 		if (isl_tab_rollback(tab, snap) < 0)
11479 			goto error;
11480 
11481 		if (empty) {
11482 			signs[i] = 1;
11483 			continue;
11484 		}
11485 
11486 		isl_int_set_si(bound->el[1 + first + i], 1);
11487 		if (isl_tab_add_ineq(tab, bound->el) < 0)
11488 			goto error;
11489 		empty = tab->empty;
11490 		isl_int_set_si(bound->el[1 + first + i], 0);
11491 		if (isl_tab_rollback(tab, snap) < 0)
11492 			goto error;
11493 
11494 		signs[i] = empty ? -1 : 0;
11495 	}
11496 
11497 	isl_tab_free(tab);
11498 	isl_vec_free(bound);
11499 	return isl_stat_ok;
11500 error:
11501 	isl_tab_free(tab);
11502 	isl_vec_free(bound);
11503 	return isl_stat_error;
11504 }
11505 
isl_basic_set_dims_get_sign(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n,int * signs)11506 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
11507 	enum isl_dim_type type, unsigned first, unsigned n, int *signs)
11508 {
11509 	if (!bset || !signs)
11510 		return isl_stat_error;
11511 	if (isl_basic_set_check_range(bset, type, first, n) < 0)
11512 		return isl_stat_error;
11513 
11514 	first += pos(bset->dim, type) - 1;
11515 	return isl_basic_set_vars_get_sign(bset, first, n, signs);
11516 }
11517 
11518 /* Is it possible for the integer division "div" to depend (possibly
11519  * indirectly) on any output dimensions?
11520  *
11521  * If the div is undefined, then we conservatively assume that it
11522  * may depend on them.
11523  * Otherwise, we check if it actually depends on them or on any integer
11524  * divisions that may depend on them.
11525  */
div_may_involve_output(__isl_keep isl_basic_map * bmap,int div)11526 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
11527 {
11528 	int i;
11529 	isl_size n_out, n_div;
11530 	unsigned o_out, o_div;
11531 
11532 	if (isl_int_is_zero(bmap->div[div][0]))
11533 		return isl_bool_true;
11534 
11535 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11536 	if (n_out < 0)
11537 		return isl_bool_error;
11538 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11539 
11540 	if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
11541 		return isl_bool_true;
11542 
11543 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11544 	if (n_div < 0)
11545 		return isl_bool_error;
11546 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11547 
11548 	for (i = 0; i < n_div; ++i) {
11549 		isl_bool may_involve;
11550 
11551 		if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
11552 			continue;
11553 		may_involve = div_may_involve_output(bmap, i);
11554 		if (may_involve < 0 || may_involve)
11555 			return may_involve;
11556 	}
11557 
11558 	return isl_bool_false;
11559 }
11560 
11561 /* Return the first integer division of "bmap" in the range
11562  * [first, first + n[ that may depend on any output dimensions and
11563  * that has a non-zero coefficient in "c" (where the first coefficient
11564  * in "c" corresponds to integer division "first").
11565  */
first_div_may_involve_output(__isl_keep isl_basic_map * bmap,isl_int * c,int first,int n)11566 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
11567 	isl_int *c, int first, int n)
11568 {
11569 	int k;
11570 
11571 	if (!bmap)
11572 		return -1;
11573 
11574 	for (k = first; k < first + n; ++k) {
11575 		isl_bool may_involve;
11576 
11577 		if (isl_int_is_zero(c[k]))
11578 			continue;
11579 		may_involve = div_may_involve_output(bmap, k);
11580 		if (may_involve < 0)
11581 			return -1;
11582 		if (may_involve)
11583 			return k;
11584 	}
11585 
11586 	return first + n;
11587 }
11588 
11589 /* Look for a pair of inequality constraints in "bmap" of the form
11590  *
11591  *	-l + i >= 0		or		i >= l
11592  * and
11593  *	n + l - i >= 0		or		i <= l + n
11594  *
11595  * with n < "m" and i the output dimension at position "pos".
11596  * (Note that n >= 0 as otherwise the two constraints would conflict.)
11597  * Furthermore, "l" is only allowed to involve parameters, input dimensions
11598  * and earlier output dimensions, as well as integer divisions that do
11599  * not involve any of the output dimensions.
11600  *
11601  * Return the index of the first inequality constraint or bmap->n_ineq
11602  * if no such pair can be found.
11603  */
find_modulo_constraint_pair(__isl_keep isl_basic_map * bmap,int pos,isl_int m)11604 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
11605 	int pos, isl_int m)
11606 {
11607 	int i, j;
11608 	isl_ctx *ctx;
11609 	isl_size total;
11610 	isl_size n_div, n_out;
11611 	unsigned o_div, o_out;
11612 	int less;
11613 
11614 	total = isl_basic_map_dim(bmap, isl_dim_all);
11615 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11616 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11617 	if (total < 0 || n_out < 0 || n_div < 0)
11618 		return -1;
11619 
11620 	ctx = isl_basic_map_get_ctx(bmap);
11621 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11622 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11623 	for (i = 0; i < bmap->n_ineq; ++i) {
11624 		if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
11625 			continue;
11626 		if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
11627 					n_out - (pos + 1)) != -1)
11628 			continue;
11629 		if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11630 						0, n_div) < n_div)
11631 			continue;
11632 		for (j = i + 1; j < bmap->n_ineq; ++j) {
11633 			if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11634 					    ctx->one))
11635 				continue;
11636 			if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11637 					    bmap->ineq[j] + 1, total))
11638 				continue;
11639 			break;
11640 		}
11641 		if (j >= bmap->n_ineq)
11642 			continue;
11643 		isl_int_add(bmap->ineq[i][0],
11644 			    bmap->ineq[i][0], bmap->ineq[j][0]);
11645 		less = isl_int_abs_lt(bmap->ineq[i][0], m);
11646 		isl_int_sub(bmap->ineq[i][0],
11647 			    bmap->ineq[i][0], bmap->ineq[j][0]);
11648 		if (!less)
11649 			continue;
11650 		if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11651 			return i;
11652 		else
11653 			return j;
11654 	}
11655 
11656 	return bmap->n_ineq;
11657 }
11658 
11659 /* Return the index of the equality of "bmap" that defines
11660  * the output dimension "pos" in terms of earlier dimensions.
11661  * The equality may also involve integer divisions, as long
11662  * as those integer divisions are defined in terms of
11663  * parameters or input dimensions.
11664  * In this case, *div is set to the number of integer divisions and
11665  * *ineq is set to the number of inequality constraints (provided
11666  * div and ineq are not NULL).
11667  *
11668  * The equality may also involve a single integer division involving
11669  * the output dimensions (typically only output dimension "pos") as
11670  * long as the coefficient of output dimension "pos" is 1 or -1 and
11671  * there is a pair of constraints i >= l and i <= l + n, with i referring
11672  * to output dimension "pos", l an expression involving only earlier
11673  * dimensions and n smaller than the coefficient of the integer division
11674  * in the equality.  In this case, the output dimension can be defined
11675  * in terms of a modulo expression that does not involve the integer division.
11676  * *div is then set to this single integer division and
11677  * *ineq is set to the index of constraint i >= l.
11678  *
11679  * Return bmap->n_eq if there is no such equality.
11680  * Return -1 on error.
11681  */
isl_basic_map_output_defining_equality(__isl_keep isl_basic_map * bmap,int pos,int * div,int * ineq)11682 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11683 	int pos, int *div, int *ineq)
11684 {
11685 	int j, k, l;
11686 	isl_size n_div, n_out;
11687 	unsigned o_div, o_out;
11688 
11689 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11690 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11691 	if (n_out < 0 || n_div < 0)
11692 		return -1;
11693 
11694 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11695 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11696 
11697 	if (ineq)
11698 		*ineq = bmap->n_ineq;
11699 	if (div)
11700 		*div = n_div;
11701 	for (j = 0; j < bmap->n_eq; ++j) {
11702 		if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11703 			continue;
11704 		if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11705 					n_out - (pos + 1)) != -1)
11706 			continue;
11707 		k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11708 						0, n_div);
11709 		if (k >= n_div)
11710 			return j;
11711 		if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11712 		    !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11713 			continue;
11714 		if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11715 						k + 1, n_div - (k+1)) < n_div)
11716 			continue;
11717 		l = find_modulo_constraint_pair(bmap, pos,
11718 						bmap->eq[j][o_div + k]);
11719 		if (l < 0)
11720 			return -1;
11721 		if (l >= bmap->n_ineq)
11722 			continue;
11723 		if (div)
11724 			*div = k;
11725 		if (ineq)
11726 			*ineq = l;
11727 		return j;
11728 	}
11729 
11730 	return bmap->n_eq;
11731 }
11732 
11733 /* Check if the given basic map is obviously single-valued.
11734  * In particular, for each output dimension, check that there is
11735  * an equality that defines the output dimension in terms of
11736  * earlier dimensions.
11737  */
isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map * bmap)11738 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11739 {
11740 	int i;
11741 	isl_size n_out;
11742 
11743 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11744 	if (n_out < 0)
11745 		return isl_bool_error;
11746 
11747 	for (i = 0; i < n_out; ++i) {
11748 		int eq;
11749 
11750 		eq = isl_basic_map_output_defining_equality(bmap, i,
11751 							    NULL, NULL);
11752 		if (eq < 0)
11753 			return isl_bool_error;
11754 		if (eq >= bmap->n_eq)
11755 			return isl_bool_false;
11756 	}
11757 
11758 	return isl_bool_true;
11759 }
11760 
11761 /* Check if the given basic map is single-valued.
11762  * We simply compute
11763  *
11764  *	M \circ M^-1
11765  *
11766  * and check if the result is a subset of the identity mapping.
11767  */
isl_basic_map_is_single_valued(__isl_keep isl_basic_map * bmap)11768 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11769 {
11770 	isl_space *space;
11771 	isl_basic_map *test;
11772 	isl_basic_map *id;
11773 	isl_bool sv;
11774 
11775 	sv = isl_basic_map_plain_is_single_valued(bmap);
11776 	if (sv < 0 || sv)
11777 		return sv;
11778 
11779 	test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11780 	test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11781 
11782 	space = isl_basic_map_get_space(bmap);
11783 	space = isl_space_map_from_set(isl_space_range(space));
11784 	id = isl_basic_map_identity(space);
11785 
11786 	sv = isl_basic_map_is_subset(test, id);
11787 
11788 	isl_basic_map_free(test);
11789 	isl_basic_map_free(id);
11790 
11791 	return sv;
11792 }
11793 
11794 /* Check if the given map is obviously single-valued.
11795  */
isl_map_plain_is_single_valued(__isl_keep isl_map * map)11796 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11797 {
11798 	if (!map)
11799 		return isl_bool_error;
11800 	if (map->n == 0)
11801 		return isl_bool_true;
11802 	if (map->n >= 2)
11803 		return isl_bool_false;
11804 
11805 	return isl_basic_map_plain_is_single_valued(map->p[0]);
11806 }
11807 
11808 /* Check if the given map is single-valued.
11809  * We simply compute
11810  *
11811  *	M \circ M^-1
11812  *
11813  * and check if the result is a subset of the identity mapping.
11814  */
isl_map_is_single_valued(__isl_keep isl_map * map)11815 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11816 {
11817 	isl_space *space;
11818 	isl_map *test;
11819 	isl_map *id;
11820 	isl_bool sv;
11821 
11822 	sv = isl_map_plain_is_single_valued(map);
11823 	if (sv < 0 || sv)
11824 		return sv;
11825 
11826 	test = isl_map_reverse(isl_map_copy(map));
11827 	test = isl_map_apply_range(test, isl_map_copy(map));
11828 
11829 	space = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11830 	id = isl_map_identity(space);
11831 
11832 	sv = isl_map_is_subset(test, id);
11833 
11834 	isl_map_free(test);
11835 	isl_map_free(id);
11836 
11837 	return sv;
11838 }
11839 
isl_map_is_injective(__isl_keep isl_map * map)11840 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11841 {
11842 	isl_bool in;
11843 
11844 	map = isl_map_copy(map);
11845 	map = isl_map_reverse(map);
11846 	in = isl_map_is_single_valued(map);
11847 	isl_map_free(map);
11848 
11849 	return in;
11850 }
11851 
11852 /* Check if the given map is obviously injective.
11853  */
isl_map_plain_is_injective(__isl_keep isl_map * map)11854 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11855 {
11856 	isl_bool in;
11857 
11858 	map = isl_map_copy(map);
11859 	map = isl_map_reverse(map);
11860 	in = isl_map_plain_is_single_valued(map);
11861 	isl_map_free(map);
11862 
11863 	return in;
11864 }
11865 
isl_map_is_bijective(__isl_keep isl_map * map)11866 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11867 {
11868 	isl_bool sv;
11869 
11870 	sv = isl_map_is_single_valued(map);
11871 	if (sv < 0 || !sv)
11872 		return sv;
11873 
11874 	return isl_map_is_injective(map);
11875 }
11876 
isl_set_is_singleton(__isl_keep isl_set * set)11877 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11878 {
11879 	return isl_map_is_single_valued(set_to_map(set));
11880 }
11881 
11882 /* Does "map" only map elements to themselves?
11883  *
11884  * If the domain and range spaces are different, then "map"
11885  * is considered not to be an identity relation, even if it is empty.
11886  * Otherwise, construct the maximal identity relation and
11887  * check whether "map" is a subset of this relation.
11888  */
isl_map_is_identity(__isl_keep isl_map * map)11889 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11890 {
11891 	isl_map *id;
11892 	isl_bool equal, is_identity;
11893 
11894 	equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
11895 	if (equal < 0 || !equal)
11896 		return equal;
11897 
11898 	id = isl_map_identity(isl_map_get_space(map));
11899 	is_identity = isl_map_is_subset(map, id);
11900 	isl_map_free(id);
11901 
11902 	return is_identity;
11903 }
11904 
isl_map_is_translation(__isl_keep isl_map * map)11905 int isl_map_is_translation(__isl_keep isl_map *map)
11906 {
11907 	int ok;
11908 	isl_set *delta;
11909 
11910 	delta = isl_map_deltas(isl_map_copy(map));
11911 	ok = isl_set_is_singleton(delta);
11912 	isl_set_free(delta);
11913 
11914 	return ok;
11915 }
11916 
unique(isl_int * p,unsigned pos,unsigned len)11917 static int unique(isl_int *p, unsigned pos, unsigned len)
11918 {
11919 	if (isl_seq_first_non_zero(p, pos) != -1)
11920 		return 0;
11921 	if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11922 		return 0;
11923 	return 1;
11924 }
11925 
isl_basic_set_is_box(__isl_keep isl_basic_set * bset)11926 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11927 {
11928 	int i, j;
11929 	isl_size nvar, n_div;
11930 	unsigned ovar;
11931 
11932 	n_div = isl_basic_set_dim(bset, isl_dim_div);
11933 	if (n_div < 0)
11934 		return isl_bool_error;
11935 	if (n_div != 0)
11936 		return isl_bool_false;
11937 
11938 	nvar = isl_basic_set_dim(bset, isl_dim_set);
11939 	if (nvar < 0)
11940 		return isl_bool_error;
11941 	ovar = isl_space_offset(bset->dim, isl_dim_set);
11942 	for (j = 0; j < nvar; ++j) {
11943 		int lower = 0, upper = 0;
11944 		for (i = 0; i < bset->n_eq; ++i) {
11945 			if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11946 				continue;
11947 			if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11948 				return isl_bool_false;
11949 			break;
11950 		}
11951 		if (i < bset->n_eq)
11952 			continue;
11953 		for (i = 0; i < bset->n_ineq; ++i) {
11954 			if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11955 				continue;
11956 			if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11957 				return isl_bool_false;
11958 			if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11959 				lower = 1;
11960 			else
11961 				upper = 1;
11962 		}
11963 		if (!lower || !upper)
11964 			return isl_bool_false;
11965 	}
11966 
11967 	return isl_bool_true;
11968 }
11969 
isl_set_is_box(__isl_keep isl_set * set)11970 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11971 {
11972 	if (!set)
11973 		return isl_bool_error;
11974 	if (set->n != 1)
11975 		return isl_bool_false;
11976 
11977 	return isl_basic_set_is_box(set->p[0]);
11978 }
11979 
isl_basic_set_is_wrapping(__isl_keep isl_basic_set * bset)11980 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11981 {
11982 	if (!bset)
11983 		return isl_bool_error;
11984 
11985 	return isl_space_is_wrapping(bset->dim);
11986 }
11987 
isl_set_is_wrapping(__isl_keep isl_set * set)11988 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11989 {
11990 	if (!set)
11991 		return isl_bool_error;
11992 
11993 	return isl_space_is_wrapping(set->dim);
11994 }
11995 
11996 /* Modify the space of "map" through a call to "change".
11997  * If "can_change" is set (not NULL), then first call it to check
11998  * if the modification is allowed, printing the error message "cannot_change"
11999  * if it is not.
12000  */
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))12001 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
12002 	isl_bool (*can_change)(__isl_keep isl_map *map),
12003 	const char *cannot_change,
12004 	__isl_give isl_space *(*change)(__isl_take isl_space *space))
12005 {
12006 	isl_bool ok;
12007 	isl_space *space;
12008 
12009 	if (!map)
12010 		return NULL;
12011 
12012 	ok = can_change ? can_change(map) : isl_bool_true;
12013 	if (ok < 0)
12014 		return isl_map_free(map);
12015 	if (!ok)
12016 		isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
12017 			return isl_map_free(map));
12018 
12019 	space = change(isl_map_get_space(map));
12020 	map = isl_map_reset_space(map, space);
12021 
12022 	return map;
12023 }
12024 
12025 /* Is the domain of "map" a wrapped relation?
12026  */
isl_map_domain_is_wrapping(__isl_keep isl_map * map)12027 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
12028 {
12029 	if (!map)
12030 		return isl_bool_error;
12031 
12032 	return isl_space_domain_is_wrapping(map->dim);
12033 }
12034 
12035 /* Does "map" have a wrapped relation in both domain and range?
12036  */
isl_map_is_product(__isl_keep isl_map * map)12037 isl_bool isl_map_is_product(__isl_keep isl_map *map)
12038 {
12039 	return isl_space_is_product(isl_map_peek_space(map));
12040 }
12041 
12042 /* Is the range of "map" a wrapped relation?
12043  */
isl_map_range_is_wrapping(__isl_keep isl_map * map)12044 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
12045 {
12046 	if (!map)
12047 		return isl_bool_error;
12048 
12049 	return isl_space_range_is_wrapping(map->dim);
12050 }
12051 
isl_basic_map_wrap(__isl_take isl_basic_map * bmap)12052 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
12053 {
12054 	isl_space *space;
12055 
12056 	space = isl_basic_map_take_space(bmap);
12057 	space = isl_space_wrap(space);
12058 	bmap = isl_basic_map_restore_space(bmap, space);
12059 
12060 	bmap = isl_basic_map_finalize(bmap);
12061 
12062 	return bset_from_bmap(bmap);
12063 }
12064 
12065 /* Given a map A -> B, return the set (A -> B).
12066  */
isl_map_wrap(__isl_take isl_map * map)12067 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
12068 {
12069 	return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
12070 }
12071 
isl_basic_set_unwrap(__isl_take isl_basic_set * bset)12072 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
12073 {
12074 	bset = isl_basic_set_cow(bset);
12075 	if (!bset)
12076 		return NULL;
12077 
12078 	bset->dim = isl_space_unwrap(bset->dim);
12079 	if (!bset->dim)
12080 		goto error;
12081 
12082 	bset = isl_basic_set_finalize(bset);
12083 
12084 	return bset_to_bmap(bset);
12085 error:
12086 	isl_basic_set_free(bset);
12087 	return NULL;
12088 }
12089 
12090 /* Given a set (A -> B), return the map A -> B.
12091  * Error out if "set" is not of the form (A -> B).
12092  */
isl_set_unwrap(__isl_take isl_set * set)12093 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
12094 {
12095 	return isl_map_change_space(set, &isl_set_is_wrapping,
12096 				    "not a wrapping set", &isl_space_unwrap);
12097 }
12098 
isl_basic_map_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)12099 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
12100 	enum isl_dim_type type)
12101 {
12102 	isl_space *space;
12103 
12104 	space = isl_basic_map_take_space(bmap);
12105 	space = isl_space_reset(space, type);
12106 	bmap = isl_basic_map_restore_space(bmap, space);
12107 
12108 	bmap = isl_basic_map_mark_final(bmap);
12109 
12110 	return bmap;
12111 }
12112 
isl_map_reset(__isl_take isl_map * map,enum isl_dim_type type)12113 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
12114 	enum isl_dim_type type)
12115 {
12116 	int i;
12117 	isl_space *space;
12118 
12119 	if (!map)
12120 		return NULL;
12121 
12122 	if (!isl_space_is_named_or_nested(map->dim, type))
12123 		return map;
12124 
12125 	map = isl_map_cow(map);
12126 	if (!map)
12127 		return NULL;
12128 
12129 	for (i = 0; i < map->n; ++i) {
12130 		map->p[i] = isl_basic_map_reset(map->p[i], type);
12131 		if (!map->p[i])
12132 			goto error;
12133 	}
12134 
12135 	space = isl_map_take_space(map);
12136 	space = isl_space_reset(space, type);
12137 	map = isl_map_restore_space(map, space);
12138 
12139 	return map;
12140 error:
12141 	isl_map_free(map);
12142 	return NULL;
12143 }
12144 
isl_basic_map_flatten(__isl_take isl_basic_map * bmap)12145 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
12146 {
12147 	isl_space *space;
12148 
12149 	space = isl_basic_map_take_space(bmap);
12150 	space = isl_space_flatten(space);
12151 	bmap = isl_basic_map_restore_space(bmap, space);
12152 
12153 	bmap = isl_basic_map_mark_final(bmap);
12154 
12155 	return bmap;
12156 }
12157 
isl_basic_set_flatten(__isl_take isl_basic_set * bset)12158 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
12159 {
12160 	return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
12161 }
12162 
isl_basic_map_flatten_domain(__isl_take isl_basic_map * bmap)12163 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
12164 	__isl_take isl_basic_map *bmap)
12165 {
12166 	isl_space *space;
12167 
12168 	space = isl_basic_map_take_space(bmap);
12169 	space = isl_space_flatten_domain(space);
12170 	bmap = isl_basic_map_restore_space(bmap, space);
12171 
12172 	bmap = isl_basic_map_mark_final(bmap);
12173 
12174 	return bmap;
12175 }
12176 
isl_basic_map_flatten_range(__isl_take isl_basic_map * bmap)12177 __isl_give isl_basic_map *isl_basic_map_flatten_range(
12178 	__isl_take isl_basic_map *bmap)
12179 {
12180 	isl_space *space;
12181 
12182 	space = isl_basic_map_take_space(bmap);
12183 	space = isl_space_flatten_range(space);
12184 	bmap = isl_basic_map_restore_space(bmap, space);
12185 
12186 	bmap = isl_basic_map_mark_final(bmap);
12187 
12188 	return bmap;
12189 }
12190 
12191 /* Remove any internal structure from the spaces of domain and range of "map".
12192  */
isl_map_flatten(__isl_take isl_map * map)12193 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
12194 {
12195 	if (!map)
12196 		return NULL;
12197 
12198 	if (!map->dim->nested[0] && !map->dim->nested[1])
12199 		return map;
12200 
12201 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
12202 }
12203 
isl_set_flatten(__isl_take isl_set * set)12204 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
12205 {
12206 	return set_from_map(isl_map_flatten(set_to_map(set)));
12207 }
12208 
isl_set_flatten_map(__isl_take isl_set * set)12209 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
12210 {
12211 	isl_space *space, *flat_space;
12212 	isl_map *map;
12213 
12214 	space = isl_set_get_space(set);
12215 	flat_space = isl_space_flatten(isl_space_copy(space));
12216 	map = isl_map_identity(isl_space_join(isl_space_reverse(space),
12217 						flat_space));
12218 	map = isl_map_intersect_domain(map, set);
12219 
12220 	return map;
12221 }
12222 
12223 /* Remove any internal structure from the space of the domain of "map".
12224  */
isl_map_flatten_domain(__isl_take isl_map * map)12225 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
12226 {
12227 	if (!map)
12228 		return NULL;
12229 
12230 	if (!map->dim->nested[0])
12231 		return map;
12232 
12233 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
12234 }
12235 
12236 /* Remove any internal structure from the space of the range of "map".
12237  */
isl_map_flatten_range(__isl_take isl_map * map)12238 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
12239 {
12240 	if (!map)
12241 		return NULL;
12242 
12243 	if (!map->dim->nested[1])
12244 		return map;
12245 
12246 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
12247 }
12248 
12249 /* Reorder the dimensions of "bmap" according to the given dim_map
12250  * and set the dimension specification to "space" and
12251  * perform Gaussian elimination on the result.
12252  */
isl_basic_map_realign(__isl_take isl_basic_map * bmap,__isl_take isl_space * space,__isl_take struct isl_dim_map * dim_map)12253 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
12254 	__isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
12255 {
12256 	isl_basic_map *res;
12257 	unsigned flags;
12258 	isl_size n_div;
12259 
12260 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
12261 	if (n_div < 0 || !space || !dim_map)
12262 		goto error;
12263 
12264 	flags = bmap->flags;
12265 	ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
12266 	ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
12267 	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
12268 	res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
12269 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
12270 	if (res)
12271 		res->flags = flags;
12272 	res = isl_basic_map_gauss(res, NULL);
12273 	res = isl_basic_map_finalize(res);
12274 	return res;
12275 error:
12276 	isl_dim_map_free(dim_map);
12277 	isl_basic_map_free(bmap);
12278 	isl_space_free(space);
12279 	return NULL;
12280 }
12281 
12282 /* Reorder the dimensions of "map" according to given reordering.
12283  */
isl_map_realign(__isl_take isl_map * map,__isl_take isl_reordering * r)12284 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
12285 	__isl_take isl_reordering *r)
12286 {
12287 	int i;
12288 	struct isl_dim_map *dim_map;
12289 
12290 	map = isl_map_cow(map);
12291 	dim_map = isl_dim_map_from_reordering(r);
12292 	if (!map || !r || !dim_map)
12293 		goto error;
12294 
12295 	for (i = 0; i < map->n; ++i) {
12296 		struct isl_dim_map *dim_map_i;
12297 		isl_space *space;
12298 
12299 		dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
12300 
12301 		space = isl_reordering_get_space(r);
12302 		map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
12303 
12304 		if (!map->p[i])
12305 			goto error;
12306 	}
12307 
12308 	map = isl_map_reset_space(map, isl_reordering_get_space(r));
12309 	map = isl_map_unmark_normalized(map);
12310 
12311 	isl_reordering_free(r);
12312 	isl_dim_map_free(dim_map);
12313 	return map;
12314 error:
12315 	isl_dim_map_free(dim_map);
12316 	isl_map_free(map);
12317 	isl_reordering_free(r);
12318 	return NULL;
12319 }
12320 
isl_set_realign(__isl_take isl_set * set,__isl_take isl_reordering * r)12321 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
12322 	__isl_take isl_reordering *r)
12323 {
12324 	return set_from_map(isl_map_realign(set_to_map(set), r));
12325 }
12326 
isl_map_align_params(__isl_take isl_map * map,__isl_take isl_space * model)12327 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
12328 	__isl_take isl_space *model)
12329 {
12330 	isl_ctx *ctx;
12331 	isl_bool aligned;
12332 
12333 	if (!map || !model)
12334 		goto error;
12335 
12336 	ctx = isl_space_get_ctx(model);
12337 	if (!isl_space_has_named_params(model))
12338 		isl_die(ctx, isl_error_invalid,
12339 			"model has unnamed parameters", goto error);
12340 	if (isl_map_check_named_params(map) < 0)
12341 		goto error;
12342 	aligned = isl_map_space_has_equal_params(map, model);
12343 	if (aligned < 0)
12344 		goto error;
12345 	if (!aligned) {
12346 		isl_reordering *exp;
12347 
12348 		exp = isl_parameter_alignment_reordering(map->dim, model);
12349 		exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
12350 		map = isl_map_realign(map, exp);
12351 	}
12352 
12353 	isl_space_free(model);
12354 	return map;
12355 error:
12356 	isl_space_free(model);
12357 	isl_map_free(map);
12358 	return NULL;
12359 }
12360 
isl_set_align_params(__isl_take isl_set * set,__isl_take isl_space * model)12361 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
12362 	__isl_take isl_space *model)
12363 {
12364 	return isl_map_align_params(set, model);
12365 }
12366 
12367 /* Align the parameters of "bmap" to those of "model", introducing
12368  * additional parameters if needed.
12369  */
isl_basic_map_align_params(__isl_take isl_basic_map * bmap,__isl_take isl_space * model)12370 __isl_give isl_basic_map *isl_basic_map_align_params(
12371 	__isl_take isl_basic_map *bmap, __isl_take isl_space *model)
12372 {
12373 	isl_ctx *ctx;
12374 	isl_bool equal_params;
12375 
12376 	if (!bmap || !model)
12377 		goto error;
12378 
12379 	ctx = isl_space_get_ctx(model);
12380 	if (!isl_space_has_named_params(model))
12381 		isl_die(ctx, isl_error_invalid,
12382 			"model has unnamed parameters", goto error);
12383 	if (isl_basic_map_check_named_params(bmap) < 0)
12384 		goto error;
12385 	equal_params = isl_space_has_equal_params(bmap->dim, model);
12386 	if (equal_params < 0)
12387 		goto error;
12388 	if (!equal_params) {
12389 		isl_reordering *exp;
12390 		struct isl_dim_map *dim_map;
12391 
12392 		exp = isl_parameter_alignment_reordering(bmap->dim, model);
12393 		exp = isl_reordering_extend_space(exp,
12394 					isl_basic_map_get_space(bmap));
12395 		dim_map = isl_dim_map_from_reordering(exp);
12396 		bmap = isl_basic_map_realign(bmap,
12397 				    isl_reordering_get_space(exp),
12398 				    isl_dim_map_extend(dim_map, bmap));
12399 		isl_reordering_free(exp);
12400 		isl_dim_map_free(dim_map);
12401 	}
12402 
12403 	isl_space_free(model);
12404 	return bmap;
12405 error:
12406 	isl_space_free(model);
12407 	isl_basic_map_free(bmap);
12408 	return NULL;
12409 }
12410 
12411 /* Do "bset" and "space" have the same parameters?
12412  */
isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set * bset,__isl_keep isl_space * space)12413 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
12414 	__isl_keep isl_space *space)
12415 {
12416 	isl_space *bset_space;
12417 
12418 	bset_space = isl_basic_set_peek_space(bset);
12419 	return isl_space_has_equal_params(bset_space, space);
12420 }
12421 
12422 /* Do "map" and "space" have the same parameters?
12423  */
isl_map_space_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_space * space)12424 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
12425 	__isl_keep isl_space *space)
12426 {
12427 	isl_space *map_space;
12428 
12429 	map_space = isl_map_peek_space(map);
12430 	return isl_space_has_equal_params(map_space, space);
12431 }
12432 
12433 /* Do "set" and "space" have the same parameters?
12434  */
isl_set_space_has_equal_params(__isl_keep isl_set * set,__isl_keep isl_space * space)12435 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
12436 	__isl_keep isl_space *space)
12437 {
12438 	return isl_map_space_has_equal_params(set_to_map(set), space);
12439 }
12440 
12441 /* Align the parameters of "bset" to those of "model", introducing
12442  * additional parameters if needed.
12443  */
isl_basic_set_align_params(__isl_take isl_basic_set * bset,__isl_take isl_space * model)12444 __isl_give isl_basic_set *isl_basic_set_align_params(
12445 	__isl_take isl_basic_set *bset, __isl_take isl_space *model)
12446 {
12447 	return isl_basic_map_align_params(bset, model);
12448 }
12449 
12450 /* Drop all parameters not referenced by "map".
12451  */
isl_map_drop_unused_params(__isl_take isl_map * map)12452 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
12453 {
12454 	int i;
12455 	isl_size n;
12456 
12457 	n = isl_map_dim(map, isl_dim_param);
12458 	if (isl_map_check_named_params(map) < 0 || n < 0)
12459 		return isl_map_free(map);
12460 
12461 	for (i = n - 1; i >= 0; i--) {
12462 		isl_bool involves;
12463 
12464 		involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
12465 		if (involves < 0)
12466 			return isl_map_free(map);
12467 		if (!involves)
12468 			map = isl_map_project_out(map, isl_dim_param, i, 1);
12469 	}
12470 
12471 	return map;
12472 }
12473 
12474 /* Drop all parameters not referenced by "set".
12475  */
isl_set_drop_unused_params(__isl_take isl_set * set)12476 __isl_give isl_set *isl_set_drop_unused_params(
12477 	__isl_take isl_set *set)
12478 {
12479 	return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
12480 }
12481 
12482 /* Drop all parameters not referenced by "bmap".
12483  */
isl_basic_map_drop_unused_params(__isl_take isl_basic_map * bmap)12484 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
12485 	__isl_take isl_basic_map *bmap)
12486 {
12487 	isl_size nparam;
12488 	int i;
12489 
12490 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
12491 	if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)
12492 		return isl_basic_map_free(bmap);
12493 
12494 	for (i = nparam - 1; i >= 0; i--) {
12495 		isl_bool involves;
12496 
12497 		involves = isl_basic_map_involves_dims(bmap,
12498 							isl_dim_param, i, 1);
12499 		if (involves < 0)
12500 			return isl_basic_map_free(bmap);
12501 		if (!involves)
12502 			bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
12503 	}
12504 
12505 	return bmap;
12506 }
12507 
12508 /* Drop all parameters not referenced by "bset".
12509  */
isl_basic_set_drop_unused_params(__isl_take isl_basic_set * bset)12510 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
12511 	__isl_take isl_basic_set *bset)
12512 {
12513 	return bset_from_bmap(isl_basic_map_drop_unused_params(
12514 							bset_to_bmap(bset)));
12515 }
12516 
12517 /* Given a tuple of identifiers "tuple" in a space that corresponds
12518  * to that of "set", if any of those identifiers appear as parameters
12519  * in "set", then equate those parameters with the corresponding
12520  * set dimensions and project out the parameters.
12521  * The result therefore has no such parameters.
12522  */
equate_params(__isl_take isl_set * set,__isl_keep isl_multi_id * tuple)12523 static __isl_give isl_set *equate_params(__isl_take isl_set *set,
12524 	__isl_keep isl_multi_id *tuple)
12525 {
12526 	int i;
12527 	isl_size n;
12528 	isl_space *set_space, *tuple_space;
12529 
12530 	set_space = isl_set_peek_space(set);
12531 	tuple_space = isl_multi_id_peek_space(tuple);
12532 	if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
12533 		return isl_set_free(set);
12534 	n = isl_multi_id_size(tuple);
12535 	if (n < 0)
12536 		return isl_set_free(set);
12537 	for (i = 0; i < n; ++i) {
12538 		isl_id *id;
12539 		int pos;
12540 
12541 		id = isl_multi_id_get_at(tuple, i);
12542 		if (!id)
12543 			return isl_set_free(set);
12544 		pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
12545 		isl_id_free(id);
12546 		if (pos < 0)
12547 			continue;
12548 		set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
12549 		set = isl_set_project_out(set, isl_dim_param, pos, 1);
12550 	}
12551 	return set;
12552 }
12553 
12554 /* Bind the set dimensions of "set" to parameters with identifiers
12555  * specified by "tuple", living in the same space as "set".
12556  *
12557  * If no parameters with these identifiers appear in "set" already,
12558  * then the set dimensions are simply reinterpreted as parameters.
12559  * Otherwise, the parameters are first equated to the corresponding
12560  * set dimensions.
12561  */
isl_set_bind(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12562 __isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
12563 	__isl_take isl_multi_id *tuple)
12564 {
12565 	isl_space *space;
12566 
12567 	set = equate_params(set, tuple);
12568 	space = isl_set_get_space(set);
12569 	space = isl_space_bind_set(space, tuple);
12570 	isl_multi_id_free(tuple);
12571 	set = isl_set_reset_space(set, space);
12572 
12573 	return set;
12574 }
12575 
12576 /* Given a tuple of identifiers "tuple" in a space that corresponds
12577  * to the domain of "map", if any of those identifiers appear as parameters
12578  * in "map", then equate those parameters with the corresponding
12579  * input dimensions and project out the parameters.
12580  * The result therefore has no such parameters.
12581  */
map_equate_params(__isl_take isl_map * map,__isl_keep isl_multi_id * tuple)12582 static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
12583 	__isl_keep isl_multi_id *tuple)
12584 {
12585 	int i;
12586 	isl_size n;
12587 	isl_space *map_space, *tuple_space;
12588 
12589 	map_space = isl_map_peek_space(map);
12590 	tuple_space = isl_multi_id_peek_space(tuple);
12591 	if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
12592 		return isl_map_free(map);
12593 	n = isl_multi_id_size(tuple);
12594 	if (n < 0)
12595 		return isl_map_free(map);
12596 	for (i = 0; i < n; ++i) {
12597 		isl_id *id;
12598 		int pos;
12599 
12600 		id = isl_multi_id_get_at(tuple, i);
12601 		if (!id)
12602 			return isl_map_free(map);
12603 		pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
12604 		isl_id_free(id);
12605 		if (pos < 0)
12606 			continue;
12607 		map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
12608 		map = isl_map_project_out(map, isl_dim_param, pos, 1);
12609 	}
12610 	return map;
12611 }
12612 
12613 /* Bind the input dimensions of "map" to parameters with identifiers
12614  * specified by "tuple", living in the domain space of "map".
12615  *
12616  * If no parameters with these identifiers appear in "map" already,
12617  * then the input dimensions are simply reinterpreted as parameters.
12618  * Otherwise, the parameters are first equated to the corresponding
12619  * input dimensions.
12620  */
isl_map_bind_domain(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12621 __isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
12622 	__isl_take isl_multi_id *tuple)
12623 {
12624 	isl_space *space;
12625 	isl_set *set;
12626 
12627 	map = map_equate_params(map, tuple);
12628 	space = isl_map_get_space(map);
12629 	space = isl_space_bind_map_domain(space, tuple);
12630 	isl_multi_id_free(tuple);
12631 	set = set_from_map(isl_map_reset_space(map, space));
12632 
12633 	return set;
12634 }
12635 
12636 /* Bind the output dimensions of "map" to parameters with identifiers
12637  * specified by "tuple", living in the range space of "map".
12638  *
12639  * Since binding is more easily implemented on the domain,
12640  * bind the input dimensions of the inverse of "map".
12641  */
isl_map_bind_range(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12642 __isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
12643 	__isl_take isl_multi_id *tuple)
12644 {
12645 	return isl_map_bind_domain(isl_map_reverse(map), tuple);
12646 }
12647 
12648 /* Insert a domain corresponding to "tuple"
12649  * into the nullary or unary relation "set".
12650  * The result has an extra initial tuple and is therefore
12651  * either a unary or binary relation.
12652  * Any parameters with identifiers in "tuple" are reinterpreted
12653  * as the corresponding domain dimensions.
12654  */
unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12655 static __isl_give isl_map *unbind_params_insert_domain(
12656 	__isl_take isl_set *set, __isl_take isl_multi_id *tuple)
12657 {
12658 	isl_space *space;
12659 	isl_reordering *r;
12660 
12661 	space = isl_set_peek_space(set);
12662 	r = isl_reordering_unbind_params_insert_domain(space, tuple);
12663 	isl_multi_id_free(tuple);
12664 
12665 	return isl_map_realign(set_to_map(set), r);
12666 }
12667 
12668 /* Construct a set with "tuple" as domain from the parameter domain "set".
12669  * Any parameters with identifiers in "tuple" are reinterpreted
12670  * as the corresponding set dimensions.
12671  */
isl_set_unbind_params(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12672 __isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
12673 	__isl_take isl_multi_id *tuple)
12674 {
12675 	isl_bool is_params;
12676 
12677 	is_params = isl_set_is_params(set);
12678 	if (is_params < 0)
12679 		set = isl_set_free(set);
12680 	else if (!is_params)
12681 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
12682 			"expecting parameter domain", set = isl_set_free(set));
12683 	return set_from_map(unbind_params_insert_domain(set, tuple));
12684 }
12685 
12686 /* Check that "set" is a proper set, i.e., that it is not a parameter domain.
12687  */
isl_set_check_is_set(__isl_keep isl_set * set)12688 static isl_stat isl_set_check_is_set(__isl_keep isl_set *set)
12689 {
12690 	isl_bool is_params;
12691 
12692 	is_params = isl_set_is_params(set);
12693 	if (is_params < 0)
12694 		return isl_stat_error;
12695 	else if (is_params)
12696 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
12697 			"expecting proper set", return isl_stat_error);
12698 
12699 	return isl_stat_ok;
12700 }
12701 
12702 /* Construct a map with "domain" as domain and "set" as range.
12703  * Any parameters with identifiers in "domain" are reinterpreted
12704  * as the corresponding domain dimensions.
12705  */
isl_set_unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * domain)12706 __isl_give isl_map *isl_set_unbind_params_insert_domain(
12707 	__isl_take isl_set *set, __isl_take isl_multi_id *domain)
12708 {
12709 	if (isl_set_check_is_set(set) < 0)
12710 		set = isl_set_free(set);
12711 	return unbind_params_insert_domain(set, domain);
12712 }
12713 
12714 /* Construct a map with "domain" as domain and "set" as range.
12715  */
isl_set_insert_domain(__isl_take isl_set * set,__isl_take isl_space * domain)12716 __isl_give isl_map *isl_set_insert_domain(__isl_take isl_set *set,
12717 	__isl_take isl_space *domain)
12718 {
12719 	isl_size dim;
12720 	isl_space *space;
12721 	isl_map *map;
12722 
12723 	if (isl_set_check_is_set(set) < 0 || isl_space_check_is_set(domain) < 0)
12724 		domain = isl_space_free(domain);
12725 	dim = isl_space_dim(domain, isl_dim_set);
12726 	if (dim < 0)
12727 		domain = isl_space_free(domain);
12728 	space = isl_set_get_space(set);
12729 	domain = isl_space_replace_params(domain, space);
12730 	space = isl_space_map_from_domain_and_range(domain, space);
12731 
12732 	map = isl_map_from_range(set);
12733 	map = isl_map_add_dims(map, isl_dim_in, dim);
12734 	map = isl_map_reset_space(map, space);
12735 
12736 	return map;
12737 }
12738 
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)12739 __isl_give isl_mat *isl_basic_map_equalities_matrix(
12740 		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12741 		enum isl_dim_type c2, enum isl_dim_type c3,
12742 		enum isl_dim_type c4, enum isl_dim_type c5)
12743 {
12744 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12745 	struct isl_mat *mat;
12746 	int i, j, k;
12747 	int pos;
12748 	isl_size total;
12749 
12750 	total = isl_basic_map_dim(bmap, isl_dim_all);
12751 	if (total < 0)
12752 		return NULL;
12753 	mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
12754 	if (!mat)
12755 		return NULL;
12756 	for (i = 0; i < bmap->n_eq; ++i)
12757 		for (j = 0, pos = 0; j < 5; ++j) {
12758 			int off = isl_basic_map_offset(bmap, c[j]);
12759 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12760 			if (dim < 0)
12761 				return isl_mat_free(mat);
12762 			for (k = 0; k < dim; ++k) {
12763 				isl_int_set(mat->row[i][pos],
12764 					    bmap->eq[i][off + k]);
12765 				++pos;
12766 			}
12767 		}
12768 
12769 	return mat;
12770 }
12771 
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)12772 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
12773 		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12774 		enum isl_dim_type c2, enum isl_dim_type c3,
12775 		enum isl_dim_type c4, enum isl_dim_type c5)
12776 {
12777 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12778 	struct isl_mat *mat;
12779 	int i, j, k;
12780 	int pos;
12781 	isl_size total;
12782 
12783 	total = isl_basic_map_dim(bmap, isl_dim_all);
12784 	if (total < 0)
12785 		return NULL;
12786 	mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
12787 	if (!mat)
12788 		return NULL;
12789 	for (i = 0; i < bmap->n_ineq; ++i)
12790 		for (j = 0, pos = 0; j < 5; ++j) {
12791 			int off = isl_basic_map_offset(bmap, c[j]);
12792 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12793 			if (dim < 0)
12794 				return isl_mat_free(mat);
12795 			for (k = 0; k < dim; ++k) {
12796 				isl_int_set(mat->row[i][pos],
12797 					    bmap->ineq[i][off + k]);
12798 				++pos;
12799 			}
12800 		}
12801 
12802 	return mat;
12803 }
12804 
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)12805 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
12806 	__isl_take isl_space *space,
12807 	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12808 	enum isl_dim_type c2, enum isl_dim_type c3,
12809 	enum isl_dim_type c4, enum isl_dim_type c5)
12810 {
12811 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12812 	isl_basic_map *bmap = NULL;
12813 	isl_size dim;
12814 	unsigned total;
12815 	unsigned extra;
12816 	int i, j, k, l;
12817 	int pos;
12818 
12819 	dim = isl_space_dim(space, isl_dim_all);
12820 	if (dim < 0 || !eq || !ineq)
12821 		goto error;
12822 
12823 	if (eq->n_col != ineq->n_col)
12824 		isl_die(space->ctx, isl_error_invalid,
12825 			"equalities and inequalities matrices should have "
12826 			"same number of columns", goto error);
12827 
12828 	total = 1 + dim;
12829 
12830 	if (eq->n_col < total)
12831 		isl_die(space->ctx, isl_error_invalid,
12832 			"number of columns too small", goto error);
12833 
12834 	extra = eq->n_col - total;
12835 
12836 	bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
12837 				       eq->n_row, ineq->n_row);
12838 	if (!bmap)
12839 		goto error;
12840 	for (i = 0; i < extra; ++i) {
12841 		k = isl_basic_map_alloc_div(bmap);
12842 		if (k < 0)
12843 			goto error;
12844 		isl_int_set_si(bmap->div[k][0], 0);
12845 	}
12846 	for (i = 0; i < eq->n_row; ++i) {
12847 		l = isl_basic_map_alloc_equality(bmap);
12848 		if (l < 0)
12849 			goto error;
12850 		for (j = 0, pos = 0; j < 5; ++j) {
12851 			int off = isl_basic_map_offset(bmap, c[j]);
12852 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12853 			if (dim < 0)
12854 				goto error;
12855 			for (k = 0; k < dim; ++k) {
12856 				isl_int_set(bmap->eq[l][off + k],
12857 					    eq->row[i][pos]);
12858 				++pos;
12859 			}
12860 		}
12861 	}
12862 	for (i = 0; i < ineq->n_row; ++i) {
12863 		l = isl_basic_map_alloc_inequality(bmap);
12864 		if (l < 0)
12865 			goto error;
12866 		for (j = 0, pos = 0; j < 5; ++j) {
12867 			int off = isl_basic_map_offset(bmap, c[j]);
12868 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12869 			if (dim < 0)
12870 				goto error;
12871 			for (k = 0; k < dim; ++k) {
12872 				isl_int_set(bmap->ineq[l][off + k],
12873 					    ineq->row[i][pos]);
12874 				++pos;
12875 			}
12876 		}
12877 	}
12878 
12879 	isl_space_free(space);
12880 	isl_mat_free(eq);
12881 	isl_mat_free(ineq);
12882 
12883 	bmap = isl_basic_map_simplify(bmap);
12884 	return isl_basic_map_finalize(bmap);
12885 error:
12886 	isl_space_free(space);
12887 	isl_mat_free(eq);
12888 	isl_mat_free(ineq);
12889 	isl_basic_map_free(bmap);
12890 	return NULL;
12891 }
12892 
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)12893 __isl_give isl_mat *isl_basic_set_equalities_matrix(
12894 	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12895 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12896 {
12897 	return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12898 						c1, c2, c3, c4, isl_dim_in);
12899 }
12900 
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)12901 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12902 	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12903 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12904 {
12905 	return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12906 						 c1, c2, c3, c4, isl_dim_in);
12907 }
12908 
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)12909 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12910 	__isl_take isl_space *space,
12911 	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12912 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12913 {
12914 	isl_basic_map *bmap;
12915 	bmap = isl_basic_map_from_constraint_matrices(space, eq, ineq,
12916 						   c1, c2, c3, c4, isl_dim_in);
12917 	return bset_from_bmap(bmap);
12918 }
12919 
isl_basic_map_can_zip(__isl_keep isl_basic_map * bmap)12920 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12921 {
12922 	if (!bmap)
12923 		return isl_bool_error;
12924 
12925 	return isl_space_can_zip(bmap->dim);
12926 }
12927 
isl_map_can_zip(__isl_keep isl_map * map)12928 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12929 {
12930 	if (!map)
12931 		return isl_bool_error;
12932 
12933 	return isl_space_can_zip(map->dim);
12934 }
12935 
12936 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12937  * (A -> C) -> (B -> D).
12938  */
isl_basic_map_zip(__isl_take isl_basic_map * bmap)12939 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12940 {
12941 	unsigned pos;
12942 	isl_size n_in;
12943 	isl_size n1;
12944 	isl_size n2;
12945 
12946 	if (!bmap)
12947 		return NULL;
12948 
12949 	if (!isl_basic_map_can_zip(bmap))
12950 		isl_die(bmap->ctx, isl_error_invalid,
12951 			"basic map cannot be zipped", goto error);
12952 	n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12953 	n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12954 	n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12955 	if (n_in < 0 || n1 < 0 || n2 < 0)
12956 		return isl_basic_map_free(bmap);
12957 	pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
12958 	bmap = isl_basic_map_cow(bmap);
12959 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12960 	if (!bmap)
12961 		return NULL;
12962 	bmap->dim = isl_space_zip(bmap->dim);
12963 	if (!bmap->dim)
12964 		goto error;
12965 	bmap = isl_basic_map_mark_final(bmap);
12966 	return bmap;
12967 error:
12968 	isl_basic_map_free(bmap);
12969 	return NULL;
12970 }
12971 
12972 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12973  * (A -> C) -> (B -> D).
12974  */
isl_map_zip(__isl_take isl_map * map)12975 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12976 {
12977 	if (!map)
12978 		return NULL;
12979 
12980 	if (!isl_map_can_zip(map))
12981 		isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12982 			goto error);
12983 
12984 	return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);
12985 error:
12986 	isl_map_free(map);
12987 	return NULL;
12988 }
12989 
12990 /* Can we apply isl_basic_map_curry to "bmap"?
12991  * That is, does it have a nested relation in its domain?
12992  */
isl_basic_map_can_curry(__isl_keep isl_basic_map * bmap)12993 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12994 {
12995 	if (!bmap)
12996 		return isl_bool_error;
12997 
12998 	return isl_space_can_curry(bmap->dim);
12999 }
13000 
13001 /* Can we apply isl_map_curry to "map"?
13002  * That is, does it have a nested relation in its domain?
13003  */
isl_map_can_curry(__isl_keep isl_map * map)13004 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
13005 {
13006 	if (!map)
13007 		return isl_bool_error;
13008 
13009 	return isl_space_can_curry(map->dim);
13010 }
13011 
13012 /* Given a basic map (A -> B) -> C, return the corresponding basic map
13013  * A -> (B -> C).
13014  */
isl_basic_map_curry(__isl_take isl_basic_map * bmap)13015 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
13016 {
13017 
13018 	if (!bmap)
13019 		return NULL;
13020 
13021 	if (!isl_basic_map_can_curry(bmap))
13022 		isl_die(bmap->ctx, isl_error_invalid,
13023 			"basic map cannot be curried", goto error);
13024 	bmap = isl_basic_map_cow(bmap);
13025 	if (!bmap)
13026 		return NULL;
13027 	bmap->dim = isl_space_curry(bmap->dim);
13028 	if (!bmap->dim)
13029 		goto error;
13030 	bmap = isl_basic_map_mark_final(bmap);
13031 	return bmap;
13032 error:
13033 	isl_basic_map_free(bmap);
13034 	return NULL;
13035 }
13036 
13037 /* Given a map (A -> B) -> C, return the corresponding map
13038  * A -> (B -> C).
13039  */
isl_map_curry(__isl_take isl_map * map)13040 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
13041 {
13042 	return isl_map_change_space(map, &isl_map_can_curry,
13043 				    "map cannot be curried", &isl_space_curry);
13044 }
13045 
13046 /* Can isl_map_range_curry be applied to "map"?
13047  * That is, does it have a nested relation in its range,
13048  * the domain of which is itself a nested relation?
13049  */
isl_map_can_range_curry(__isl_keep isl_map * map)13050 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
13051 {
13052 	if (!map)
13053 		return isl_bool_error;
13054 
13055 	return isl_space_can_range_curry(map->dim);
13056 }
13057 
13058 /* Given a map A -> ((B -> C) -> D), return the corresponding map
13059  * A -> (B -> (C -> D)).
13060  */
isl_map_range_curry(__isl_take isl_map * map)13061 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
13062 {
13063 	return isl_map_change_space(map, &isl_map_can_range_curry,
13064 				    "map range cannot be curried",
13065 				    &isl_space_range_curry);
13066 }
13067 
13068 /* Can we apply isl_basic_map_uncurry to "bmap"?
13069  * That is, does it have a nested relation in its domain?
13070  */
isl_basic_map_can_uncurry(__isl_keep isl_basic_map * bmap)13071 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
13072 {
13073 	if (!bmap)
13074 		return isl_bool_error;
13075 
13076 	return isl_space_can_uncurry(bmap->dim);
13077 }
13078 
13079 /* Can we apply isl_map_uncurry to "map"?
13080  * That is, does it have a nested relation in its domain?
13081  */
isl_map_can_uncurry(__isl_keep isl_map * map)13082 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
13083 {
13084 	if (!map)
13085 		return isl_bool_error;
13086 
13087 	return isl_space_can_uncurry(map->dim);
13088 }
13089 
13090 /* Given a basic map A -> (B -> C), return the corresponding basic map
13091  * (A -> B) -> C.
13092  */
isl_basic_map_uncurry(__isl_take isl_basic_map * bmap)13093 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
13094 {
13095 
13096 	if (!bmap)
13097 		return NULL;
13098 
13099 	if (!isl_basic_map_can_uncurry(bmap))
13100 		isl_die(bmap->ctx, isl_error_invalid,
13101 			"basic map cannot be uncurried",
13102 			return isl_basic_map_free(bmap));
13103 	bmap = isl_basic_map_cow(bmap);
13104 	if (!bmap)
13105 		return NULL;
13106 	bmap->dim = isl_space_uncurry(bmap->dim);
13107 	if (!bmap->dim)
13108 		return isl_basic_map_free(bmap);
13109 	bmap = isl_basic_map_mark_final(bmap);
13110 	return bmap;
13111 }
13112 
13113 /* Given a map A -> (B -> C), return the corresponding map
13114  * (A -> B) -> C.
13115  */
isl_map_uncurry(__isl_take isl_map * map)13116 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
13117 {
13118 	return isl_map_change_space(map, &isl_map_can_uncurry,
13119 				"map cannot be uncurried", &isl_space_uncurry);
13120 }
13121 
isl_set_equate(__isl_take isl_set * set,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13122 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
13123 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13124 {
13125 	return isl_map_equate(set, type1, pos1, type2, pos2);
13126 }
13127 
13128 /* Construct a basic map where the given dimensions are equal to each other.
13129  */
equator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13130 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
13131 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13132 {
13133 	isl_basic_map *bmap = NULL;
13134 	int i;
13135 	isl_size total;
13136 
13137 	total = isl_space_dim(space, isl_dim_all);
13138 	if (total < 0 ||
13139 	    isl_space_check_range(space, type1, pos1, 1) < 0 ||
13140 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13141 		goto error;
13142 
13143 	if (type1 == type2 && pos1 == pos2)
13144 		return isl_basic_map_universe(space);
13145 
13146 	bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
13147 	i = isl_basic_map_alloc_equality(bmap);
13148 	if (i < 0)
13149 		goto error;
13150 	isl_seq_clr(bmap->eq[i], 1 + total);
13151 	pos1 += isl_basic_map_offset(bmap, type1);
13152 	pos2 += isl_basic_map_offset(bmap, type2);
13153 	isl_int_set_si(bmap->eq[i][pos1], -1);
13154 	isl_int_set_si(bmap->eq[i][pos2], 1);
13155 	bmap = isl_basic_map_finalize(bmap);
13156 	isl_space_free(space);
13157 	return bmap;
13158 error:
13159 	isl_space_free(space);
13160 	isl_basic_map_free(bmap);
13161 	return NULL;
13162 }
13163 
13164 /* Add a constraint imposing that the given two dimensions are equal.
13165  */
isl_basic_map_equate(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13166 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
13167 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13168 {
13169 	isl_basic_map *eq;
13170 
13171 	eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13172 
13173 	bmap = isl_basic_map_intersect(bmap, eq);
13174 
13175 	return bmap;
13176 }
13177 
13178 /* Add a constraint imposing that the given two dimensions are equal.
13179  */
isl_map_equate(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13180 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
13181 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13182 {
13183 	isl_basic_map *bmap;
13184 
13185 	bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
13186 
13187 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13188 
13189 	return map;
13190 }
13191 
13192 /* Add a constraint imposing that the given two dimensions have opposite values.
13193  */
isl_map_oppose(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13194 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
13195 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13196 {
13197 	isl_basic_map *bmap = NULL;
13198 	int i;
13199 	isl_size total;
13200 
13201 	if (isl_map_check_range(map, type1, pos1, 1) < 0)
13202 		return isl_map_free(map);
13203 	if (isl_map_check_range(map, type2, pos2, 1) < 0)
13204 		return isl_map_free(map);
13205 
13206 	total = isl_map_dim(map, isl_dim_all);
13207 	if (total < 0)
13208 		return isl_map_free(map);
13209 	bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
13210 	i = isl_basic_map_alloc_equality(bmap);
13211 	if (i < 0)
13212 		goto error;
13213 	isl_seq_clr(bmap->eq[i], 1 + total);
13214 	pos1 += isl_basic_map_offset(bmap, type1);
13215 	pos2 += isl_basic_map_offset(bmap, type2);
13216 	isl_int_set_si(bmap->eq[i][pos1], 1);
13217 	isl_int_set_si(bmap->eq[i][pos2], 1);
13218 	bmap = isl_basic_map_finalize(bmap);
13219 
13220 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13221 
13222 	return map;
13223 error:
13224 	isl_basic_map_free(bmap);
13225 	isl_map_free(map);
13226 	return NULL;
13227 }
13228 
13229 /* Construct a constraint imposing that the value of the first dimension is
13230  * greater than or equal to that of the second.
13231  */
constraint_order_ge(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13232 static __isl_give isl_constraint *constraint_order_ge(
13233 	__isl_take isl_space *space, enum isl_dim_type type1, int pos1,
13234 	enum isl_dim_type type2, int pos2)
13235 {
13236 	isl_constraint *c;
13237 
13238 	if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13239 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13240 		space = isl_space_free(space);
13241 	if (!space)
13242 		return NULL;
13243 
13244 	c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
13245 
13246 	if (type1 == type2 && pos1 == pos2)
13247 		return c;
13248 
13249 	c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
13250 	c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
13251 
13252 	return c;
13253 }
13254 
13255 /* Add a constraint imposing that the value of the first dimension is
13256  * greater than or equal to that of the second.
13257  */
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)13258 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
13259 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13260 {
13261 	isl_constraint *c;
13262 	isl_space *space;
13263 
13264 	if (type1 == type2 && pos1 == pos2)
13265 		return bmap;
13266 	space = isl_basic_map_get_space(bmap);
13267 	c = constraint_order_ge(space, type1, pos1, type2, pos2);
13268 	bmap = isl_basic_map_add_constraint(bmap, c);
13269 
13270 	return bmap;
13271 }
13272 
13273 /* Add a constraint imposing that the value of the first dimension is
13274  * greater than or equal to that of the second.
13275  */
isl_map_order_ge(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13276 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
13277 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13278 {
13279 	isl_constraint *c;
13280 	isl_space *space;
13281 
13282 	if (type1 == type2 && pos1 == pos2)
13283 		return map;
13284 	space = isl_map_get_space(map);
13285 	c = constraint_order_ge(space, type1, pos1, type2, pos2);
13286 	map = isl_map_add_constraint(map, c);
13287 
13288 	return map;
13289 }
13290 
13291 /* Add a constraint imposing that the value of the first dimension is
13292  * less than or equal to that of the second.
13293  */
isl_map_order_le(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13294 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
13295 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13296 {
13297 	return isl_map_order_ge(map, type2, pos2, type1, pos1);
13298 }
13299 
13300 /* Construct a basic map where the value of the first dimension is
13301  * greater than that of the second.
13302  */
greator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13303 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
13304 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13305 {
13306 	isl_basic_map *bmap = NULL;
13307 	int i;
13308 	isl_size total;
13309 
13310 	if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13311 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13312 		goto error;
13313 
13314 	if (type1 == type2 && pos1 == pos2)
13315 		return isl_basic_map_empty(space);
13316 
13317 	bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
13318 	total = isl_basic_map_dim(bmap, isl_dim_all);
13319 	i = isl_basic_map_alloc_inequality(bmap);
13320 	if (total < 0 || i < 0)
13321 		return isl_basic_map_free(bmap);
13322 	isl_seq_clr(bmap->ineq[i], 1 + total);
13323 	pos1 += isl_basic_map_offset(bmap, type1);
13324 	pos2 += isl_basic_map_offset(bmap, type2);
13325 	isl_int_set_si(bmap->ineq[i][pos1], 1);
13326 	isl_int_set_si(bmap->ineq[i][pos2], -1);
13327 	isl_int_set_si(bmap->ineq[i][0], -1);
13328 	bmap = isl_basic_map_finalize(bmap);
13329 
13330 	return bmap;
13331 error:
13332 	isl_space_free(space);
13333 	isl_basic_map_free(bmap);
13334 	return NULL;
13335 }
13336 
13337 /* Add a constraint imposing that the value of the first dimension is
13338  * greater than that of the second.
13339  */
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)13340 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
13341 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13342 {
13343 	isl_basic_map *gt;
13344 
13345 	gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13346 
13347 	bmap = isl_basic_map_intersect(bmap, gt);
13348 
13349 	return bmap;
13350 }
13351 
13352 /* Add a constraint imposing that the value of the first dimension is
13353  * greater than that of the second.
13354  */
isl_map_order_gt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13355 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
13356 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13357 {
13358 	isl_basic_map *bmap;
13359 
13360 	bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
13361 
13362 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13363 
13364 	return map;
13365 }
13366 
13367 /* Add a constraint imposing that the value of the first dimension is
13368  * smaller than that of the second.
13369  */
isl_map_order_lt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13370 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
13371 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13372 {
13373 	return isl_map_order_gt(map, type2, pos2, type1, pos1);
13374 }
13375 
isl_basic_map_get_div(__isl_keep isl_basic_map * bmap,int pos)13376 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
13377 	int pos)
13378 {
13379 	isl_aff *div;
13380 	isl_local_space *ls;
13381 
13382 	if (!bmap)
13383 		return NULL;
13384 
13385 	if (!isl_basic_map_divs_known(bmap))
13386 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13387 			"some divs are unknown", return NULL);
13388 
13389 	ls = isl_basic_map_get_local_space(bmap);
13390 	div = isl_local_space_get_div(ls, pos);
13391 	isl_local_space_free(ls);
13392 
13393 	return div;
13394 }
13395 
isl_basic_set_get_div(__isl_keep isl_basic_set * bset,int pos)13396 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
13397 	int pos)
13398 {
13399 	return isl_basic_map_get_div(bset, pos);
13400 }
13401 
13402 /* Plug in "subs" for dimension "type", "pos" of "bset".
13403  *
13404  * Let i be the dimension to replace and let "subs" be of the form
13405  *
13406  *	f/d
13407  *
13408  * Any integer division with a non-zero coefficient for i,
13409  *
13410  *	floor((a i + g)/m)
13411  *
13412  * is replaced by
13413  *
13414  *	floor((a f + d g)/(m d))
13415  *
13416  * Constraints of the form
13417  *
13418  *	a i + g
13419  *
13420  * are replaced by
13421  *
13422  *	a f + d g
13423  *
13424  * We currently require that "subs" is an integral expression.
13425  * Handling rational expressions may require us to add stride constraints
13426  * as we do in isl_basic_set_preimage_multi_aff.
13427  */
isl_basic_set_substitute(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)13428 __isl_give isl_basic_set *isl_basic_set_substitute(
13429 	__isl_take isl_basic_set *bset,
13430 	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13431 {
13432 	int i;
13433 	isl_int v;
13434 	isl_ctx *ctx;
13435 	isl_size n_div;
13436 
13437 	if (bset && isl_basic_set_plain_is_empty(bset))
13438 		return bset;
13439 
13440 	bset = isl_basic_set_cow(bset);
13441 	if (!bset || !subs)
13442 		goto error;
13443 
13444 	ctx = isl_basic_set_get_ctx(bset);
13445 	if (!isl_space_is_equal(bset->dim, subs->ls->dim))
13446 		isl_die(ctx, isl_error_invalid,
13447 			"spaces don't match", goto error);
13448 	n_div = isl_local_space_dim(subs->ls, isl_dim_div);
13449 	if (n_div < 0)
13450 		goto error;
13451 	if (n_div != 0)
13452 		isl_die(ctx, isl_error_unsupported,
13453 			"cannot handle divs yet", goto error);
13454 	if (!isl_int_is_one(subs->v->el[0]))
13455 		isl_die(ctx, isl_error_invalid,
13456 			"can only substitute integer expressions", goto error);
13457 
13458 	pos += isl_basic_set_offset(bset, type);
13459 
13460 	isl_int_init(v);
13461 
13462 	for (i = 0; i < bset->n_eq; ++i) {
13463 		if (isl_int_is_zero(bset->eq[i][pos]))
13464 			continue;
13465 		isl_int_set(v, bset->eq[i][pos]);
13466 		isl_int_set_si(bset->eq[i][pos], 0);
13467 		isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
13468 				v, subs->v->el + 1, subs->v->size - 1);
13469 	}
13470 
13471 	for (i = 0; i < bset->n_ineq; ++i) {
13472 		if (isl_int_is_zero(bset->ineq[i][pos]))
13473 			continue;
13474 		isl_int_set(v, bset->ineq[i][pos]);
13475 		isl_int_set_si(bset->ineq[i][pos], 0);
13476 		isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
13477 				v, subs->v->el + 1, subs->v->size - 1);
13478 	}
13479 
13480 	for (i = 0; i < bset->n_div; ++i) {
13481 		if (isl_int_is_zero(bset->div[i][1 + pos]))
13482 			continue;
13483 		isl_int_set(v, bset->div[i][1 + pos]);
13484 		isl_int_set_si(bset->div[i][1 + pos], 0);
13485 		isl_seq_combine(bset->div[i] + 1,
13486 				subs->v->el[0], bset->div[i] + 1,
13487 				v, subs->v->el + 1, subs->v->size - 1);
13488 		isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
13489 	}
13490 
13491 	isl_int_clear(v);
13492 
13493 	bset = isl_basic_set_simplify(bset);
13494 	return isl_basic_set_finalize(bset);
13495 error:
13496 	isl_basic_set_free(bset);
13497 	return NULL;
13498 }
13499 
13500 /* Plug in "subs" for dimension "type", "pos" of "set".
13501  */
isl_set_substitute(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)13502 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
13503 	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13504 {
13505 	int i;
13506 
13507 	if (set && isl_set_plain_is_empty(set))
13508 		return set;
13509 
13510 	set = isl_set_cow(set);
13511 	if (!set || !subs)
13512 		goto error;
13513 
13514 	for (i = set->n - 1; i >= 0; --i) {
13515 		set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
13516 		set = set_from_map(remove_if_empty(set_to_map(set), i));
13517 		if (!set)
13518 			return NULL;
13519 	}
13520 
13521 	return set;
13522 error:
13523 	isl_set_free(set);
13524 	return NULL;
13525 }
13526 
13527 /* Check if the range of "ma" is compatible with the domain or range
13528  * (depending on "type") of "bmap".
13529  */
check_basic_map_compatible_range_multi_aff(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13530 static isl_stat check_basic_map_compatible_range_multi_aff(
13531 	__isl_keep isl_basic_map *bmap, enum isl_dim_type type,
13532 	__isl_keep isl_multi_aff *ma)
13533 {
13534 	isl_bool m;
13535 	isl_space *ma_space;
13536 
13537 	ma_space = isl_multi_aff_get_space(ma);
13538 
13539 	m = isl_space_has_equal_params(bmap->dim, ma_space);
13540 	if (m < 0)
13541 		goto error;
13542 	if (!m)
13543 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13544 			"parameters don't match", goto error);
13545 	m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
13546 	if (m < 0)
13547 		goto error;
13548 	if (!m)
13549 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13550 			"spaces don't match", goto error);
13551 
13552 	isl_space_free(ma_space);
13553 	return isl_stat_ok;
13554 error:
13555 	isl_space_free(ma_space);
13556 	return isl_stat_error;
13557 }
13558 
13559 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
13560  * coefficients before the transformed range of dimensions,
13561  * the "n_after" coefficients after the transformed range of dimensions
13562  * and the coefficients of the other divs in "bmap".
13563  */
set_ma_divs(__isl_take isl_basic_map * bmap,__isl_keep isl_multi_aff * ma,int n_before,int n_after,int n_div)13564 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
13565 	__isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
13566 {
13567 	int i;
13568 	isl_size n_param;
13569 	isl_size n_set;
13570 	isl_local_space *ls;
13571 
13572 	if (n_div == 0)
13573 		return bmap;
13574 
13575 	ls = isl_aff_get_domain_local_space(ma->u.p[0]);
13576 	n_param = isl_local_space_dim(ls, isl_dim_param);
13577 	n_set = isl_local_space_dim(ls, isl_dim_set);
13578 	if (n_param < 0 || n_set < 0)
13579 		return isl_basic_map_free(bmap);
13580 
13581 	for (i = 0; i < n_div; ++i) {
13582 		int o_bmap = 0, o_ls = 0;
13583 
13584 		isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
13585 		o_bmap += 1 + 1 + n_param;
13586 		o_ls += 1 + 1 + n_param;
13587 		isl_seq_clr(bmap->div[i] + o_bmap, n_before);
13588 		o_bmap += n_before;
13589 		isl_seq_cpy(bmap->div[i] + o_bmap,
13590 			    ls->div->row[i] + o_ls, n_set);
13591 		o_bmap += n_set;
13592 		o_ls += n_set;
13593 		isl_seq_clr(bmap->div[i] + o_bmap, n_after);
13594 		o_bmap += n_after;
13595 		isl_seq_cpy(bmap->div[i] + o_bmap,
13596 			    ls->div->row[i] + o_ls, n_div);
13597 		o_bmap += n_div;
13598 		o_ls += n_div;
13599 		isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
13600 		bmap = isl_basic_map_add_div_constraints(bmap, i);
13601 		if (!bmap)
13602 			goto error;
13603 	}
13604 
13605 	isl_local_space_free(ls);
13606 	return bmap;
13607 error:
13608 	isl_local_space_free(ls);
13609 	return isl_basic_map_free(bmap);
13610 }
13611 
13612 /* How many stride constraints does "ma" enforce?
13613  * That is, how many of the affine expressions have a denominator
13614  * different from one?
13615  */
multi_aff_strides(__isl_keep isl_multi_aff * ma)13616 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
13617 {
13618 	int i;
13619 	int strides = 0;
13620 
13621 	for (i = 0; i < ma->n; ++i)
13622 		if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
13623 			strides++;
13624 
13625 	return strides;
13626 }
13627 
13628 /* For each affine expression in ma of the form
13629  *
13630  *	x_i = (f_i y + h_i)/m_i
13631  *
13632  * with m_i different from one, add a constraint to "bmap"
13633  * of the form
13634  *
13635  *	f_i y + h_i = m_i alpha_i
13636  *
13637  * with alpha_i an additional existentially quantified variable.
13638  *
13639  * The input variables of "ma" correspond to a subset of the variables
13640  * of "bmap".  There are "n_before" variables in "bmap" before this
13641  * subset and "n_after" variables after this subset.
13642  * The integer divisions of the affine expressions in "ma" are assumed
13643  * to have been aligned.  There are "n_div_ma" of them and
13644  * they appear first in "bmap", straight after the "n_after" variables.
13645  */
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)13646 static __isl_give isl_basic_map *add_ma_strides(
13647 	__isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
13648 	int n_before, int n_after, int n_div_ma)
13649 {
13650 	int i, k;
13651 	int div;
13652 	isl_size total;
13653 	isl_size n_param;
13654 	isl_size n_in;
13655 
13656 	total = isl_basic_map_dim(bmap, isl_dim_all);
13657 	n_param = isl_multi_aff_dim(ma, isl_dim_param);
13658 	n_in = isl_multi_aff_dim(ma, isl_dim_in);
13659 	if (total < 0 || n_param < 0 || n_in < 0)
13660 		return isl_basic_map_free(bmap);
13661 	for (i = 0; i < ma->n; ++i) {
13662 		int o_bmap = 0, o_ma = 1;
13663 
13664 		if (isl_int_is_one(ma->u.p[i]->v->el[0]))
13665 			continue;
13666 		div = isl_basic_map_alloc_div(bmap);
13667 		k = isl_basic_map_alloc_equality(bmap);
13668 		if (div < 0 || k < 0)
13669 			goto error;
13670 		isl_int_set_si(bmap->div[div][0], 0);
13671 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13672 			    ma->u.p[i]->v->el + o_ma, 1 + n_param);
13673 		o_bmap += 1 + n_param;
13674 		o_ma += 1 + n_param;
13675 		isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
13676 		o_bmap += n_before;
13677 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13678 			    ma->u.p[i]->v->el + o_ma, n_in);
13679 		o_bmap += n_in;
13680 		o_ma += n_in;
13681 		isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
13682 		o_bmap += n_after;
13683 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13684 			    ma->u.p[i]->v->el + o_ma, n_div_ma);
13685 		o_bmap += n_div_ma;
13686 		o_ma += n_div_ma;
13687 		isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
13688 		isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
13689 		total++;
13690 	}
13691 
13692 	return bmap;
13693 error:
13694 	isl_basic_map_free(bmap);
13695 	return NULL;
13696 }
13697 
13698 /* Replace the domain or range space (depending on "type) of "space" by "set".
13699  */
isl_space_set(__isl_take isl_space * space,enum isl_dim_type type,__isl_take isl_space * set)13700 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
13701 	enum isl_dim_type type, __isl_take isl_space *set)
13702 {
13703 	if (type == isl_dim_in) {
13704 		space = isl_space_range(space);
13705 		space = isl_space_map_from_domain_and_range(set, space);
13706 	} else {
13707 		space = isl_space_domain(space);
13708 		space = isl_space_map_from_domain_and_range(space, set);
13709 	}
13710 
13711 	return space;
13712 }
13713 
13714 /* Compute the preimage of the domain or range (depending on "type")
13715  * of "bmap" under the function represented by "ma".
13716  * In other words, plug in "ma" in the domain or range of "bmap".
13717  * The result is a basic map that lives in the same space as "bmap"
13718  * except that the domain or range has been replaced by
13719  * the domain space of "ma".
13720  *
13721  * If bmap is represented by
13722  *
13723  *	A(p) + S u + B x + T v + C(divs) >= 0,
13724  *
13725  * where u and x are input and output dimensions if type == isl_dim_out
13726  * while x and v are input and output dimensions if type == isl_dim_in,
13727  * and ma is represented by
13728  *
13729  *	x = D(p) + F(y) + G(divs')
13730  *
13731  * then the result is
13732  *
13733  *	A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
13734  *
13735  * The divs in the input set are similarly adjusted.
13736  * In particular
13737  *
13738  *	floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
13739  *
13740  * becomes
13741  *
13742  *	floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
13743  *		B_i G(divs') + c_i(divs))/n_i)
13744  *
13745  * If bmap is not a rational map and if F(y) involves any denominators
13746  *
13747  *	x_i = (f_i y + h_i)/m_i
13748  *
13749  * then additional constraints are added to ensure that we only
13750  * map back integer points.  That is we enforce
13751  *
13752  *	f_i y + h_i = m_i alpha_i
13753  *
13754  * with alpha_i an additional existentially quantified variable.
13755  *
13756  * We first copy over the divs from "ma".
13757  * Then we add the modified constraints and divs from "bmap".
13758  * Finally, we add the stride constraints, if needed.
13759  */
isl_basic_map_preimage_multi_aff(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13760 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
13761 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
13762 	__isl_take isl_multi_aff *ma)
13763 {
13764 	int i, k;
13765 	isl_space *space;
13766 	isl_basic_map *res = NULL;
13767 	isl_size n_before, n_after, n_div_bmap, n_div_ma;
13768 	isl_int f, c1, c2, g;
13769 	isl_bool rational;
13770 	int strides;
13771 
13772 	isl_int_init(f);
13773 	isl_int_init(c1);
13774 	isl_int_init(c2);
13775 	isl_int_init(g);
13776 
13777 	ma = isl_multi_aff_align_divs(ma);
13778 	if (!bmap || !ma)
13779 		goto error;
13780 	if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
13781 		goto error;
13782 
13783 	if (type == isl_dim_in) {
13784 		n_before = 0;
13785 		n_after = isl_basic_map_dim(bmap, isl_dim_out);
13786 	} else {
13787 		n_before = isl_basic_map_dim(bmap, isl_dim_in);
13788 		n_after = 0;
13789 	}
13790 	n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
13791 	n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
13792 	if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
13793 		goto error;
13794 
13795 	space = isl_multi_aff_get_domain_space(ma);
13796 	space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
13797 	rational = isl_basic_map_is_rational(bmap);
13798 	strides = rational ? 0 : multi_aff_strides(ma);
13799 	res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
13800 			    bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
13801 	if (rational)
13802 		res = isl_basic_map_set_rational(res);
13803 
13804 	for (i = 0; i < n_div_ma + n_div_bmap; ++i)
13805 		if (isl_basic_map_alloc_div(res) < 0)
13806 			goto error;
13807 
13808 	res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
13809 	if (!res)
13810 		goto error;
13811 
13812 	for (i = 0; i < bmap->n_eq; ++i) {
13813 		k = isl_basic_map_alloc_equality(res);
13814 		if (k < 0)
13815 			goto error;
13816 		if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13817 				    n_after, n_div_ma, n_div_bmap,
13818 				    f, c1, c2, g, 0) < 0)
13819 			goto error;
13820 	}
13821 
13822 	for (i = 0; i < bmap->n_ineq; ++i) {
13823 		k = isl_basic_map_alloc_inequality(res);
13824 		if (k < 0)
13825 			goto error;
13826 		if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13827 				    n_after, n_div_ma, n_div_bmap,
13828 				    f, c1, c2, g, 0) < 0)
13829 			goto error;
13830 	}
13831 
13832 	for (i = 0; i < bmap->n_div; ++i) {
13833 		if (isl_int_is_zero(bmap->div[i][0])) {
13834 			isl_int_set_si(res->div[n_div_ma + i][0], 0);
13835 			continue;
13836 		}
13837 		if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13838 				    n_before, n_after, n_div_ma, n_div_bmap,
13839 				    f, c1, c2, g, 1) < 0)
13840 			goto error;
13841 	}
13842 
13843 	if (strides)
13844 		res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13845 
13846 	isl_int_clear(f);
13847 	isl_int_clear(c1);
13848 	isl_int_clear(c2);
13849 	isl_int_clear(g);
13850 	isl_basic_map_free(bmap);
13851 	isl_multi_aff_free(ma);
13852 	res = isl_basic_map_simplify(res);
13853 	return isl_basic_map_finalize(res);
13854 error:
13855 	isl_int_clear(f);
13856 	isl_int_clear(c1);
13857 	isl_int_clear(c2);
13858 	isl_int_clear(g);
13859 	isl_basic_map_free(bmap);
13860 	isl_multi_aff_free(ma);
13861 	isl_basic_map_free(res);
13862 	return NULL;
13863 }
13864 
13865 /* Compute the preimage of "bset" under the function represented by "ma".
13866  * In other words, plug in "ma" in "bset".  The result is a basic set
13867  * that lives in the domain space of "ma".
13868  */
isl_basic_set_preimage_multi_aff(__isl_take isl_basic_set * bset,__isl_take isl_multi_aff * ma)13869 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13870 	__isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13871 {
13872 	return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13873 }
13874 
13875 /* Compute the preimage of the domain of "bmap" under the function
13876  * represented by "ma".
13877  * In other words, plug in "ma" in the domain of "bmap".
13878  * The result is a basic map that lives in the same space as "bmap"
13879  * except that the domain has been replaced by the domain space of "ma".
13880  */
isl_basic_map_preimage_domain_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13881 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13882 	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13883 {
13884 	return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13885 }
13886 
13887 /* Compute the preimage of the range of "bmap" under the function
13888  * represented by "ma".
13889  * In other words, plug in "ma" in the range of "bmap".
13890  * The result is a basic map that lives in the same space as "bmap"
13891  * except that the range has been replaced by the domain space of "ma".
13892  */
isl_basic_map_preimage_range_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13893 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13894 	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13895 {
13896 	return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13897 }
13898 
13899 /* Check if the range of "ma" is compatible with the domain or range
13900  * (depending on "type") of "map".
13901  * Return isl_stat_error if anything is wrong.
13902  */
check_map_compatible_range_multi_aff(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13903 static isl_stat check_map_compatible_range_multi_aff(
13904 	__isl_keep isl_map *map, enum isl_dim_type type,
13905 	__isl_keep isl_multi_aff *ma)
13906 {
13907 	isl_bool m;
13908 	isl_space *ma_space;
13909 
13910 	ma_space = isl_multi_aff_get_space(ma);
13911 	m = isl_map_space_tuple_is_equal(map, type, ma_space, isl_dim_out);
13912 	isl_space_free(ma_space);
13913 	if (m < 0)
13914 		return isl_stat_error;
13915 	if (!m)
13916 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
13917 			"spaces don't match", return isl_stat_error);
13918 	return isl_stat_ok;
13919 }
13920 
13921 /* Compute the preimage of the domain or range (depending on "type")
13922  * of "map" under the function represented by "ma".
13923  * In other words, plug in "ma" in the domain or range of "map".
13924  * The result is a map that lives in the same space as "map"
13925  * except that the domain or range has been replaced by
13926  * the domain space of "ma".
13927  *
13928  * The parameters are assumed to have been aligned.
13929  */
map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13930 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13931 	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13932 {
13933 	int i;
13934 	isl_space *space;
13935 
13936 	map = isl_map_cow(map);
13937 	ma = isl_multi_aff_align_divs(ma);
13938 	if (!map || !ma)
13939 		goto error;
13940 	if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13941 		goto error;
13942 
13943 	for (i = 0; i < map->n; ++i) {
13944 		map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13945 							isl_multi_aff_copy(ma));
13946 		if (!map->p[i])
13947 			goto error;
13948 	}
13949 
13950 	space = isl_multi_aff_get_domain_space(ma);
13951 	space = isl_space_set(isl_map_get_space(map), type, space);
13952 
13953 	isl_space_free(isl_map_take_space(map));
13954 	map = isl_map_restore_space(map, space);
13955 	if (!map)
13956 		goto error;
13957 
13958 	isl_multi_aff_free(ma);
13959 	if (map->n > 1)
13960 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
13961 	ISL_F_CLR(map, ISL_SET_NORMALIZED);
13962 	return map;
13963 error:
13964 	isl_multi_aff_free(ma);
13965 	isl_map_free(map);
13966 	return NULL;
13967 }
13968 
13969 /* Compute the preimage of the domain or range (depending on "type")
13970  * of "map" under the function represented by "ma".
13971  * In other words, plug in "ma" in the domain or range of "map".
13972  * The result is a map that lives in the same space as "map"
13973  * except that the domain or range has been replaced by
13974  * the domain space of "ma".
13975  */
isl_map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13976 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13977 	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13978 {
13979 	isl_bool aligned;
13980 
13981 	if (!map || !ma)
13982 		goto error;
13983 
13984 	aligned = isl_map_space_has_equal_params(map, ma->space);
13985 	if (aligned < 0)
13986 		goto error;
13987 	if (aligned)
13988 		return map_preimage_multi_aff(map, type, ma);
13989 
13990 	if (isl_map_check_named_params(map) < 0)
13991 		goto error;
13992 	if (!isl_space_has_named_params(ma->space))
13993 		isl_die(map->ctx, isl_error_invalid,
13994 			"unaligned unnamed parameters", goto error);
13995 	map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13996 	ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13997 
13998 	return map_preimage_multi_aff(map, type, ma);
13999 error:
14000 	isl_multi_aff_free(ma);
14001 	return isl_map_free(map);
14002 }
14003 
14004 /* Compute the preimage of "set" under the function represented by "ma".
14005  * In other words, plug in "ma" in "set".  The result is a set
14006  * that lives in the domain space of "ma".
14007  */
isl_set_preimage_multi_aff(__isl_take isl_set * set,__isl_take isl_multi_aff * ma)14008 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
14009 	__isl_take isl_multi_aff *ma)
14010 {
14011 	return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
14012 }
14013 
14014 /* Compute the preimage of the domain of "map" under the function
14015  * represented by "ma".
14016  * In other words, plug in "ma" in the domain of "map".
14017  * The result is a map that lives in the same space as "map"
14018  * except that the domain has been replaced by the domain space of "ma".
14019  */
isl_map_preimage_domain_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)14020 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
14021 	__isl_take isl_multi_aff *ma)
14022 {
14023 	return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
14024 }
14025 
14026 /* Compute the preimage of the range of "map" under the function
14027  * represented by "ma".
14028  * In other words, plug in "ma" in the range of "map".
14029  * The result is a map that lives in the same space as "map"
14030  * except that the range has been replaced by the domain space of "ma".
14031  */
isl_map_preimage_range_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)14032 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
14033 	__isl_take isl_multi_aff *ma)
14034 {
14035 	return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
14036 }
14037 
14038 /* Compute the preimage of "map" under the function represented by "pma".
14039  * In other words, plug in "pma" in the domain or range of "map".
14040  * The result is a map that lives in the same space as "map",
14041  * except that the space of type "type" has been replaced by
14042  * the domain space of "pma".
14043  *
14044  * The parameters of "map" and "pma" are assumed to have been aligned.
14045  */
isl_map_preimage_pw_multi_aff_aligned(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14046 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
14047 	__isl_take isl_map *map, enum isl_dim_type type,
14048 	__isl_take isl_pw_multi_aff *pma)
14049 {
14050 	int i;
14051 	isl_map *res;
14052 
14053 	if (!pma)
14054 		goto error;
14055 
14056 	if (pma->n == 0) {
14057 		isl_pw_multi_aff_free(pma);
14058 		res = isl_map_empty(isl_map_get_space(map));
14059 		isl_map_free(map);
14060 		return res;
14061 	}
14062 
14063 	res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14064 					isl_multi_aff_copy(pma->p[0].maff));
14065 	if (type == isl_dim_in)
14066 		res = isl_map_intersect_domain(res,
14067 						isl_map_copy(pma->p[0].set));
14068 	else
14069 		res = isl_map_intersect_range(res,
14070 						isl_map_copy(pma->p[0].set));
14071 
14072 	for (i = 1; i < pma->n; ++i) {
14073 		isl_map *res_i;
14074 
14075 		res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14076 					isl_multi_aff_copy(pma->p[i].maff));
14077 		if (type == isl_dim_in)
14078 			res_i = isl_map_intersect_domain(res_i,
14079 						isl_map_copy(pma->p[i].set));
14080 		else
14081 			res_i = isl_map_intersect_range(res_i,
14082 						isl_map_copy(pma->p[i].set));
14083 		res = isl_map_union(res, res_i);
14084 	}
14085 
14086 	isl_pw_multi_aff_free(pma);
14087 	isl_map_free(map);
14088 	return res;
14089 error:
14090 	isl_pw_multi_aff_free(pma);
14091 	isl_map_free(map);
14092 	return NULL;
14093 }
14094 
14095 /* Compute the preimage of "map" under the function represented by "pma".
14096  * In other words, plug in "pma" in the domain or range of "map".
14097  * The result is a map that lives in the same space as "map",
14098  * except that the space of type "type" has been replaced by
14099  * the domain space of "pma".
14100  */
isl_map_preimage_pw_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14101 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
14102 	enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
14103 {
14104 	isl_bool aligned;
14105 
14106 	if (!map || !pma)
14107 		goto error;
14108 
14109 	aligned = isl_map_space_has_equal_params(map, pma->dim);
14110 	if (aligned < 0)
14111 		goto error;
14112 	if (aligned)
14113 		return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14114 
14115 	if (isl_map_check_named_params(map) < 0)
14116 		goto error;
14117 	if (isl_pw_multi_aff_check_named_params(pma) < 0)
14118 		goto error;
14119 	map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
14120 	pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
14121 
14122 	return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14123 error:
14124 	isl_pw_multi_aff_free(pma);
14125 	return isl_map_free(map);
14126 }
14127 
14128 /* Compute the preimage of "set" under the function represented by "pma".
14129  * In other words, plug in "pma" in "set".  The result is a set
14130  * that lives in the domain space of "pma".
14131  */
isl_set_preimage_pw_multi_aff(__isl_take isl_set * set,__isl_take isl_pw_multi_aff * pma)14132 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
14133 	__isl_take isl_pw_multi_aff *pma)
14134 {
14135 	return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
14136 }
14137 
14138 /* Compute the preimage of the domain of "map" under the function
14139  * represented by "pma".
14140  * In other words, plug in "pma" in the domain of "map".
14141  * The result is a map that lives in the same space as "map",
14142  * except that domain space has been replaced by the domain space of "pma".
14143  */
isl_map_preimage_domain_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14144 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
14145 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14146 {
14147 	return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
14148 }
14149 
14150 /* Compute the preimage of the range of "map" under the function
14151  * represented by "pma".
14152  * In other words, plug in "pma" in the range of "map".
14153  * The result is a map that lives in the same space as "map",
14154  * except that range space has been replaced by the domain space of "pma".
14155  */
isl_map_preimage_range_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14156 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
14157 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14158 {
14159 	return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
14160 }
14161 
14162 /* Compute the preimage of "map" under the function represented by "mpa".
14163  * In other words, plug in "mpa" in the domain or range of "map".
14164  * The result is a map that lives in the same space as "map",
14165  * except that the space of type "type" has been replaced by
14166  * the domain space of "mpa".
14167  *
14168  * If the map does not involve any constraints that refer to the
14169  * dimensions of the substituted space, then the only possible
14170  * effect of "mpa" on the map is to map the space to a different space.
14171  * We create a separate isl_multi_aff to effectuate this change
14172  * in order to avoid spurious splitting of the map along the pieces
14173  * of "mpa".
14174  * If "mpa" has a non-trivial explicit domain, however,
14175  * then the full substitution should be performed.
14176  */
isl_map_preimage_multi_pw_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_pw_aff * mpa)14177 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
14178 	enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
14179 {
14180 	isl_size n;
14181 	isl_bool full;
14182 	isl_pw_multi_aff *pma;
14183 
14184 	n = isl_map_dim(map, type);
14185 	if (n < 0 || !mpa)
14186 		goto error;
14187 
14188 	full = isl_map_involves_dims(map, type, 0, n);
14189 	if (full >= 0 && !full)
14190 		full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
14191 	if (full < 0)
14192 		goto error;
14193 	if (!full) {
14194 		isl_space *space;
14195 		isl_multi_aff *ma;
14196 
14197 		space = isl_multi_pw_aff_get_space(mpa);
14198 		isl_multi_pw_aff_free(mpa);
14199 		ma = isl_multi_aff_zero(space);
14200 		return isl_map_preimage_multi_aff(map, type, ma);
14201 	}
14202 
14203 	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
14204 	return isl_map_preimage_pw_multi_aff(map, type, pma);
14205 error:
14206 	isl_map_free(map);
14207 	isl_multi_pw_aff_free(mpa);
14208 	return NULL;
14209 }
14210 
14211 /* Compute the preimage of "map" under the function represented by "mpa".
14212  * In other words, plug in "mpa" in the domain "map".
14213  * The result is a map that lives in the same space as "map",
14214  * except that domain space has been replaced by the domain space of "mpa".
14215  */
isl_map_preimage_domain_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * mpa)14216 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
14217 	__isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
14218 {
14219 	return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
14220 }
14221 
14222 /* Compute the preimage of "set" by the function represented by "mpa".
14223  * In other words, plug in "mpa" in "set".
14224  */
isl_set_preimage_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * mpa)14225 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
14226 	__isl_take isl_multi_pw_aff *mpa)
14227 {
14228 	return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
14229 }
14230 
14231 /* Return a copy of the equality constraints of "bset" as a matrix.
14232  */
isl_basic_set_extract_equalities(__isl_keep isl_basic_set * bset)14233 __isl_give isl_mat *isl_basic_set_extract_equalities(
14234 	__isl_keep isl_basic_set *bset)
14235 {
14236 	isl_ctx *ctx;
14237 	isl_size total;
14238 
14239 	total = isl_basic_set_dim(bset, isl_dim_all);
14240 	if (total < 0)
14241 		return NULL;
14242 
14243 	ctx = isl_basic_set_get_ctx(bset);
14244 	return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
14245 }
14246 
14247 /* Are the "n" "coefficients" starting at "first" of the integer division
14248  * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
14249  * to each other?
14250  * The "coefficient" at position 0 is the denominator.
14251  * The "coefficient" at position 1 is the constant term.
14252  */
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)14253 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
14254 	int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
14255 	unsigned first, unsigned n)
14256 {
14257 	if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
14258 		return isl_bool_error;
14259 	if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
14260 		return isl_bool_error;
14261 	return isl_seq_eq(bmap1->div[pos1] + first,
14262 			  bmap2->div[pos2] + first, n);
14263 }
14264 
14265 /* Are the integer division expressions at position "pos1" in "bmap1" and
14266  * "pos2" in "bmap2" equal to each other, except that the constant terms
14267  * are different?
14268  */
isl_basic_map_equal_div_expr_except_constant(__isl_keep isl_basic_map * bmap1,int pos1,__isl_keep isl_basic_map * bmap2,int pos2)14269 isl_bool isl_basic_map_equal_div_expr_except_constant(
14270 	__isl_keep isl_basic_map *bmap1, int pos1,
14271 	__isl_keep isl_basic_map *bmap2, int pos2)
14272 {
14273 	isl_bool equal;
14274 	isl_size total, total2;
14275 
14276 	total = isl_basic_map_dim(bmap1, isl_dim_all);
14277 	total2 = isl_basic_map_dim(bmap2, isl_dim_all);
14278 	if (total < 0 || total2 < 0)
14279 		return isl_bool_error;
14280 	if (total != total2)
14281 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
14282 			"incomparable div expressions", return isl_bool_error);
14283 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14284 						0, 1);
14285 	if (equal < 0 || !equal)
14286 		return equal;
14287 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14288 						1, 1);
14289 	if (equal < 0 || equal)
14290 		return isl_bool_not(equal);
14291 	return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14292 						2, total);
14293 }
14294 
14295 /* Replace the numerator of the constant term of the integer division
14296  * expression at position "div" in "bmap" by "value".
14297  * The caller guarantees that this does not change the meaning
14298  * of the input.
14299  */
isl_basic_map_set_div_expr_constant_num_si_inplace(__isl_take isl_basic_map * bmap,int div,int value)14300 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
14301 	__isl_take isl_basic_map *bmap, int div, int value)
14302 {
14303 	if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
14304 		return isl_basic_map_free(bmap);
14305 
14306 	isl_int_set_si(bmap->div[div][1], value);
14307 
14308 	return bmap;
14309 }
14310 
14311 /* Is the point "inner" internal to inequality constraint "ineq"
14312  * of "bset"?
14313  * The point is considered to be internal to the inequality constraint,
14314  * if it strictly lies on the positive side of the inequality constraint,
14315  * or if it lies on the constraint and the constraint is lexico-positive.
14316  */
is_internal(__isl_keep isl_vec * inner,__isl_keep isl_basic_set * bset,int ineq)14317 static isl_bool is_internal(__isl_keep isl_vec *inner,
14318 	__isl_keep isl_basic_set *bset, int ineq)
14319 {
14320 	isl_ctx *ctx;
14321 	int pos;
14322 	isl_size total;
14323 
14324 	if (!inner || !bset)
14325 		return isl_bool_error;
14326 
14327 	ctx = isl_basic_set_get_ctx(bset);
14328 	isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
14329 				&ctx->normalize_gcd);
14330 	if (!isl_int_is_zero(ctx->normalize_gcd))
14331 		return isl_int_is_nonneg(ctx->normalize_gcd);
14332 
14333 	total = isl_basic_set_dim(bset, isl_dim_all);
14334 	if (total < 0)
14335 		return isl_bool_error;
14336 	pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
14337 	return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
14338 }
14339 
14340 /* Tighten the inequality constraints of "bset" that are outward with respect
14341  * to the point "vec".
14342  * That is, tighten the constraints that are not satisfied by "vec".
14343  *
14344  * "vec" is a point internal to some superset S of "bset" that is used
14345  * to make the subsets of S disjoint, by tightening one half of the constraints
14346  * that separate two subsets.  In particular, the constraints of S
14347  * are all satisfied by "vec" and should not be tightened.
14348  * Of the internal constraints, those that have "vec" on the outside
14349  * are tightened.  The shared facet is included in the adjacent subset
14350  * with the opposite constraint.
14351  * For constraints that saturate "vec", this criterion cannot be used
14352  * to determine which of the two sides should be tightened.
14353  * Instead, the sign of the first non-zero coefficient is used
14354  * to make this choice.  Note that this second criterion is never used
14355  * on the constraints of S since "vec" is interior to "S".
14356  */
isl_basic_set_tighten_outward(__isl_take isl_basic_set * bset,__isl_keep isl_vec * vec)14357 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
14358 	__isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
14359 {
14360 	int j;
14361 
14362 	bset = isl_basic_set_cow(bset);
14363 	if (!bset)
14364 		return NULL;
14365 	for (j = 0; j < bset->n_ineq; ++j) {
14366 		isl_bool internal;
14367 
14368 		internal = is_internal(vec, bset, j);
14369 		if (internal < 0)
14370 			return isl_basic_set_free(bset);
14371 		if (internal)
14372 			continue;
14373 		isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
14374 	}
14375 
14376 	return bset;
14377 }
14378 
14379 /* Replace the variables x of type "type" starting at "first" in "bmap"
14380  * by x' with x = M x' with M the matrix trans.
14381  * That is, replace the corresponding coefficients c by c M.
14382  *
14383  * The transformation matrix should be a square matrix.
14384  */
isl_basic_map_transform_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14385 __isl_give isl_basic_map *isl_basic_map_transform_dims(
14386 	__isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
14387 	__isl_take isl_mat *trans)
14388 {
14389 	unsigned pos;
14390 
14391 	bmap = isl_basic_map_cow(bmap);
14392 	if (!bmap || !trans)
14393 		goto error;
14394 
14395 	if (trans->n_row != trans->n_col)
14396 		isl_die(trans->ctx, isl_error_invalid,
14397 			"expecting square transformation matrix", goto error);
14398 	if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
14399 		goto error;
14400 
14401 	pos = isl_basic_map_offset(bmap, type) + first;
14402 
14403 	if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
14404 			isl_mat_copy(trans)) < 0)
14405 		goto error;
14406 	if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
14407 		      isl_mat_copy(trans)) < 0)
14408 		goto error;
14409 	if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
14410 		      isl_mat_copy(trans)) < 0)
14411 		goto error;
14412 
14413 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
14414 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
14415 
14416 	isl_mat_free(trans);
14417 	return bmap;
14418 error:
14419 	isl_mat_free(trans);
14420 	isl_basic_map_free(bmap);
14421 	return NULL;
14422 }
14423 
14424 /* Replace the variables x of type "type" starting at "first" in "bset"
14425  * by x' with x = M x' with M the matrix trans.
14426  * That is, replace the corresponding coefficients c by c M.
14427  *
14428  * The transformation matrix should be a square matrix.
14429  */
isl_basic_set_transform_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14430 __isl_give isl_basic_set *isl_basic_set_transform_dims(
14431 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
14432 	__isl_take isl_mat *trans)
14433 {
14434 	return isl_basic_map_transform_dims(bset, type, first, trans);
14435 }
14436