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 
115 /* Return the dimensionality of the domain (tuple) of the map.
116  */
isl_map_domain_tuple_dim(__isl_keep isl_map * map)117 isl_size isl_map_domain_tuple_dim(__isl_keep isl_map *map)
118 {
119 	return isl_map_dim(map, isl_dim_in);
120 }
121 
122 /* Return the dimensionality of the range (tuple) of the map.
123  */
isl_map_range_tuple_dim(__isl_keep isl_map * map)124 isl_size isl_map_range_tuple_dim(__isl_keep isl_map *map)
125 {
126 	return isl_map_dim(map, isl_dim_out);
127 }
128 
isl_set_dim(__isl_keep isl_set * set,enum isl_dim_type type)129 isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
130 {
131 	return isl_map_dim(set_to_map(set), type);
132 }
133 
134 /* Return the dimensionality of the (tuple of the) set.
135  */
isl_set_tuple_dim(__isl_keep isl_set * set)136 isl_size isl_set_tuple_dim(__isl_keep isl_set *set)
137 {
138 	return isl_set_dim(set, isl_dim_set);
139 }
140 
141 /* Return the position of the variables of the given type
142  * within the sequence of variables of "bmap".
143  */
isl_basic_map_var_offset(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)144 isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
145 	enum isl_dim_type type)
146 {
147 	isl_space *space;
148 
149 	space = isl_basic_map_peek_space(bmap);
150 	if (!space)
151 		return isl_size_error;
152 
153 	switch (type) {
154 	case isl_dim_param:
155 	case isl_dim_in:
156 	case isl_dim_out:	return isl_space_offset(space, type);
157 	case isl_dim_div:	return isl_space_dim(space, isl_dim_all);
158 	case isl_dim_cst:
159 	default:
160 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
161 			"invalid dimension type", return isl_size_error);
162 	}
163 }
164 
165 /* Return the position of the variables of the given type
166  * within the sequence of variables of "bset".
167  */
isl_basic_set_var_offset(__isl_keep isl_basic_set * bset,enum isl_dim_type type)168 isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
169 	enum isl_dim_type type)
170 {
171 	return isl_basic_map_var_offset(bset_to_bmap(bset), type);
172 }
173 
174 /* Return the position of the coefficients of the variables of the given type
175  * within the sequence of coefficients of "bmap".
176  */
isl_basic_map_offset(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)177 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
178 	enum isl_dim_type type)
179 {
180 	switch (type) {
181 	case isl_dim_cst:	return 0;
182 	case isl_dim_param:
183 	case isl_dim_in:
184 	case isl_dim_out:
185 	case isl_dim_div:	return 1 + isl_basic_map_var_offset(bmap, type);
186 	default:		return 0;
187 	}
188 }
189 
isl_basic_set_offset(__isl_keep isl_basic_set * bset,enum isl_dim_type type)190 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
191 					enum isl_dim_type type)
192 {
193 	return isl_basic_map_offset(bset, type);
194 }
195 
map_offset(__isl_keep isl_map * map,enum isl_dim_type type)196 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
197 {
198 	return pos(map->dim, type);
199 }
200 
isl_basic_set_dim(__isl_keep isl_basic_set * bset,enum isl_dim_type type)201 isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,
202 				enum isl_dim_type type)
203 {
204 	return isl_basic_map_dim(bset, type);
205 }
206 
isl_basic_set_n_dim(__isl_keep isl_basic_set * bset)207 isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
208 {
209 	return isl_basic_set_dim(bset, isl_dim_set);
210 }
211 
isl_basic_set_n_param(__isl_keep isl_basic_set * bset)212 isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
213 {
214 	return isl_basic_set_dim(bset, isl_dim_param);
215 }
216 
isl_basic_set_total_dim(__isl_keep const isl_basic_set * bset)217 isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
218 {
219 	return isl_basic_map_total_dim(const_bset_to_bmap(bset));
220 }
221 
isl_set_n_dim(__isl_keep isl_set * set)222 isl_size isl_set_n_dim(__isl_keep isl_set *set)
223 {
224 	return isl_set_dim(set, isl_dim_set);
225 }
226 
isl_set_n_param(__isl_keep isl_set * set)227 isl_size isl_set_n_param(__isl_keep isl_set *set)
228 {
229 	return isl_set_dim(set, isl_dim_param);
230 }
231 
isl_basic_map_total_dim(__isl_keep const isl_basic_map * bmap)232 isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
233 {
234 	isl_size dim;
235 
236 	if (!bmap)
237 		return isl_size_error;
238 	dim = isl_space_dim(bmap->dim, isl_dim_all);
239 	if (dim < 0)
240 		return isl_size_error;
241 	return dim + bmap->n_div;
242 }
243 
244 /* Return the number of equality constraints in the description of "bmap".
245  * Return isl_size_error on error.
246  */
isl_basic_map_n_equality(__isl_keep isl_basic_map * bmap)247 isl_size isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
248 {
249 	if (!bmap)
250 		return isl_size_error;
251 	return bmap->n_eq;
252 }
253 
254 /* Return the number of equality constraints in the description of "bset".
255  * Return isl_size_error on error.
256  */
isl_basic_set_n_equality(__isl_keep isl_basic_set * bset)257 isl_size isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
258 {
259 	return isl_basic_map_n_equality(bset_to_bmap(bset));
260 }
261 
262 /* Return the number of inequality constraints in the description of "bmap".
263  * Return isl_size_error on error.
264  */
isl_basic_map_n_inequality(__isl_keep isl_basic_map * bmap)265 isl_size isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
266 {
267 	if (!bmap)
268 		return isl_size_error;
269 	return bmap->n_ineq;
270 }
271 
272 /* Return the number of inequality constraints in the description of "bset".
273  * Return isl_size_error on error.
274  */
isl_basic_set_n_inequality(__isl_keep isl_basic_set * bset)275 isl_size isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
276 {
277 	return isl_basic_map_n_inequality(bset_to_bmap(bset));
278 }
279 
280 /* Do "bmap1" and "bmap2" have the same parameters?
281  */
isl_basic_map_has_equal_params(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)282 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
283 	__isl_keep isl_basic_map *bmap2)
284 {
285 	isl_space *space1, *space2;
286 
287 	space1 = isl_basic_map_peek_space(bmap1);
288 	space2 = isl_basic_map_peek_space(bmap2);
289 	return isl_space_has_equal_params(space1, space2);
290 }
291 
292 /* Do "map1" and "map2" have the same parameters?
293  */
isl_map_has_equal_params(__isl_keep isl_map * map1,__isl_keep isl_map * map2)294 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
295 	__isl_keep isl_map *map2)
296 {
297 	isl_space *space1, *space2;
298 
299 	space1 = isl_map_peek_space(map1);
300 	space2 = isl_map_peek_space(map2);
301 	return isl_space_has_equal_params(space1, space2);
302 }
303 
304 /* Do "map" and "set" have the same parameters?
305  */
isl_map_set_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_set * set)306 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
307 	__isl_keep isl_set *set)
308 {
309 	return isl_map_has_equal_params(map, set_to_map(set));
310 }
311 
312 /* Is the tuple of type "type" of "bmap" the same as the single tuple of "bset"?
313  */
isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_basic_set * bset)314 static isl_bool isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map *bmap,
315 	enum isl_dim_type type, __isl_keep isl_basic_set *bset)
316 {
317 	isl_space *bmap_space, *bset_space;
318 
319 	bmap_space = isl_basic_map_peek_space(bmap);
320 	bset_space = isl_basic_set_peek_space(bset);
321 	return isl_space_tuple_is_equal(bmap_space, type,
322 					bset_space, isl_dim_set);
323 }
324 
325 /* Is the tuple of type "type" of "map" the same as the single tuple of "set"?
326  */
isl_map_set_tuple_is_equal(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_set * set)327 static isl_bool isl_map_set_tuple_is_equal(__isl_keep isl_map *map,
328 	enum isl_dim_type type, __isl_keep isl_set *set)
329 {
330 	return isl_map_tuple_is_equal(map, type, set_to_map(set), isl_dim_set);
331 }
332 
isl_map_compatible_domain(__isl_keep isl_map * map,__isl_keep isl_set * set)333 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
334 	__isl_keep isl_set *set)
335 {
336 	isl_bool m;
337 	if (!map || !set)
338 		return isl_bool_error;
339 	m = isl_map_has_equal_params(map, set_to_map(set));
340 	if (m < 0 || !m)
341 		return m;
342 	return isl_map_set_tuple_is_equal(map, isl_dim_in, set);
343 }
344 
isl_basic_map_compatible_domain(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)345 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
346 	__isl_keep isl_basic_set *bset)
347 {
348 	isl_bool m;
349 	if (!bmap || !bset)
350 		return isl_bool_error;
351 	m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
352 	if (m < 0 || !m)
353 		return m;
354 	return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_in, bset);
355 }
356 
isl_map_compatible_range(__isl_keep isl_map * map,__isl_keep isl_set * set)357 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
358 	__isl_keep isl_set *set)
359 {
360 	isl_bool m;
361 	if (!map || !set)
362 		return isl_bool_error;
363 	m = isl_map_has_equal_params(map, set_to_map(set));
364 	if (m < 0 || !m)
365 		return m;
366 	return isl_map_set_tuple_is_equal(map, isl_dim_out, set);
367 }
368 
isl_basic_map_compatible_range(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)369 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
370 	__isl_keep isl_basic_set *bset)
371 {
372 	isl_bool m;
373 	if (!bmap || !bset)
374 		return isl_bool_error;
375 	m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
376 	if (m < 0 || !m)
377 		return m;
378 	return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_out, bset);
379 }
380 
isl_basic_map_get_ctx(__isl_keep isl_basic_map * bmap)381 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
382 {
383 	return bmap ? bmap->ctx : NULL;
384 }
385 
isl_basic_set_get_ctx(__isl_keep isl_basic_set * bset)386 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
387 {
388 	return bset ? bset->ctx : NULL;
389 }
390 
isl_map_get_ctx(__isl_keep isl_map * map)391 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
392 {
393 	return map ? map->ctx : NULL;
394 }
395 
isl_set_get_ctx(__isl_keep isl_set * set)396 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
397 {
398 	return set ? set->ctx : NULL;
399 }
400 
401 /* Return the space of "bmap".
402  */
isl_basic_map_peek_space(__isl_keep const isl_basic_map * bmap)403 __isl_keep isl_space *isl_basic_map_peek_space(
404 	__isl_keep const isl_basic_map *bmap)
405 {
406 	return bmap ? bmap->dim : NULL;
407 }
408 
409 /* Return the space of "bset".
410  */
isl_basic_set_peek_space(__isl_keep isl_basic_set * bset)411 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
412 {
413 	return isl_basic_map_peek_space(bset_to_bmap(bset));
414 }
415 
isl_basic_map_get_space(__isl_keep isl_basic_map * bmap)416 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
417 {
418 	return isl_space_copy(isl_basic_map_peek_space(bmap));
419 }
420 
isl_basic_set_get_space(__isl_keep isl_basic_set * bset)421 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
422 {
423 	return isl_basic_map_get_space(bset_to_bmap(bset));
424 }
425 
426 /* Return the space of "bmap".
427  * This may be either a copy or the space itself
428  * if there is only one reference to "bmap".
429  * This allows the space to be modified inplace
430  * if both the basic map and its space have only a single reference.
431  * The caller is not allowed to modify "bmap" between this call and
432  * a subsequent call to isl_basic_map_restore_space.
433  * The only exception is that isl_basic_map_free can be called instead.
434  */
isl_basic_map_take_space(__isl_keep isl_basic_map * bmap)435 static __isl_give isl_space *isl_basic_map_take_space(
436 	__isl_keep isl_basic_map *bmap)
437 {
438 	isl_space *space;
439 
440 	if (!bmap)
441 		return NULL;
442 	if (bmap->ref != 1)
443 		return isl_basic_map_get_space(bmap);
444 	space = bmap->dim;
445 	bmap->dim = NULL;
446 	return space;
447 }
448 
449 /* Set the space of "bmap" to "space", where the space of "bmap" may be missing
450  * due to a preceding call to isl_basic_map_take_space.
451  * However, in this case, "bmap" only has a single reference and
452  * then the call to isl_basic_map_cow has no effect.
453  */
isl_basic_map_restore_space(__isl_take isl_basic_map * bmap,__isl_take isl_space * space)454 static __isl_give isl_basic_map *isl_basic_map_restore_space(
455 	__isl_take isl_basic_map *bmap, __isl_take isl_space *space)
456 {
457 	if (!bmap || !space)
458 		goto error;
459 
460 	if (bmap->dim == space) {
461 		isl_space_free(space);
462 		return bmap;
463 	}
464 
465 	bmap = isl_basic_map_cow(bmap);
466 	if (!bmap)
467 		goto error;
468 	isl_space_free(bmap->dim);
469 	bmap->dim = space;
470 
471 	return bmap;
472 error:
473 	isl_basic_map_free(bmap);
474 	isl_space_free(space);
475 	return NULL;
476 }
477 
478 /* Extract the divs in "bmap" as a matrix.
479  */
isl_basic_map_get_divs(__isl_keep isl_basic_map * bmap)480 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
481 {
482 	int i;
483 	isl_ctx *ctx;
484 	isl_mat *div;
485 	isl_size v_div;
486 	unsigned cols;
487 
488 	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
489 	if (v_div < 0)
490 		return NULL;
491 
492 	ctx = isl_basic_map_get_ctx(bmap);
493 	cols = 1 + 1 + v_div + bmap->n_div;
494 	div = isl_mat_alloc(ctx, bmap->n_div, cols);
495 	if (!div)
496 		return NULL;
497 
498 	for (i = 0; i < bmap->n_div; ++i)
499 		isl_seq_cpy(div->row[i], bmap->div[i], cols);
500 
501 	return div;
502 }
503 
504 /* Extract the divs in "bset" as a matrix.
505  */
isl_basic_set_get_divs(__isl_keep isl_basic_set * bset)506 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
507 {
508 	return isl_basic_map_get_divs(bset);
509 }
510 
isl_basic_map_get_local_space(__isl_keep isl_basic_map * bmap)511 __isl_give isl_local_space *isl_basic_map_get_local_space(
512 	__isl_keep isl_basic_map *bmap)
513 {
514 	isl_mat *div;
515 
516 	if (!bmap)
517 		return NULL;
518 
519 	div = isl_basic_map_get_divs(bmap);
520 	return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
521 }
522 
isl_basic_set_get_local_space(__isl_keep isl_basic_set * bset)523 __isl_give isl_local_space *isl_basic_set_get_local_space(
524 	__isl_keep isl_basic_set *bset)
525 {
526 	return isl_basic_map_get_local_space(bset);
527 }
528 
529 /* For each known div d = floor(f/m), add the constraints
530  *
531  *		f - m d >= 0
532  *		-(f-(m-1)) + m d >= 0
533  *
534  * Do not finalize the result.
535  */
add_known_div_constraints(__isl_take isl_basic_map * bmap)536 static __isl_give isl_basic_map *add_known_div_constraints(
537 	__isl_take isl_basic_map *bmap)
538 {
539 	int i;
540 	isl_size n_div;
541 
542 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
543 	if (n_div < 0)
544 		return isl_basic_map_free(bmap);
545 	if (n_div == 0)
546 		return bmap;
547 	bmap = isl_basic_map_cow(bmap);
548 	bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
549 	if (!bmap)
550 		return NULL;
551 	for (i = 0; i < n_div; ++i) {
552 		if (isl_int_is_zero(bmap->div[i][0]))
553 			continue;
554 		bmap = isl_basic_map_add_div_constraints(bmap, i);
555 	}
556 
557 	return bmap;
558 }
559 
isl_basic_map_from_local_space(__isl_take isl_local_space * ls)560 __isl_give isl_basic_map *isl_basic_map_from_local_space(
561 	__isl_take isl_local_space *ls)
562 {
563 	int i;
564 	isl_size n_div;
565 	isl_basic_map *bmap;
566 
567 	n_div = isl_local_space_dim(ls, isl_dim_div);
568 	if (n_div < 0)
569 		ls = isl_local_space_free(ls);
570 	if (!ls)
571 		return NULL;
572 
573 	bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
574 					n_div, 0, 2 * n_div);
575 
576 	for (i = 0; i < n_div; ++i)
577 		if (isl_basic_map_alloc_div(bmap) < 0)
578 			goto error;
579 
580 	for (i = 0; i < n_div; ++i)
581 		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
582 	bmap = add_known_div_constraints(bmap);
583 
584 	isl_local_space_free(ls);
585 	return bmap;
586 error:
587 	isl_local_space_free(ls);
588 	isl_basic_map_free(bmap);
589 	return NULL;
590 }
591 
isl_basic_set_from_local_space(__isl_take isl_local_space * ls)592 __isl_give isl_basic_set *isl_basic_set_from_local_space(
593 	__isl_take isl_local_space *ls)
594 {
595 	return isl_basic_map_from_local_space(ls);
596 }
597 
isl_map_get_space(__isl_keep isl_map * map)598 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
599 {
600 	return isl_space_copy(isl_map_peek_space(map));
601 }
602 
isl_set_get_space(__isl_keep isl_set * set)603 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
604 {
605 	if (!set)
606 		return NULL;
607 	return isl_space_copy(set->dim);
608 }
609 
610 /* Return the space of "map".
611  * This may be either a copy or the space itself
612  * if there is only one reference to "map".
613  * This allows the space to be modified inplace
614  * if both the map and its space have only a single reference.
615  * The caller is not allowed to modify "map" between this call and
616  * a subsequent call to isl_map_restore_space.
617  * The only exception is that isl_map_free can be called instead.
618  */
isl_map_take_space(__isl_keep isl_map * map)619 static __isl_give isl_space *isl_map_take_space(__isl_keep isl_map *map)
620 {
621 	isl_space *space;
622 
623 	if (!map)
624 		return NULL;
625 	if (map->ref != 1)
626 		return isl_map_get_space(map);
627 	space = map->dim;
628 	map->dim = NULL;
629 	return space;
630 }
631 
632 /* Set the space of "map" to "space", where the space of "map" may be missing
633  * due to a preceding call to isl_map_take_space.
634  * However, in this case, "map" only has a single reference and
635  * then the call to isl_map_cow has no effect.
636  */
isl_map_restore_space(__isl_take isl_map * map,__isl_take isl_space * space)637 static __isl_give isl_map *isl_map_restore_space(__isl_take isl_map *map,
638 	__isl_take isl_space *space)
639 {
640 	if (!map || !space)
641 		goto error;
642 
643 	if (map->dim == space) {
644 		isl_space_free(space);
645 		return map;
646 	}
647 
648 	map = isl_map_cow(map);
649 	if (!map)
650 		goto error;
651 	isl_space_free(map->dim);
652 	map->dim = space;
653 
654 	return map;
655 error:
656 	isl_map_free(map);
657 	isl_space_free(space);
658 	return NULL;
659 }
660 
isl_basic_map_set_tuple_name(__isl_take isl_basic_map * bmap,enum isl_dim_type type,const char * s)661 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
662 	__isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
663 {
664 	isl_space *space;
665 
666 	space = isl_basic_map_take_space(bmap);
667 	space = isl_space_set_tuple_name(space, type, s);
668 	bmap = isl_basic_map_restore_space(bmap, space);
669 	bmap = isl_basic_map_finalize(bmap);
670 	return bmap;
671 }
672 
isl_basic_set_set_tuple_name(__isl_take isl_basic_set * bset,const char * s)673 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
674 	__isl_take isl_basic_set *bset, const char *s)
675 {
676 	return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
677 }
678 
isl_basic_map_get_tuple_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)679 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
680 	enum isl_dim_type type)
681 {
682 	return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
683 }
684 
isl_map_set_tuple_name(__isl_take isl_map * map,enum isl_dim_type type,const char * s)685 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
686 	enum isl_dim_type type, const char *s)
687 {
688 	int i;
689 	isl_space *space;
690 
691 	map = isl_map_cow(map);
692 	if (!map)
693 		return NULL;
694 
695 	for (i = 0; i < map->n; ++i) {
696 		map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
697 		if (!map->p[i])
698 			goto error;
699 	}
700 
701 	space = isl_map_take_space(map);
702 	space = isl_space_set_tuple_name(space, type, s);
703 	map = isl_map_restore_space(map, space);
704 
705 	return map;
706 error:
707 	isl_map_free(map);
708 	return NULL;
709 }
710 
711 /* Replace the identifier of the tuple of type "type" by "id".
712  */
isl_basic_map_set_tuple_id(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_id * id)713 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
714 	__isl_take isl_basic_map *bmap,
715 	enum isl_dim_type type, __isl_take isl_id *id)
716 {
717 	isl_space *space;
718 
719 	space = isl_basic_map_take_space(bmap);
720 	space = isl_space_set_tuple_id(space, type, id);
721 	bmap = isl_basic_map_restore_space(bmap, space);
722 	bmap = isl_basic_map_finalize(bmap);
723 	return bmap;
724 }
725 
726 /* Replace the identifier of the tuple by "id".
727  */
isl_basic_set_set_tuple_id(__isl_take isl_basic_set * bset,__isl_take isl_id * id)728 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
729 	__isl_take isl_basic_set *bset, __isl_take isl_id *id)
730 {
731 	return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
732 }
733 
734 /* Does the input or output tuple have a name?
735  */
isl_map_has_tuple_name(__isl_keep isl_map * map,enum isl_dim_type type)736 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
737 {
738 	return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
739 }
740 
isl_map_get_tuple_name(__isl_keep isl_map * map,enum isl_dim_type type)741 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
742 	enum isl_dim_type type)
743 {
744 	return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
745 }
746 
isl_set_set_tuple_name(__isl_take isl_set * set,const char * s)747 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
748 	const char *s)
749 {
750 	return set_from_map(isl_map_set_tuple_name(set_to_map(set),
751 						isl_dim_set, s));
752 }
753 
isl_map_set_tuple_id(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_id * id)754 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
755 	enum isl_dim_type type, __isl_take isl_id *id)
756 {
757 	isl_space *space;
758 
759 	space = isl_map_take_space(map);
760 	space = isl_space_set_tuple_id(space, type, id);
761 	map = isl_map_restore_space(map, space);
762 
763 	return isl_map_reset_space(map, isl_map_get_space(map));
764 }
765 
766 /* Replace the identifier of the domain tuple of "map" by "id".
767  */
isl_map_set_domain_tuple_id(__isl_take isl_map * map,__isl_take isl_id * id)768 __isl_give isl_map *isl_map_set_domain_tuple_id(__isl_take isl_map *map,
769 	__isl_take isl_id *id)
770 {
771 	return isl_map_set_tuple_id(map, isl_dim_in, id);
772 }
773 
774 /* Replace the identifier of the range tuple of "map" by "id".
775  */
isl_map_set_range_tuple_id(__isl_take isl_map * map,__isl_take isl_id * id)776 __isl_give isl_map *isl_map_set_range_tuple_id(__isl_take isl_map *map,
777 	__isl_take isl_id *id)
778 {
779 	return isl_map_set_tuple_id(map, isl_dim_out, id);
780 }
781 
isl_set_set_tuple_id(__isl_take isl_set * set,__isl_take isl_id * id)782 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
783 	__isl_take isl_id *id)
784 {
785 	return isl_map_set_tuple_id(set, isl_dim_set, id);
786 }
787 
isl_map_reset_tuple_id(__isl_take isl_map * map,enum isl_dim_type type)788 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
789 	enum isl_dim_type type)
790 {
791 	isl_space *space;
792 
793 	space = isl_map_take_space(map);
794 	space = isl_space_reset_tuple_id(space, type);
795 	map = isl_map_restore_space(map, space);
796 
797 	return isl_map_reset_space(map, isl_map_get_space(map));
798 }
799 
isl_set_reset_tuple_id(__isl_take isl_set * set)800 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
801 {
802 	return isl_map_reset_tuple_id(set, isl_dim_set);
803 }
804 
isl_map_has_tuple_id(__isl_keep isl_map * map,enum isl_dim_type type)805 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
806 {
807 	return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
808 }
809 
810 /* Does the domain tuple of "map" have an identifier?
811  */
isl_map_has_domain_tuple_id(__isl_keep isl_map * map)812 isl_bool isl_map_has_domain_tuple_id(__isl_keep isl_map *map)
813 {
814 	return isl_map_has_tuple_id(map, isl_dim_in);
815 }
816 
817 /* Does the range tuple of "map" have an identifier?
818  */
isl_map_has_range_tuple_id(__isl_keep isl_map * map)819 isl_bool isl_map_has_range_tuple_id(__isl_keep isl_map *map)
820 {
821 	return isl_map_has_tuple_id(map, isl_dim_out);
822 }
823 
isl_map_get_tuple_id(__isl_keep isl_map * map,enum isl_dim_type type)824 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
825 	enum isl_dim_type type)
826 {
827 	return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
828 }
829 
830 /* Return the identifier of the domain tuple of "map", assuming it has one.
831  */
isl_map_get_domain_tuple_id(__isl_keep isl_map * map)832 __isl_give isl_id *isl_map_get_domain_tuple_id(__isl_keep isl_map *map)
833 {
834 	return isl_map_get_tuple_id(map, isl_dim_in);
835 }
836 
837 /* Return the identifier of the range tuple of "map", assuming it has one.
838  */
isl_map_get_range_tuple_id(__isl_keep isl_map * map)839 __isl_give isl_id *isl_map_get_range_tuple_id(__isl_keep isl_map *map)
840 {
841 	return isl_map_get_tuple_id(map, isl_dim_out);
842 }
843 
isl_set_has_tuple_id(__isl_keep isl_set * set)844 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
845 {
846 	return isl_map_has_tuple_id(set, isl_dim_set);
847 }
848 
isl_set_get_tuple_id(__isl_keep isl_set * set)849 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
850 {
851 	return isl_map_get_tuple_id(set, isl_dim_set);
852 }
853 
854 /* Does the set tuple have a name?
855  */
isl_set_has_tuple_name(__isl_keep isl_set * set)856 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
857 {
858 	if (!set)
859 		return isl_bool_error;
860 	return isl_space_has_tuple_name(set->dim, isl_dim_set);
861 }
862 
863 
isl_basic_set_get_tuple_name(__isl_keep isl_basic_set * bset)864 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
865 {
866 	return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
867 }
868 
isl_set_get_tuple_name(__isl_keep isl_set * set)869 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
870 {
871 	return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
872 }
873 
isl_basic_map_get_dim_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)874 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
875 	enum isl_dim_type type, unsigned pos)
876 {
877 	return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
878 }
879 
isl_basic_set_get_dim_name(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned pos)880 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
881 	enum isl_dim_type type, unsigned pos)
882 {
883 	return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
884 }
885 
886 /* Does the given dimension have a name?
887  */
isl_map_has_dim_name(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)888 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
889 	enum isl_dim_type type, unsigned pos)
890 {
891 	if (!map)
892 		return isl_bool_error;
893 	return isl_space_has_dim_name(map->dim, type, pos);
894 }
895 
isl_map_get_dim_name(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)896 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
897 	enum isl_dim_type type, unsigned pos)
898 {
899 	return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
900 }
901 
isl_set_get_dim_name(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)902 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
903 	enum isl_dim_type type, unsigned pos)
904 {
905 	return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
906 }
907 
908 /* Does the given dimension have a name?
909  */
isl_set_has_dim_name(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)910 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
911 	enum isl_dim_type type, unsigned pos)
912 {
913 	if (!set)
914 		return isl_bool_error;
915 	return isl_space_has_dim_name(set->dim, type, pos);
916 }
917 
isl_basic_map_set_dim_name(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,const char * s)918 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
919 	__isl_take isl_basic_map *bmap,
920 	enum isl_dim_type type, unsigned pos, const char *s)
921 {
922 	isl_space *space;
923 
924 	space = isl_basic_map_take_space(bmap);
925 	space = isl_space_set_dim_name(space, type, pos, s);
926 	bmap = isl_basic_map_restore_space(bmap, space);
927 	return isl_basic_map_finalize(bmap);
928 }
929 
isl_map_set_dim_name(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,const char * s)930 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
931 	enum isl_dim_type type, unsigned pos, const char *s)
932 {
933 	int i;
934 	isl_space *space;
935 
936 	map = isl_map_cow(map);
937 	if (!map)
938 		return NULL;
939 
940 	for (i = 0; i < map->n; ++i) {
941 		map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
942 		if (!map->p[i])
943 			goto error;
944 	}
945 
946 	space = isl_map_take_space(map);
947 	space = isl_space_set_dim_name(space, type, pos, s);
948 	map = isl_map_restore_space(map, space);
949 
950 	return map;
951 error:
952 	isl_map_free(map);
953 	return NULL;
954 }
955 
isl_basic_set_set_dim_name(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,const char * s)956 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
957 	__isl_take isl_basic_set *bset,
958 	enum isl_dim_type type, unsigned pos, const char *s)
959 {
960 	return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
961 							type, pos, s));
962 }
963 
isl_set_set_dim_name(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,const char * s)964 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
965 	enum isl_dim_type type, unsigned pos, const char *s)
966 {
967 	return set_from_map(isl_map_set_dim_name(set_to_map(set),
968 							type, pos, s));
969 }
970 
isl_basic_map_has_dim_id(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)971 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
972 	enum isl_dim_type type, unsigned pos)
973 {
974 	if (!bmap)
975 		return isl_bool_error;
976 	return isl_space_has_dim_id(bmap->dim, type, pos);
977 }
978 
isl_basic_set_get_dim_id(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned pos)979 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
980 	enum isl_dim_type type, unsigned pos)
981 {
982 	return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
983 }
984 
isl_map_has_dim_id(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)985 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
986 	enum isl_dim_type type, unsigned pos)
987 {
988 	return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
989 }
990 
isl_map_get_dim_id(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)991 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
992 	enum isl_dim_type type, unsigned pos)
993 {
994 	return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
995 }
996 
isl_set_has_dim_id(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)997 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
998 	enum isl_dim_type type, unsigned pos)
999 {
1000 	return isl_map_has_dim_id(set, type, pos);
1001 }
1002 
isl_set_get_dim_id(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)1003 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
1004 	enum isl_dim_type type, unsigned pos)
1005 {
1006 	return isl_map_get_dim_id(set, type, pos);
1007 }
1008 
isl_map_set_dim_id(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_id * id)1009 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
1010 	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
1011 {
1012 	isl_space *space;
1013 
1014 	space = isl_map_take_space(map);
1015 	space = isl_space_set_dim_id(space, type, pos, id);
1016 	map = isl_map_restore_space(map, space);
1017 
1018 	return isl_map_reset_space(map, isl_map_get_space(map));
1019 }
1020 
isl_set_set_dim_id(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_id * id)1021 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
1022 	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
1023 {
1024 	return isl_map_set_dim_id(set, type, pos, id);
1025 }
1026 
isl_map_find_dim_by_id(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_id * id)1027 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
1028 	__isl_keep isl_id *id)
1029 {
1030 	if (!map)
1031 		return -1;
1032 	return isl_space_find_dim_by_id(map->dim, type, id);
1033 }
1034 
isl_set_find_dim_by_id(__isl_keep isl_set * set,enum isl_dim_type type,__isl_keep isl_id * id)1035 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
1036 	__isl_keep isl_id *id)
1037 {
1038 	return isl_map_find_dim_by_id(set, type, id);
1039 }
1040 
1041 /* Return the position of the dimension of the given type and name
1042  * in "bmap".
1043  * Return -1 if no such dimension can be found.
1044  */
isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,const char * name)1045 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
1046 	enum isl_dim_type type, const char *name)
1047 {
1048 	if (!bmap)
1049 		return -1;
1050 	return isl_space_find_dim_by_name(bmap->dim, type, name);
1051 }
1052 
isl_map_find_dim_by_name(__isl_keep isl_map * map,enum isl_dim_type type,const char * name)1053 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
1054 	const char *name)
1055 {
1056 	if (!map)
1057 		return -1;
1058 	return isl_space_find_dim_by_name(map->dim, type, name);
1059 }
1060 
isl_set_find_dim_by_name(__isl_keep isl_set * set,enum isl_dim_type type,const char * name)1061 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
1062 	const char *name)
1063 {
1064 	return isl_map_find_dim_by_name(set, type, name);
1065 }
1066 
1067 /* Check whether equality i of bset is a pure stride constraint
1068  * on a single dimension, i.e., of the form
1069  *
1070  *	v = k e
1071  *
1072  * with k a constant and e an existentially quantified variable.
1073  */
isl_basic_set_eq_is_stride(__isl_keep isl_basic_set * bset,int i)1074 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
1075 {
1076 	isl_size nparam;
1077 	isl_size d;
1078 	isl_size n_div;
1079 	int pos1;
1080 	int pos2;
1081 
1082 	nparam = isl_basic_set_dim(bset, isl_dim_param);
1083 	d = isl_basic_set_dim(bset, isl_dim_set);
1084 	n_div = isl_basic_set_dim(bset, isl_dim_div);
1085 	if (nparam < 0 || d < 0 || n_div < 0)
1086 		return isl_bool_error;
1087 
1088 	if (!isl_int_is_zero(bset->eq[i][0]))
1089 		return isl_bool_false;
1090 
1091 	if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
1092 		return isl_bool_false;
1093 	pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
1094 	if (pos1 == -1)
1095 		return isl_bool_false;
1096 	if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
1097 					d - pos1 - 1) != -1)
1098 		return isl_bool_false;
1099 
1100 	pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
1101 	if (pos2 == -1)
1102 		return isl_bool_false;
1103 	if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d  + pos2 + 1,
1104 				   n_div - pos2 - 1) != -1)
1105 		return isl_bool_false;
1106 	if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
1107 	    !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
1108 		return isl_bool_false;
1109 
1110 	return isl_bool_true;
1111 }
1112 
1113 /* Reset the user pointer on all identifiers of parameters and tuples
1114  * of the space of "map".
1115  */
isl_map_reset_user(__isl_take isl_map * map)1116 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
1117 {
1118 	isl_space *space;
1119 
1120 	space = isl_map_get_space(map);
1121 	space = isl_space_reset_user(space);
1122 	map = isl_map_reset_space(map, space);
1123 
1124 	return map;
1125 }
1126 
1127 /* Reset the user pointer on all identifiers of parameters and tuples
1128  * of the space of "set".
1129  */
isl_set_reset_user(__isl_take isl_set * set)1130 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
1131 {
1132 	return isl_map_reset_user(set);
1133 }
1134 
isl_basic_map_is_rational(__isl_keep isl_basic_map * bmap)1135 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
1136 {
1137 	if (!bmap)
1138 		return isl_bool_error;
1139 	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
1140 }
1141 
1142 /* Has "map" been marked as a rational map?
1143  * In particular, have all basic maps in "map" been marked this way?
1144  * An empty map is not considered to be rational.
1145  * Maps where only some of the basic maps are marked rational
1146  * are not allowed.
1147  */
isl_map_is_rational(__isl_keep isl_map * map)1148 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
1149 {
1150 	int i;
1151 	isl_bool rational;
1152 
1153 	if (!map)
1154 		return isl_bool_error;
1155 	if (map->n == 0)
1156 		return isl_bool_false;
1157 	rational = isl_basic_map_is_rational(map->p[0]);
1158 	if (rational < 0)
1159 		return rational;
1160 	for (i = 1; i < map->n; ++i) {
1161 		isl_bool rational_i;
1162 
1163 		rational_i = isl_basic_map_is_rational(map->p[i]);
1164 		if (rational_i < 0)
1165 			return rational_i;
1166 		if (rational != rational_i)
1167 			isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1168 				"mixed rational and integer basic maps "
1169 				"not supported", return isl_bool_error);
1170 	}
1171 
1172 	return rational;
1173 }
1174 
1175 /* Has "set" been marked as a rational set?
1176  * In particular, have all basic set in "set" been marked this way?
1177  * An empty set is not considered to be rational.
1178  * Sets where only some of the basic sets are marked rational
1179  * are not allowed.
1180  */
isl_set_is_rational(__isl_keep isl_set * set)1181 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1182 {
1183 	return isl_map_is_rational(set);
1184 }
1185 
isl_basic_set_is_rational(__isl_keep isl_basic_set * bset)1186 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1187 {
1188 	return isl_basic_map_is_rational(bset);
1189 }
1190 
1191 /* Does "bmap" contain any rational points?
1192  *
1193  * If "bmap" has an equality for each dimension, equating the dimension
1194  * to an integer constant, then it has no rational points, even if it
1195  * is marked as rational.
1196  */
isl_basic_map_has_rational(__isl_keep isl_basic_map * bmap)1197 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1198 {
1199 	isl_bool has_rational = isl_bool_true;
1200 	isl_size total;
1201 
1202 	if (!bmap)
1203 		return isl_bool_error;
1204 	if (isl_basic_map_plain_is_empty(bmap))
1205 		return isl_bool_false;
1206 	if (!isl_basic_map_is_rational(bmap))
1207 		return isl_bool_false;
1208 	bmap = isl_basic_map_copy(bmap);
1209 	bmap = isl_basic_map_implicit_equalities(bmap);
1210 	total = isl_basic_map_dim(bmap, isl_dim_all);
1211 	if (total < 0)
1212 		return isl_bool_error;
1213 	if (bmap->n_eq == total) {
1214 		int i, j;
1215 		for (i = 0; i < bmap->n_eq; ++i) {
1216 			j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1217 			if (j < 0)
1218 				break;
1219 			if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1220 			    !isl_int_is_negone(bmap->eq[i][1 + j]))
1221 				break;
1222 			j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1223 						    total - j - 1);
1224 			if (j >= 0)
1225 				break;
1226 		}
1227 		if (i == bmap->n_eq)
1228 			has_rational = isl_bool_false;
1229 	}
1230 	isl_basic_map_free(bmap);
1231 
1232 	return has_rational;
1233 }
1234 
1235 /* Does "map" contain any rational points?
1236  */
isl_map_has_rational(__isl_keep isl_map * map)1237 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1238 {
1239 	int i;
1240 	isl_bool has_rational;
1241 
1242 	if (!map)
1243 		return isl_bool_error;
1244 	for (i = 0; i < map->n; ++i) {
1245 		has_rational = isl_basic_map_has_rational(map->p[i]);
1246 		if (has_rational < 0 || has_rational)
1247 			return has_rational;
1248 	}
1249 	return isl_bool_false;
1250 }
1251 
1252 /* Does "set" contain any rational points?
1253  */
isl_set_has_rational(__isl_keep isl_set * set)1254 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1255 {
1256 	return isl_map_has_rational(set);
1257 }
1258 
1259 /* Is this basic set a parameter domain?
1260  */
isl_basic_set_is_params(__isl_keep isl_basic_set * bset)1261 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1262 {
1263 	if (!bset)
1264 		return isl_bool_error;
1265 	return isl_space_is_params(bset->dim);
1266 }
1267 
1268 /* Is this set a parameter domain?
1269  */
isl_set_is_params(__isl_keep isl_set * set)1270 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1271 {
1272 	if (!set)
1273 		return isl_bool_error;
1274 	return isl_space_is_params(set->dim);
1275 }
1276 
1277 /* Is this map actually a parameter domain?
1278  * Users should never call this function.  Outside of isl,
1279  * a map can never be a parameter domain.
1280  */
isl_map_is_params(__isl_keep isl_map * map)1281 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1282 {
1283 	if (!map)
1284 		return isl_bool_error;
1285 	return isl_space_is_params(map->dim);
1286 }
1287 
basic_map_init(isl_ctx * ctx,__isl_take isl_basic_map * bmap,unsigned extra,unsigned n_eq,unsigned n_ineq)1288 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1289 	__isl_take isl_basic_map *bmap, unsigned extra,
1290 	unsigned n_eq, unsigned n_ineq)
1291 {
1292 	int i;
1293 	isl_space *space = isl_basic_map_peek_space(bmap);
1294 	isl_size n_var = isl_space_dim(space, isl_dim_all);
1295 	size_t row_size = 1 + n_var + extra;
1296 
1297 	bmap->ctx = ctx;
1298 	isl_ctx_ref(ctx);
1299 
1300 	if (n_var < 0)
1301 		return isl_basic_map_free(bmap);
1302 
1303 	bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1304 	if (isl_blk_is_error(bmap->block))
1305 		goto error;
1306 
1307 	bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1308 	if ((n_ineq + n_eq) && !bmap->ineq)
1309 		goto error;
1310 
1311 	if (extra == 0) {
1312 		bmap->block2 = isl_blk_empty();
1313 		bmap->div = NULL;
1314 	} else {
1315 		bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1316 		if (isl_blk_is_error(bmap->block2))
1317 			goto error;
1318 
1319 		bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1320 		if (!bmap->div)
1321 			goto error;
1322 	}
1323 
1324 	for (i = 0; i < n_ineq + n_eq; ++i)
1325 		bmap->ineq[i] = bmap->block.data + i * row_size;
1326 
1327 	for (i = 0; i < extra; ++i)
1328 		bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1329 
1330 	bmap->ref = 1;
1331 	bmap->flags = 0;
1332 	bmap->c_size = n_eq + n_ineq;
1333 	bmap->eq = bmap->ineq + n_ineq;
1334 	bmap->extra = extra;
1335 	bmap->n_eq = 0;
1336 	bmap->n_ineq = 0;
1337 	bmap->n_div = 0;
1338 	bmap->sample = NULL;
1339 
1340 	return bmap;
1341 error:
1342 	isl_basic_map_free(bmap);
1343 	return NULL;
1344 }
1345 
isl_basic_set_alloc(isl_ctx * ctx,unsigned nparam,unsigned dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1346 __isl_give isl_basic_set *isl_basic_set_alloc(isl_ctx *ctx,
1347 		unsigned nparam, unsigned dim, unsigned extra,
1348 		unsigned n_eq, unsigned n_ineq)
1349 {
1350 	struct isl_basic_map *bmap;
1351 	isl_space *space;
1352 
1353 	space = isl_space_set_alloc(ctx, nparam, dim);
1354 	if (!space)
1355 		return NULL;
1356 
1357 	bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1358 	return bset_from_bmap(bmap);
1359 }
1360 
isl_basic_set_alloc_space(__isl_take isl_space * space,unsigned extra,unsigned n_eq,unsigned n_ineq)1361 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *space,
1362 		unsigned extra, unsigned n_eq, unsigned n_ineq)
1363 {
1364 	struct isl_basic_map *bmap;
1365 	if (!space)
1366 		return NULL;
1367 	isl_assert(space->ctx, space->n_in == 0, goto error);
1368 	bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1369 	return bset_from_bmap(bmap);
1370 error:
1371 	isl_space_free(space);
1372 	return NULL;
1373 }
1374 
isl_basic_map_alloc_space(__isl_take isl_space * space,unsigned extra,unsigned n_eq,unsigned n_ineq)1375 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1376 		unsigned extra, unsigned n_eq, unsigned n_ineq)
1377 {
1378 	struct isl_basic_map *bmap;
1379 
1380 	if (!space)
1381 		return NULL;
1382 	bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1383 	if (!bmap)
1384 		goto error;
1385 	bmap->dim = space;
1386 
1387 	return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1388 error:
1389 	isl_space_free(space);
1390 	return NULL;
1391 }
1392 
isl_basic_map_alloc(isl_ctx * ctx,unsigned nparam,unsigned in,unsigned out,unsigned extra,unsigned n_eq,unsigned n_ineq)1393 __isl_give isl_basic_map *isl_basic_map_alloc(isl_ctx *ctx,
1394 		unsigned nparam, unsigned in, unsigned out, unsigned extra,
1395 		unsigned n_eq, unsigned n_ineq)
1396 {
1397 	struct isl_basic_map *bmap;
1398 	isl_space *space;
1399 
1400 	space = isl_space_alloc(ctx, nparam, in, out);
1401 	if (!space)
1402 		return NULL;
1403 
1404 	bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1405 	return bmap;
1406 }
1407 
dup_constraints(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)1408 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1409 	__isl_keep isl_basic_map *src)
1410 {
1411 	int i;
1412 	isl_size total = isl_basic_map_dim(src, isl_dim_all);
1413 
1414 	if (!dst || total < 0)
1415 		return isl_basic_map_free(dst);
1416 
1417 	for (i = 0; i < src->n_eq; ++i) {
1418 		int j = isl_basic_map_alloc_equality(dst);
1419 		if (j < 0)
1420 			return isl_basic_map_free(dst);
1421 		isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1422 	}
1423 
1424 	for (i = 0; i < src->n_ineq; ++i) {
1425 		int j = isl_basic_map_alloc_inequality(dst);
1426 		if (j < 0)
1427 			return isl_basic_map_free(dst);
1428 		isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1429 	}
1430 
1431 	for (i = 0; i < src->n_div; ++i) {
1432 		int j = isl_basic_map_alloc_div(dst);
1433 		if (j < 0)
1434 			return isl_basic_map_free(dst);
1435 		isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1436 	}
1437 	ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1438 	return dst;
1439 }
1440 
isl_basic_map_dup(__isl_keep isl_basic_map * bmap)1441 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1442 {
1443 	struct isl_basic_map *dup;
1444 
1445 	if (!bmap)
1446 		return NULL;
1447 	dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1448 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
1449 	dup = dup_constraints(dup, bmap);
1450 	if (!dup)
1451 		return NULL;
1452 	dup->flags = bmap->flags;
1453 	dup->sample = isl_vec_copy(bmap->sample);
1454 	return dup;
1455 }
1456 
isl_basic_set_dup(__isl_keep isl_basic_set * bset)1457 __isl_give isl_basic_set *isl_basic_set_dup(__isl_keep isl_basic_set *bset)
1458 {
1459 	struct isl_basic_map *dup;
1460 
1461 	dup = isl_basic_map_dup(bset_to_bmap(bset));
1462 	return bset_from_bmap(dup);
1463 }
1464 
isl_basic_set_copy(__isl_keep isl_basic_set * bset)1465 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1466 {
1467 	if (!bset)
1468 		return NULL;
1469 
1470 	if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1471 		bset->ref++;
1472 		return bset;
1473 	}
1474 	return isl_basic_set_dup(bset);
1475 }
1476 
isl_set_copy(__isl_keep isl_set * set)1477 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1478 {
1479 	if (!set)
1480 		return NULL;
1481 
1482 	set->ref++;
1483 	return set;
1484 }
1485 
isl_basic_map_copy(__isl_keep isl_basic_map * bmap)1486 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1487 {
1488 	if (!bmap)
1489 		return NULL;
1490 
1491 	if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1492 		bmap->ref++;
1493 		return bmap;
1494 	}
1495 	bmap = isl_basic_map_dup(bmap);
1496 	if (bmap)
1497 		ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1498 	return bmap;
1499 }
1500 
isl_map_copy(__isl_keep isl_map * map)1501 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1502 {
1503 	if (!map)
1504 		return NULL;
1505 
1506 	map->ref++;
1507 	return map;
1508 }
1509 
isl_basic_map_free(__isl_take isl_basic_map * bmap)1510 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1511 {
1512 	if (!bmap)
1513 		return NULL;
1514 
1515 	if (--bmap->ref > 0)
1516 		return NULL;
1517 
1518 	isl_ctx_deref(bmap->ctx);
1519 	free(bmap->div);
1520 	isl_blk_free(bmap->ctx, bmap->block2);
1521 	free(bmap->ineq);
1522 	isl_blk_free(bmap->ctx, bmap->block);
1523 	isl_vec_free(bmap->sample);
1524 	isl_space_free(bmap->dim);
1525 	free(bmap);
1526 
1527 	return NULL;
1528 }
1529 
isl_basic_set_free(__isl_take isl_basic_set * bset)1530 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1531 {
1532 	return isl_basic_map_free(bset_to_bmap(bset));
1533 }
1534 
room_for_con(__isl_keep isl_basic_map * bmap,unsigned n)1535 static int room_for_con(__isl_keep isl_basic_map *bmap, unsigned n)
1536 {
1537 	return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1538 }
1539 
1540 /* Check that "bset" does not involve any parameters.
1541  */
isl_basic_set_check_no_params(__isl_keep isl_basic_set * bset)1542 isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1543 {
1544 	isl_size nparam;
1545 
1546 	nparam = isl_basic_set_dim(bset, isl_dim_param);
1547 	if (nparam < 0)
1548 		return isl_stat_error;
1549 	if (nparam != 0)
1550 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1551 			"basic set should not have any parameters",
1552 			return isl_stat_error);
1553 	return isl_stat_ok;
1554 }
1555 
1556 /* Check that "bset" does not involve any local variables.
1557  */
isl_basic_set_check_no_locals(__isl_keep isl_basic_set * bset)1558 isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1559 {
1560 	isl_size n_div;
1561 
1562 	n_div = isl_basic_set_dim(bset, isl_dim_div);
1563 	if (n_div < 0)
1564 		return isl_stat_error;
1565 	if (n_div != 0)
1566 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1567 			"basic set should not have any local variables",
1568 			return isl_stat_error);
1569 	return isl_stat_ok;
1570 }
1571 
1572 #undef TYPE
1573 #define TYPE isl_map
1574 
1575 #include "isl_check_named_params_templ.c"
1576 
1577 #undef TYPE
1578 #define TYPE isl_basic_map
1579 
1580 static
1581 #include "isl_check_named_params_templ.c"
1582 
1583 /* Check that "bmap1" and "bmap2" have the same parameters,
1584  * reporting an error if they do not.
1585  */
isl_basic_map_check_equal_params(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)1586 static isl_stat isl_basic_map_check_equal_params(
1587 	__isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1588 {
1589 	isl_bool match;
1590 
1591 	match = isl_basic_map_has_equal_params(bmap1, bmap2);
1592 	if (match < 0)
1593 		return isl_stat_error;
1594 	if (!match)
1595 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1596 			"parameters don't match", return isl_stat_error);
1597 	return isl_stat_ok;
1598 }
1599 
1600 #undef TYPE
1601 #define TYPE	isl_map
1602 
1603 #include "isl_align_params_bin_templ.c"
1604 
1605 #undef SUFFIX
1606 #define SUFFIX	set
1607 #undef ARG1
1608 #define ARG1	isl_map
1609 #undef ARG2
1610 #define ARG2	isl_set
1611 
1612 #include "isl_align_params_templ.c"
1613 
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))1614 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1615 	__isl_keep isl_map *map2,
1616 	isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1617 {
1618 	isl_bool r;
1619 
1620 	if (!map1 || !map2)
1621 		return isl_bool_error;
1622 	if (isl_map_has_equal_params(map1, map2))
1623 		return fn(map1, map2);
1624 	if (isl_map_check_named_params(map1) < 0)
1625 		return isl_bool_error;
1626 	if (isl_map_check_named_params(map2) < 0)
1627 		return isl_bool_error;
1628 	map1 = isl_map_copy(map1);
1629 	map2 = isl_map_copy(map2);
1630 	map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1631 	map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1632 	r = fn(map1, map2);
1633 	isl_map_free(map1);
1634 	isl_map_free(map2);
1635 	return r;
1636 }
1637 
isl_basic_map_alloc_equality(__isl_keep isl_basic_map * bmap)1638 int isl_basic_map_alloc_equality(__isl_keep isl_basic_map *bmap)
1639 {
1640 	isl_size total;
1641 	struct isl_ctx *ctx;
1642 
1643 	total = isl_basic_map_dim(bmap, isl_dim_all);
1644 	if (total < 0)
1645 		return -1;
1646 	ctx = bmap->ctx;
1647 	isl_assert(ctx, room_for_con(bmap, 1), return -1);
1648 	isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1649 			return -1);
1650 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1651 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1652 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1653 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1654 	if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1655 		isl_int *t;
1656 		int j = isl_basic_map_alloc_inequality(bmap);
1657 		if (j < 0)
1658 			return -1;
1659 		t = bmap->ineq[j];
1660 		bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1661 		bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1662 		bmap->eq[-1] = t;
1663 		bmap->n_eq++;
1664 		bmap->n_ineq--;
1665 		bmap->eq--;
1666 		return 0;
1667 	}
1668 	isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + total,
1669 		      bmap->extra - bmap->n_div);
1670 	return bmap->n_eq++;
1671 }
1672 
isl_basic_set_alloc_equality(__isl_keep isl_basic_set * bset)1673 int isl_basic_set_alloc_equality(__isl_keep isl_basic_set *bset)
1674 {
1675 	return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1676 }
1677 
isl_basic_map_free_equality(__isl_take isl_basic_map * bmap,unsigned n)1678 __isl_give isl_basic_map *isl_basic_map_free_equality(
1679 	__isl_take isl_basic_map *bmap, unsigned n)
1680 {
1681 	if (!bmap)
1682 		return NULL;
1683 	if (n > bmap->n_eq)
1684 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1685 			"invalid number of equalities",
1686 			isl_basic_map_free(bmap));
1687 	bmap->n_eq -= n;
1688 	return bmap;
1689 }
1690 
isl_basic_set_free_equality(__isl_take isl_basic_set * bset,unsigned n)1691 __isl_give isl_basic_set *isl_basic_set_free_equality(
1692 	__isl_take isl_basic_set *bset, unsigned n)
1693 {
1694 	return bset_from_bmap(isl_basic_map_free_equality(bset_to_bmap(bset),
1695 							    n));
1696 }
1697 
1698 /* Drop the equality constraint at position "pos",
1699  * preserving the order of the other equality constraints.
1700  */
isl_basic_map_drop_equality(__isl_keep isl_basic_map * bmap,unsigned pos)1701 int isl_basic_map_drop_equality(__isl_keep isl_basic_map *bmap, unsigned pos)
1702 {
1703 	isl_int *t;
1704 	int r;
1705 
1706 	if (!bmap)
1707 		return -1;
1708 	isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1709 
1710 	t = bmap->eq[pos];
1711 	bmap->n_eq--;
1712 	for (r = pos; r < bmap->n_eq; ++r)
1713 		bmap->eq[r] = bmap->eq[r + 1];
1714 	bmap->eq[bmap->n_eq] = t;
1715 
1716 	return 0;
1717 }
1718 
1719 /* Turn inequality "pos" of "bmap" into an equality.
1720  *
1721  * In particular, we move the inequality in front of the equalities
1722  * and move the last inequality in the position of the moved inequality.
1723  * Note that isl_tab_make_equalities_explicit depends on this particular
1724  * change in the ordering of the constraints.
1725  */
isl_basic_map_inequality_to_equality(__isl_keep isl_basic_map * bmap,unsigned pos)1726 void isl_basic_map_inequality_to_equality(
1727 		__isl_keep isl_basic_map *bmap, unsigned pos)
1728 {
1729 	isl_int *t;
1730 
1731 	t = bmap->ineq[pos];
1732 	bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1733 	bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1734 	bmap->eq[-1] = t;
1735 	bmap->n_eq++;
1736 	bmap->n_ineq--;
1737 	bmap->eq--;
1738 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1739 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1740 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1741 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1742 }
1743 
room_for_ineq(__isl_keep isl_basic_map * bmap,unsigned n)1744 static int room_for_ineq(__isl_keep isl_basic_map *bmap, unsigned n)
1745 {
1746 	return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1747 }
1748 
isl_basic_map_alloc_inequality(__isl_keep isl_basic_map * bmap)1749 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1750 {
1751 	isl_size total;
1752 	struct isl_ctx *ctx;
1753 
1754 	total = isl_basic_map_dim(bmap, isl_dim_all);
1755 	if (total < 0)
1756 		return -1;
1757 	ctx = bmap->ctx;
1758 	isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1759 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1760 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1761 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1762 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1763 	isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1 + total,
1764 		      bmap->extra - bmap->n_div);
1765 	return bmap->n_ineq++;
1766 }
1767 
isl_basic_set_alloc_inequality(__isl_keep isl_basic_set * bset)1768 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1769 {
1770 	return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1771 }
1772 
isl_basic_map_free_inequality(__isl_take isl_basic_map * bmap,unsigned n)1773 __isl_give isl_basic_map *isl_basic_map_free_inequality(
1774 	__isl_take isl_basic_map *bmap, unsigned n)
1775 {
1776 	if (!bmap)
1777 		return NULL;
1778 	if (n > bmap->n_ineq)
1779 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1780 			"invalid number of inequalities",
1781 			return isl_basic_map_free(bmap));
1782 	bmap->n_ineq -= n;
1783 	return bmap;
1784 }
1785 
isl_basic_set_free_inequality(__isl_take isl_basic_set * bset,unsigned n)1786 __isl_give isl_basic_set *isl_basic_set_free_inequality(
1787 	__isl_take isl_basic_set *bset, unsigned n)
1788 {
1789 	return bset_from_bmap(isl_basic_map_free_inequality(bset_to_bmap(bset),
1790 							    n));
1791 }
1792 
isl_basic_map_drop_inequality(__isl_keep isl_basic_map * bmap,unsigned pos)1793 int isl_basic_map_drop_inequality(__isl_keep isl_basic_map *bmap, unsigned pos)
1794 {
1795 	isl_int *t;
1796 	if (!bmap)
1797 		return -1;
1798 	isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1799 
1800 	if (pos != bmap->n_ineq - 1) {
1801 		t = bmap->ineq[pos];
1802 		bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1803 		bmap->ineq[bmap->n_ineq - 1] = t;
1804 		ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1805 	}
1806 	bmap->n_ineq--;
1807 	return 0;
1808 }
1809 
isl_basic_set_drop_inequality(__isl_keep isl_basic_set * bset,unsigned pos)1810 int isl_basic_set_drop_inequality(__isl_keep isl_basic_set *bset, unsigned pos)
1811 {
1812 	return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1813 }
1814 
isl_basic_map_add_eq(__isl_take isl_basic_map * bmap,isl_int * eq)1815 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1816 	isl_int *eq)
1817 {
1818 	isl_bool empty;
1819 	isl_size total;
1820 	int k;
1821 
1822 	empty = isl_basic_map_plain_is_empty(bmap);
1823 	if (empty < 0)
1824 		return isl_basic_map_free(bmap);
1825 	if (empty)
1826 		return bmap;
1827 
1828 	bmap = isl_basic_map_cow(bmap);
1829 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1830 	total = isl_basic_map_dim(bmap, isl_dim_all);
1831 	if (total < 0)
1832 		return isl_basic_map_free(bmap);
1833 	k = isl_basic_map_alloc_equality(bmap);
1834 	if (k < 0)
1835 		goto error;
1836 	isl_seq_cpy(bmap->eq[k], eq, 1 + total);
1837 	return bmap;
1838 error:
1839 	isl_basic_map_free(bmap);
1840 	return NULL;
1841 }
1842 
isl_basic_set_add_eq(__isl_take isl_basic_set * bset,isl_int * eq)1843 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1844 	isl_int *eq)
1845 {
1846 	return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1847 }
1848 
isl_basic_map_add_ineq(__isl_take isl_basic_map * bmap,isl_int * ineq)1849 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1850 	isl_int *ineq)
1851 {
1852 	isl_size total;
1853 	int k;
1854 
1855 	bmap = isl_basic_map_cow(bmap);
1856 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1857 	total = isl_basic_map_dim(bmap, isl_dim_all);
1858 	if (total < 0)
1859 		return isl_basic_map_free(bmap);
1860 	k = isl_basic_map_alloc_inequality(bmap);
1861 	if (k < 0)
1862 		goto error;
1863 	isl_seq_cpy(bmap->ineq[k], ineq, 1 + total);
1864 	return bmap;
1865 error:
1866 	isl_basic_map_free(bmap);
1867 	return NULL;
1868 }
1869 
isl_basic_set_add_ineq(__isl_take isl_basic_set * bset,isl_int * ineq)1870 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1871 	isl_int *ineq)
1872 {
1873 	return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1874 }
1875 
isl_basic_map_alloc_div(__isl_keep isl_basic_map * bmap)1876 int isl_basic_map_alloc_div(__isl_keep isl_basic_map *bmap)
1877 {
1878 	isl_size total;
1879 
1880 	total = isl_basic_map_dim(bmap, isl_dim_all);
1881 	if (total < 0)
1882 		return -1;
1883 	isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1884 	isl_seq_clr(bmap->div[bmap->n_div] + 1 + 1 + total,
1885 		      bmap->extra - bmap->n_div);
1886 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1887 	return bmap->n_div++;
1888 }
1889 
isl_basic_set_alloc_div(__isl_keep isl_basic_set * bset)1890 int isl_basic_set_alloc_div(__isl_keep isl_basic_set *bset)
1891 {
1892 	return isl_basic_map_alloc_div(bset_to_bmap(bset));
1893 }
1894 
1895 #undef TYPE
1896 #define TYPE	isl_basic_map
1897 #include "check_type_range_templ.c"
1898 
1899 /* Check that there are "n" dimensions of type "type" starting at "first"
1900  * in "bset".
1901  */
isl_basic_set_check_range(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)1902 isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1903 	enum isl_dim_type type, unsigned first, unsigned n)
1904 {
1905 	return isl_basic_map_check_range(bset_to_bmap(bset),
1906 					type, first, n);
1907 }
1908 
1909 /* Insert an extra integer division, prescribed by "div", to "bmap"
1910  * at (integer division) position "pos".
1911  *
1912  * The integer division is first added at the end and then moved
1913  * into the right position.
1914  */
isl_basic_map_insert_div(__isl_take isl_basic_map * bmap,int pos,__isl_keep isl_vec * div)1915 __isl_give isl_basic_map *isl_basic_map_insert_div(
1916 	__isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1917 {
1918 	int i, k;
1919 	isl_size total;
1920 
1921 	bmap = isl_basic_map_cow(bmap);
1922 	total = isl_basic_map_dim(bmap, isl_dim_all);
1923 	if (total < 0 || !div)
1924 		return isl_basic_map_free(bmap);
1925 
1926 	if (div->size != 1 + 1 + total)
1927 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1928 			"unexpected size", return isl_basic_map_free(bmap));
1929 	if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1930 		return isl_basic_map_free(bmap);
1931 
1932 	bmap = isl_basic_map_extend(bmap, 1, 0, 2);
1933 	k = isl_basic_map_alloc_div(bmap);
1934 	if (k < 0)
1935 		return isl_basic_map_free(bmap);
1936 	isl_seq_cpy(bmap->div[k], div->el, div->size);
1937 	isl_int_set_si(bmap->div[k][div->size], 0);
1938 
1939 	for (i = k; i > pos; --i)
1940 		bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1941 
1942 	return bmap;
1943 }
1944 
isl_basic_map_free_div(__isl_keep isl_basic_map * bmap,unsigned n)1945 isl_stat isl_basic_map_free_div(__isl_keep isl_basic_map *bmap, unsigned n)
1946 {
1947 	if (!bmap)
1948 		return isl_stat_error;
1949 	isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1950 	bmap->n_div -= n;
1951 	return isl_stat_ok;
1952 }
1953 
add_constraints(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2,unsigned i_pos,unsigned o_pos)1954 static __isl_give isl_basic_map *add_constraints(
1955 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1956 	unsigned i_pos, unsigned o_pos)
1957 {
1958 	isl_size total, n_param, n_in, n_out, n_div;
1959 	unsigned o_in, o_out;
1960 	isl_ctx *ctx;
1961 	isl_space *space;
1962 	struct isl_dim_map *dim_map;
1963 
1964 	space = isl_basic_map_peek_space(bmap2);
1965 	if (!bmap1 || !space)
1966 		goto error;
1967 
1968 	total = isl_basic_map_dim(bmap1, isl_dim_all);
1969 	n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1970 	n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1971 	o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1972 	n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1973 	o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1974 	n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1975 	if (total < 0 || n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
1976 		goto error;
1977 	ctx = isl_basic_map_get_ctx(bmap1);
1978 	dim_map = isl_dim_map_alloc(ctx, total + n_div);
1979 	isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1980 	isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1981 	isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1982 	isl_dim_map_div(dim_map, bmap2, total);
1983 
1984 	return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1985 error:
1986 	isl_basic_map_free(bmap1);
1987 	isl_basic_map_free(bmap2);
1988 	return NULL;
1989 }
1990 
isl_basic_map_extend(__isl_take isl_basic_map * base,unsigned extra,unsigned n_eq,unsigned n_ineq)1991 __isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
1992 	unsigned extra, unsigned n_eq, unsigned n_ineq)
1993 {
1994 	isl_space *space;
1995 	struct isl_basic_map *ext;
1996 	unsigned flags;
1997 	int dims_ok;
1998 
1999 	if (!base)
2000 		goto error;
2001 
2002 	dims_ok = base->extra >= base->n_div + extra;
2003 
2004 	if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
2005 		       room_for_ineq(base, n_ineq))
2006 		return base;
2007 
2008 	extra += base->extra;
2009 	n_eq += base->n_eq;
2010 	n_ineq += base->n_ineq;
2011 
2012 	space = isl_basic_map_get_space(base);
2013 	ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
2014 	if (!ext)
2015 		goto error;
2016 
2017 	if (dims_ok)
2018 		ext->sample = isl_vec_copy(base->sample);
2019 	flags = base->flags;
2020 	ext = add_constraints(ext, base, 0, 0);
2021 	if (ext) {
2022 		ext->flags = flags;
2023 		ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
2024 	}
2025 
2026 	return ext;
2027 
2028 error:
2029 	isl_basic_map_free(base);
2030 	return NULL;
2031 }
2032 
isl_basic_set_extend(__isl_take isl_basic_set * base,unsigned extra,unsigned n_eq,unsigned n_ineq)2033 __isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,
2034 	unsigned extra, unsigned n_eq, unsigned n_ineq)
2035 {
2036 	return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
2037 						    extra, n_eq, n_ineq));
2038 }
2039 
isl_basic_map_extend_constraints(__isl_take isl_basic_map * base,unsigned n_eq,unsigned n_ineq)2040 __isl_give isl_basic_map *isl_basic_map_extend_constraints(
2041 	__isl_take isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
2042 {
2043 	return isl_basic_map_extend(base, 0, n_eq, n_ineq);
2044 }
2045 
isl_basic_set_extend_constraints(__isl_take isl_basic_set * base,unsigned n_eq,unsigned n_ineq)2046 __isl_give isl_basic_set *isl_basic_set_extend_constraints(
2047 	__isl_take isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
2048 {
2049 	isl_basic_map *bmap = bset_to_bmap(base);
2050 	bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
2051 	return bset_from_bmap(bmap);
2052 }
2053 
isl_basic_set_cow(__isl_take isl_basic_set * bset)2054 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
2055 {
2056 	return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
2057 }
2058 
isl_basic_map_cow(__isl_take isl_basic_map * bmap)2059 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
2060 {
2061 	if (!bmap)
2062 		return NULL;
2063 
2064 	if (bmap->ref > 1) {
2065 		bmap->ref--;
2066 		bmap = isl_basic_map_dup(bmap);
2067 	}
2068 	if (bmap) {
2069 		ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
2070 		ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
2071 	}
2072 	return bmap;
2073 }
2074 
2075 /* Clear all cached information in "map", either because it is about
2076  * to be modified or because it is being freed.
2077  * Always return the same pointer that is passed in.
2078  * This is needed for the use in isl_map_free.
2079  */
clear_caches(__isl_take isl_map * map)2080 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
2081 {
2082 	isl_basic_map_free(map->cached_simple_hull[0]);
2083 	isl_basic_map_free(map->cached_simple_hull[1]);
2084 	map->cached_simple_hull[0] = NULL;
2085 	map->cached_simple_hull[1] = NULL;
2086 	return map;
2087 }
2088 
isl_set_cow(__isl_take isl_set * set)2089 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
2090 {
2091 	return isl_map_cow(set);
2092 }
2093 
2094 /* Return an isl_map that is equal to "map" and that has only
2095  * a single reference.
2096  *
2097  * If the original input already has only one reference, then
2098  * simply return it, but clear all cached information, since
2099  * it may be rendered invalid by the operations that will be
2100  * performed on the result.
2101  *
2102  * Otherwise, create a duplicate (without any cached information).
2103  */
isl_map_cow(__isl_take isl_map * map)2104 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
2105 {
2106 	if (!map)
2107 		return NULL;
2108 
2109 	if (map->ref == 1)
2110 		return clear_caches(map);
2111 	map->ref--;
2112 	return isl_map_dup(map);
2113 }
2114 
swap_vars(struct isl_blk blk,isl_int * a,unsigned a_len,unsigned b_len)2115 static void swap_vars(struct isl_blk blk, isl_int *a,
2116 			unsigned a_len, unsigned b_len)
2117 {
2118 	isl_seq_cpy(blk.data, a+a_len, b_len);
2119 	isl_seq_cpy(blk.data+b_len, a, a_len);
2120 	isl_seq_cpy(a, blk.data, b_len+a_len);
2121 }
2122 
isl_basic_map_swap_vars(__isl_take isl_basic_map * bmap,unsigned pos,unsigned n1,unsigned n2)2123 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
2124 	__isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
2125 {
2126 	int i;
2127 	struct isl_blk blk;
2128 
2129 	if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
2130 		goto error;
2131 
2132 	if (n1 == 0 || n2 == 0)
2133 		return bmap;
2134 
2135 	bmap = isl_basic_map_cow(bmap);
2136 	if (!bmap)
2137 		return NULL;
2138 
2139 	blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2140 	if (isl_blk_is_error(blk))
2141 		goto error;
2142 
2143 	for (i = 0; i < bmap->n_eq; ++i)
2144 		swap_vars(blk,
2145 			  bmap->eq[i] + pos, n1, n2);
2146 
2147 	for (i = 0; i < bmap->n_ineq; ++i)
2148 		swap_vars(blk,
2149 			  bmap->ineq[i] + pos, n1, n2);
2150 
2151 	for (i = 0; i < bmap->n_div; ++i)
2152 		swap_vars(blk,
2153 			  bmap->div[i]+1 + pos, n1, n2);
2154 
2155 	isl_blk_free(bmap->ctx, blk);
2156 
2157 	ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2158 	bmap = isl_basic_map_gauss(bmap, NULL);
2159 	return isl_basic_map_finalize(bmap);
2160 error:
2161 	isl_basic_map_free(bmap);
2162 	return NULL;
2163 }
2164 
2165 /* The given basic map has turned out to be empty.
2166  * Explicitly mark it as such and change the representation
2167  * to a canonical representation of the empty basic map.
2168  * Since the basic map has conflicting constraints,
2169  * it must have at least one constraint, except perhaps
2170  * if it was already explicitly marked as being empty.
2171  * Do nothing in the latter case, i.e., if it has been marked empty and
2172  * has no constraints.
2173  */
isl_basic_map_set_to_empty(__isl_take isl_basic_map * bmap)2174 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2175 	__isl_take isl_basic_map *bmap)
2176 {
2177 	int i = 0;
2178 	isl_bool empty;
2179 	isl_size n;
2180 	isl_size total;
2181 
2182 	n = isl_basic_map_n_constraint(bmap);
2183 	empty = isl_basic_map_plain_is_empty(bmap);
2184 	if (n < 0 || empty < 0)
2185 		return isl_basic_map_free(bmap);
2186 	if (n == 0 && empty)
2187 		return bmap;
2188 	total = isl_basic_map_dim(bmap, isl_dim_all);
2189 	if (total < 0)
2190 		return isl_basic_map_free(bmap);
2191 	if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2192 		return isl_basic_map_free(bmap);
2193 	bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2194 	if (!bmap)
2195 		return NULL;
2196 	if (bmap->n_eq > 0) {
2197 		bmap = isl_basic_map_free_equality(bmap, bmap->n_eq - 1);
2198 		if (!bmap)
2199 			return NULL;
2200 	} else {
2201 		i = isl_basic_map_alloc_equality(bmap);
2202 		if (i < 0)
2203 			goto error;
2204 	}
2205 	isl_int_set_si(bmap->eq[i][0], 1);
2206 	isl_seq_clr(bmap->eq[i]+1, total);
2207 	ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2208 	isl_vec_free(bmap->sample);
2209 	bmap->sample = NULL;
2210 	return isl_basic_map_finalize(bmap);
2211 error:
2212 	isl_basic_map_free(bmap);
2213 	return NULL;
2214 }
2215 
isl_basic_set_set_to_empty(__isl_take isl_basic_set * bset)2216 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2217 	__isl_take isl_basic_set *bset)
2218 {
2219 	return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2220 }
2221 
isl_basic_map_set_rational(__isl_take isl_basic_map * bmap)2222 __isl_give isl_basic_map *isl_basic_map_set_rational(
2223 	__isl_take isl_basic_map *bmap)
2224 {
2225 	if (!bmap)
2226 		return NULL;
2227 
2228 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2229 		return bmap;
2230 
2231 	bmap = isl_basic_map_cow(bmap);
2232 	if (!bmap)
2233 		return NULL;
2234 
2235 	ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2236 
2237 	return isl_basic_map_finalize(bmap);
2238 }
2239 
isl_basic_set_set_rational(__isl_take isl_basic_set * bset)2240 __isl_give isl_basic_set *isl_basic_set_set_rational(
2241 	__isl_take isl_basic_set *bset)
2242 {
2243 	return isl_basic_map_set_rational(bset);
2244 }
2245 
isl_basic_set_set_integral(__isl_take isl_basic_set * bset)2246 __isl_give isl_basic_set *isl_basic_set_set_integral(
2247 	__isl_take isl_basic_set *bset)
2248 {
2249 	if (!bset)
2250 		return NULL;
2251 
2252 	if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2253 		return bset;
2254 
2255 	bset = isl_basic_set_cow(bset);
2256 	if (!bset)
2257 		return NULL;
2258 
2259 	ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2260 
2261 	return isl_basic_set_finalize(bset);
2262 }
2263 
isl_map_set_rational(__isl_take isl_map * map)2264 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2265 {
2266 	int i;
2267 
2268 	map = isl_map_cow(map);
2269 	if (!map)
2270 		return NULL;
2271 	for (i = 0; i < map->n; ++i) {
2272 		map->p[i] = isl_basic_map_set_rational(map->p[i]);
2273 		if (!map->p[i])
2274 			goto error;
2275 	}
2276 	return map;
2277 error:
2278 	isl_map_free(map);
2279 	return NULL;
2280 }
2281 
isl_set_set_rational(__isl_take isl_set * set)2282 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2283 {
2284 	return isl_map_set_rational(set);
2285 }
2286 
2287 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2288  * of "bmap").
2289  */
swap_div(__isl_keep isl_basic_map * bmap,int a,int b)2290 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2291 {
2292 	isl_int *t = bmap->div[a];
2293 	bmap->div[a] = bmap->div[b];
2294 	bmap->div[b] = t;
2295 }
2296 
2297 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2298  * div definitions accordingly.
2299  */
isl_basic_map_swap_div(__isl_take isl_basic_map * bmap,int a,int b)2300 __isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2301 	int a, int b)
2302 {
2303 	int i;
2304 	isl_size off;
2305 
2306 	off = isl_basic_map_var_offset(bmap, isl_dim_div);
2307 	if (off < 0)
2308 		return isl_basic_map_free(bmap);
2309 
2310 	swap_div(bmap, a, b);
2311 
2312 	for (i = 0; i < bmap->n_eq; ++i)
2313 		isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2314 
2315 	for (i = 0; i < bmap->n_ineq; ++i)
2316 		isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2317 
2318 	for (i = 0; i < bmap->n_div; ++i)
2319 		isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2320 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2321 
2322 	return bmap;
2323 }
2324 
constraint_drop_vars(isl_int * c,unsigned n,unsigned rem)2325 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2326 {
2327 	isl_seq_cpy(c, c + n, rem);
2328 	isl_seq_clr(c + rem, n);
2329 }
2330 
2331 /* Drop n dimensions starting at first.
2332  *
2333  * In principle, this frees up some extra variables as the number
2334  * of columns remains constant, but we would have to extend
2335  * the div array too as the number of rows in this array is assumed
2336  * to be equal to extra.
2337  */
isl_basic_set_drop_dims(__isl_take isl_basic_set * bset,unsigned first,unsigned n)2338 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2339 	__isl_take isl_basic_set *bset, unsigned first, unsigned n)
2340 {
2341 	return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2342 }
2343 
2344 /* Move "n" divs starting at "first" to the end of the list of divs.
2345  */
move_divs_last(__isl_take isl_basic_map * bmap,unsigned first,unsigned n)2346 static __isl_give isl_basic_map *move_divs_last(__isl_take isl_basic_map *bmap,
2347 	unsigned first, unsigned n)
2348 {
2349 	isl_int **div;
2350 	int i;
2351 
2352 	if (first + n == bmap->n_div)
2353 		return bmap;
2354 
2355 	div = isl_alloc_array(bmap->ctx, isl_int *, n);
2356 	if (!div)
2357 		goto error;
2358 	for (i = 0; i < n; ++i)
2359 		div[i] = bmap->div[first + i];
2360 	for (i = 0; i < bmap->n_div - first - n; ++i)
2361 		bmap->div[first + i] = bmap->div[first + n + i];
2362 	for (i = 0; i < n; ++i)
2363 		bmap->div[bmap->n_div - n + i] = div[i];
2364 	free(div);
2365 	return bmap;
2366 error:
2367 	isl_basic_map_free(bmap);
2368 	return NULL;
2369 }
2370 
2371 #undef TYPE
2372 #define TYPE	isl_map
2373 static
2374 #include "check_type_range_templ.c"
2375 
2376 /* Check that there are "n" dimensions of type "type" starting at "first"
2377  * in "set".
2378  */
isl_set_check_range(__isl_keep isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2379 isl_stat isl_set_check_range(__isl_keep isl_set *set,
2380 	enum isl_dim_type type, unsigned first, unsigned n)
2381 {
2382 	return isl_map_check_range(set_to_map(set), type, first, n);
2383 }
2384 
2385 /* Drop "n" dimensions of type "type" starting at "first".
2386  * Perform the core computation, without cowing or
2387  * simplifying and finalizing the result.
2388  *
2389  * In principle, this frees up some extra variables as the number
2390  * of columns remains constant, but we would have to extend
2391  * the div array too as the number of rows in this array is assumed
2392  * to be equal to extra.
2393  */
isl_basic_map_drop_core(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2394 __isl_give isl_basic_map *isl_basic_map_drop_core(
2395 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
2396 	unsigned first, unsigned n)
2397 {
2398 	int i;
2399 	unsigned offset;
2400 	unsigned left;
2401 	isl_size total;
2402 
2403 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2404 		return isl_basic_map_free(bmap);
2405 
2406 	total = isl_basic_map_dim(bmap, isl_dim_all);
2407 	if (total < 0)
2408 		return isl_basic_map_free(bmap);
2409 
2410 	offset = isl_basic_map_offset(bmap, type) + first;
2411 	left = total - (offset - 1) - n;
2412 	for (i = 0; i < bmap->n_eq; ++i)
2413 		constraint_drop_vars(bmap->eq[i]+offset, n, left);
2414 
2415 	for (i = 0; i < bmap->n_ineq; ++i)
2416 		constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2417 
2418 	for (i = 0; i < bmap->n_div; ++i)
2419 		constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2420 
2421 	if (type == isl_dim_div) {
2422 		bmap = move_divs_last(bmap, first, n);
2423 		if (!bmap)
2424 			return NULL;
2425 		if (isl_basic_map_free_div(bmap, n) < 0)
2426 			return isl_basic_map_free(bmap);
2427 	} else
2428 		bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2429 	if (!bmap->dim)
2430 		return isl_basic_map_free(bmap);
2431 
2432 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2433 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2434 	return bmap;
2435 }
2436 
2437 /* Drop "n" dimensions of type "type" starting at "first".
2438  *
2439  * In principle, this frees up some extra variables as the number
2440  * of columns remains constant, but we would have to extend
2441  * the div array too as the number of rows in this array is assumed
2442  * to be equal to extra.
2443  */
isl_basic_map_drop(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2444 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2445 	enum isl_dim_type type, unsigned first, unsigned n)
2446 {
2447 	if (!bmap)
2448 		return NULL;
2449 	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2450 		return bmap;
2451 
2452 	bmap = isl_basic_map_cow(bmap);
2453 	if (!bmap)
2454 		return NULL;
2455 
2456 	bmap = isl_basic_map_drop_core(bmap, type, first, n);
2457 
2458 	bmap = isl_basic_map_simplify(bmap);
2459 	return isl_basic_map_finalize(bmap);
2460 }
2461 
isl_basic_set_drop(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2462 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2463 	enum isl_dim_type type, unsigned first, unsigned n)
2464 {
2465 	return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2466 							type, first, n));
2467 }
2468 
2469 /* No longer consider "map" to be normalized.
2470  */
isl_map_unmark_normalized(__isl_take isl_map * map)2471 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2472 {
2473 	if (!map)
2474 		return NULL;
2475 	ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2476 	return map;
2477 }
2478 
isl_map_drop(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2479 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2480 	enum isl_dim_type type, unsigned first, unsigned n)
2481 {
2482 	int i;
2483 	isl_space *space;
2484 
2485 	if (isl_map_check_range(map, type, first, n) < 0)
2486 		return isl_map_free(map);
2487 
2488 	if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2489 		return map;
2490 	map = isl_map_cow(map);
2491 	if (!map)
2492 		goto error;
2493 
2494 	for (i = 0; i < map->n; ++i) {
2495 		map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2496 		if (!map->p[i])
2497 			goto error;
2498 	}
2499 	map = isl_map_unmark_normalized(map);
2500 
2501 	space = isl_map_take_space(map);
2502 	space = isl_space_drop_dims(space, type, first, n);
2503 	map = isl_map_restore_space(map, space);
2504 
2505 	return map;
2506 error:
2507 	isl_map_free(map);
2508 	return NULL;
2509 }
2510 
isl_set_drop(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2511 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2512 	enum isl_dim_type type, unsigned first, unsigned n)
2513 {
2514 	return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2515 }
2516 
2517 /* Drop the integer division at position "div", which is assumed
2518  * not to appear in any of the constraints or
2519  * in any of the other integer divisions.
2520  *
2521  * Since the integer division is redundant, there is no need to cow.
2522  */
isl_basic_map_drop_div(__isl_take isl_basic_map * bmap,unsigned div)2523 __isl_give isl_basic_map *isl_basic_map_drop_div(
2524 	__isl_take isl_basic_map *bmap, unsigned div)
2525 {
2526 	return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2527 }
2528 
2529 /* Eliminate the specified n dimensions starting at first from the
2530  * constraints, without removing the dimensions from the space.
2531  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2532  */
isl_map_eliminate(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2533 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2534 	enum isl_dim_type type, unsigned first, unsigned n)
2535 {
2536 	int i;
2537 
2538 	if (n == 0)
2539 		return map;
2540 
2541 	if (isl_map_check_range(map, type, first, n) < 0)
2542 		return isl_map_free(map);
2543 
2544 	map = isl_map_cow(map);
2545 	if (!map)
2546 		return NULL;
2547 
2548 	for (i = 0; i < map->n; ++i) {
2549 		map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2550 		if (!map->p[i])
2551 			goto error;
2552 	}
2553 	return map;
2554 error:
2555 	isl_map_free(map);
2556 	return NULL;
2557 }
2558 
2559 /* Eliminate the specified n dimensions starting at first from the
2560  * constraints, without removing the dimensions from the space.
2561  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2562  */
isl_set_eliminate(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2563 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2564 	enum isl_dim_type type, unsigned first, unsigned n)
2565 {
2566 	return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2567 }
2568 
2569 /* Eliminate the specified n dimensions starting at first from the
2570  * constraints, without removing the dimensions from the space.
2571  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2572  */
isl_set_eliminate_dims(__isl_take isl_set * set,unsigned first,unsigned n)2573 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2574 	unsigned first, unsigned n)
2575 {
2576 	return isl_set_eliminate(set, isl_dim_set, first, n);
2577 }
2578 
isl_basic_map_remove_divs(__isl_take isl_basic_map * bmap)2579 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2580 	__isl_take isl_basic_map *bmap)
2581 {
2582 	isl_size v_div;
2583 
2584 	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2585 	if (v_div < 0)
2586 		return isl_basic_map_free(bmap);
2587 	bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);
2588 	if (!bmap)
2589 		return NULL;
2590 	bmap->n_div = 0;
2591 	return isl_basic_map_finalize(bmap);
2592 }
2593 
isl_basic_set_remove_divs(__isl_take isl_basic_set * bset)2594 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2595 	__isl_take isl_basic_set *bset)
2596 {
2597 	return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2598 }
2599 
isl_map_remove_divs(__isl_take isl_map * map)2600 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2601 {
2602 	int i;
2603 
2604 	if (!map)
2605 		return NULL;
2606 	if (map->n == 0)
2607 		return map;
2608 
2609 	map = isl_map_cow(map);
2610 	if (!map)
2611 		return NULL;
2612 
2613 	for (i = 0; i < map->n; ++i) {
2614 		map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2615 		if (!map->p[i])
2616 			goto error;
2617 	}
2618 	return map;
2619 error:
2620 	isl_map_free(map);
2621 	return NULL;
2622 }
2623 
isl_set_remove_divs(__isl_take isl_set * set)2624 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2625 {
2626 	return isl_map_remove_divs(set);
2627 }
2628 
isl_basic_map_remove_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2629 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2630 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
2631 	unsigned first, unsigned n)
2632 {
2633 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2634 		return isl_basic_map_free(bmap);
2635 	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2636 		return bmap;
2637 	bmap = isl_basic_map_eliminate_vars(bmap,
2638 			isl_basic_map_offset(bmap, type) - 1 + first, n);
2639 	if (!bmap)
2640 		return bmap;
2641 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2642 		return bmap;
2643 	bmap = isl_basic_map_drop(bmap, type, first, n);
2644 	return bmap;
2645 }
2646 
2647 /* Return true if the definition of the given div (recursively) involves
2648  * any of the given variables.
2649  */
div_involves_vars(__isl_keep isl_basic_map * bmap,int div,unsigned first,unsigned n)2650 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2651 	unsigned first, unsigned n)
2652 {
2653 	int i;
2654 	unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2655 
2656 	if (isl_int_is_zero(bmap->div[div][0]))
2657 		return isl_bool_false;
2658 	if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2659 		return isl_bool_true;
2660 
2661 	for (i = bmap->n_div - 1; i >= 0; --i) {
2662 		isl_bool involves;
2663 
2664 		if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2665 			continue;
2666 		involves = div_involves_vars(bmap, i, first, n);
2667 		if (involves < 0 || involves)
2668 			return involves;
2669 	}
2670 
2671 	return isl_bool_false;
2672 }
2673 
2674 /* Try and add a lower and/or upper bound on "div" to "bmap"
2675  * based on inequality "i".
2676  * "total" is the total number of variables (excluding the divs).
2677  * "v" is a temporary object that can be used during the calculations.
2678  * If "lb" is set, then a lower bound should be constructed.
2679  * If "ub" is set, then an upper bound should be constructed.
2680  *
2681  * The calling function has already checked that the inequality does not
2682  * reference "div", but we still need to check that the inequality is
2683  * of the right form.  We'll consider the case where we want to construct
2684  * a lower bound.  The construction of upper bounds is similar.
2685  *
2686  * Let "div" be of the form
2687  *
2688  *	q = floor((a + f(x))/d)
2689  *
2690  * We essentially check if constraint "i" is of the form
2691  *
2692  *	b + f(x) >= 0
2693  *
2694  * so that we can use it to derive a lower bound on "div".
2695  * However, we allow a slightly more general form
2696  *
2697  *	b + g(x) >= 0
2698  *
2699  * with the condition that the coefficients of g(x) - f(x) are all
2700  * divisible by d.
2701  * Rewriting this constraint as
2702  *
2703  *	0 >= -b - g(x)
2704  *
2705  * adding a + f(x) to both sides and dividing by d, we obtain
2706  *
2707  *	(a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2708  *
2709  * Taking the floor on both sides, we obtain
2710  *
2711  *	q >= floor((a-b)/d) + (f(x)-g(x))/d
2712  *
2713  * or
2714  *
2715  *	(g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2716  *
2717  * In the case of an upper bound, we construct the constraint
2718  *
2719  *	(g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2720  *
2721  */
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)2722 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2723 	__isl_take isl_basic_map *bmap, int div, int i,
2724 	unsigned total, isl_int v, int lb, int ub)
2725 {
2726 	int j;
2727 
2728 	for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2729 		if (lb) {
2730 			isl_int_sub(v, bmap->ineq[i][1 + j],
2731 					bmap->div[div][1 + 1 + j]);
2732 			lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2733 		}
2734 		if (ub) {
2735 			isl_int_add(v, bmap->ineq[i][1 + j],
2736 					bmap->div[div][1 + 1 + j]);
2737 			ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2738 		}
2739 	}
2740 	if (!lb && !ub)
2741 		return bmap;
2742 
2743 	bmap = isl_basic_map_cow(bmap);
2744 	bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2745 	if (lb) {
2746 		int k = isl_basic_map_alloc_inequality(bmap);
2747 		if (k < 0)
2748 			goto error;
2749 		for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2750 			isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2751 					bmap->div[div][1 + j]);
2752 			isl_int_cdiv_q(bmap->ineq[k][j],
2753 					bmap->ineq[k][j], bmap->div[div][0]);
2754 		}
2755 		isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2756 	}
2757 	if (ub) {
2758 		int k = isl_basic_map_alloc_inequality(bmap);
2759 		if (k < 0)
2760 			goto error;
2761 		for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2762 			isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2763 					bmap->div[div][1 + j]);
2764 			isl_int_fdiv_q(bmap->ineq[k][j],
2765 					bmap->ineq[k][j], bmap->div[div][0]);
2766 		}
2767 		isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2768 	}
2769 
2770 	return bmap;
2771 error:
2772 	isl_basic_map_free(bmap);
2773 	return NULL;
2774 }
2775 
2776 /* This function is called right before "div" is eliminated from "bmap"
2777  * using Fourier-Motzkin.
2778  * Look through the constraints of "bmap" for constraints on the argument
2779  * of the integer division and use them to construct constraints on the
2780  * integer division itself.  These constraints can then be combined
2781  * during the Fourier-Motzkin elimination.
2782  * Note that it is only useful to introduce lower bounds on "div"
2783  * if "bmap" already contains upper bounds on "div" as the newly
2784  * introduce lower bounds can then be combined with the pre-existing
2785  * upper bounds.  Similarly for upper bounds.
2786  * We therefore first check if "bmap" contains any lower and/or upper bounds
2787  * on "div".
2788  *
2789  * It is interesting to note that the introduction of these constraints
2790  * can indeed lead to more accurate results, even when compared to
2791  * deriving constraints on the argument of "div" from constraints on "div".
2792  * Consider, for example, the set
2793  *
2794  *	{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2795  *
2796  * The second constraint can be rewritten as
2797  *
2798  *	2 * [(-i-2j+3)/4] + k >= 0
2799  *
2800  * from which we can derive
2801  *
2802  *	-i - 2j + 3 >= -2k
2803  *
2804  * or
2805  *
2806  *	i + 2j <= 3 + 2k
2807  *
2808  * Combined with the first constraint, we obtain
2809  *
2810  *	-3 <= 3 + 2k	or	k >= -3
2811  *
2812  * If, on the other hand we derive a constraint on [(i+2j)/4] from
2813  * the first constraint, we obtain
2814  *
2815  *	[(i + 2j)/4] >= [-3/4] = -1
2816  *
2817  * Combining this constraint with the second constraint, we obtain
2818  *
2819  *	k >= -2
2820  */
insert_bounds_on_div(__isl_take isl_basic_map * bmap,int div)2821 static __isl_give isl_basic_map *insert_bounds_on_div(
2822 	__isl_take isl_basic_map *bmap, int div)
2823 {
2824 	int i;
2825 	int check_lb, check_ub;
2826 	isl_int v;
2827 	isl_size v_div;
2828 
2829 	if (!bmap)
2830 		return NULL;
2831 
2832 	if (isl_int_is_zero(bmap->div[div][0]))
2833 		return bmap;
2834 
2835 	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2836 	if (v_div < 0)
2837 		return isl_basic_map_free(bmap);
2838 
2839 	check_lb = 0;
2840 	check_ub = 0;
2841 	for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2842 		int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);
2843 		if (s > 0)
2844 			check_ub = 1;
2845 		if (s < 0)
2846 			check_lb = 1;
2847 	}
2848 
2849 	if (!check_lb && !check_ub)
2850 		return bmap;
2851 
2852 	isl_int_init(v);
2853 
2854 	for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2855 		if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))
2856 			continue;
2857 
2858 		bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,
2859 							check_lb, check_ub);
2860 	}
2861 
2862 	isl_int_clear(v);
2863 
2864 	return bmap;
2865 }
2866 
2867 /* Remove all divs (recursively) involving any of the given dimensions
2868  * in their definitions.
2869  */
isl_basic_map_remove_divs_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2870 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2871 	__isl_take isl_basic_map *bmap,
2872 	enum isl_dim_type type, unsigned first, unsigned n)
2873 {
2874 	int i;
2875 
2876 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2877 		return isl_basic_map_free(bmap);
2878 	first += isl_basic_map_offset(bmap, type);
2879 
2880 	for (i = bmap->n_div - 1; i >= 0; --i) {
2881 		isl_bool involves;
2882 
2883 		involves = div_involves_vars(bmap, i, first, n);
2884 		if (involves < 0)
2885 			return isl_basic_map_free(bmap);
2886 		if (!involves)
2887 			continue;
2888 		bmap = insert_bounds_on_div(bmap, i);
2889 		bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2890 		if (!bmap)
2891 			return NULL;
2892 		i = bmap->n_div;
2893 	}
2894 
2895 	return bmap;
2896 }
2897 
isl_basic_set_remove_divs_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2898 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2899 	__isl_take isl_basic_set *bset,
2900 	enum isl_dim_type type, unsigned first, unsigned n)
2901 {
2902 	return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2903 }
2904 
isl_map_remove_divs_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2905 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2906 	enum isl_dim_type type, unsigned first, unsigned n)
2907 {
2908 	int i;
2909 
2910 	if (!map)
2911 		return NULL;
2912 	if (map->n == 0)
2913 		return map;
2914 
2915 	map = isl_map_cow(map);
2916 	if (!map)
2917 		return NULL;
2918 
2919 	for (i = 0; i < map->n; ++i) {
2920 		map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2921 								type, first, n);
2922 		if (!map->p[i])
2923 			goto error;
2924 	}
2925 	return map;
2926 error:
2927 	isl_map_free(map);
2928 	return NULL;
2929 }
2930 
isl_set_remove_divs_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2931 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2932 	enum isl_dim_type type, unsigned first, unsigned n)
2933 {
2934 	return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2935 							      type, first, n));
2936 }
2937 
2938 /* Does the description of "bmap" depend on the specified dimensions?
2939  * We also check whether the dimensions appear in any of the div definitions.
2940  * In principle there is no need for this check.  If the dimensions appear
2941  * in a div definition, they also appear in the defining constraints of that
2942  * div.
2943  */
isl_basic_map_involves_dims(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2944 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2945 	enum isl_dim_type type, unsigned first, unsigned n)
2946 {
2947 	int i;
2948 
2949 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2950 		return isl_bool_error;
2951 
2952 	first += isl_basic_map_offset(bmap, type);
2953 	for (i = 0; i < bmap->n_eq; ++i)
2954 		if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2955 			return isl_bool_true;
2956 	for (i = 0; i < bmap->n_ineq; ++i)
2957 		if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2958 			return isl_bool_true;
2959 	for (i = 0; i < bmap->n_div; ++i) {
2960 		if (isl_int_is_zero(bmap->div[i][0]))
2961 			continue;
2962 		if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2963 			return isl_bool_true;
2964 	}
2965 
2966 	return isl_bool_false;
2967 }
2968 
isl_map_involves_dims(__isl_keep isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2969 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2970 	enum isl_dim_type type, unsigned first, unsigned n)
2971 {
2972 	int i;
2973 
2974 	if (isl_map_check_range(map, type, first, n) < 0)
2975 		return isl_bool_error;
2976 
2977 	for (i = 0; i < map->n; ++i) {
2978 		isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2979 							    type, first, n);
2980 		if (involves < 0 || involves)
2981 			return involves;
2982 	}
2983 
2984 	return isl_bool_false;
2985 }
2986 
isl_basic_set_involves_dims(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2987 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2988 	enum isl_dim_type type, unsigned first, unsigned n)
2989 {
2990 	return isl_basic_map_involves_dims(bset, type, first, n);
2991 }
2992 
isl_set_involves_dims(__isl_keep isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2993 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2994 	enum isl_dim_type type, unsigned first, unsigned n)
2995 {
2996 	return isl_map_involves_dims(set, type, first, n);
2997 }
2998 
2999 /* Does "bset" involve any local variables, i.e., integer divisions?
3000  */
isl_basic_set_involves_locals(__isl_keep isl_basic_set * bset)3001 static isl_bool isl_basic_set_involves_locals(__isl_keep isl_basic_set *bset)
3002 {
3003 	isl_size n;
3004 
3005 	n = isl_basic_set_dim(bset, isl_dim_div);
3006 	if (n < 0)
3007 		return isl_bool_error;
3008 	return isl_bool_ok(n > 0);
3009 }
3010 
3011 /* isl_set_every_basic_set callback that checks whether "bset"
3012  * is free of local variables.
3013  */
basic_set_no_locals(__isl_keep isl_basic_set * bset,void * user)3014 static isl_bool basic_set_no_locals(__isl_keep isl_basic_set *bset, void *user)
3015 {
3016 	return isl_bool_not(isl_basic_set_involves_locals(bset));
3017 }
3018 
3019 /* Does "set" involve any local variables, i.e., integer divisions?
3020  */
isl_set_involves_locals(__isl_keep isl_set * set)3021 isl_bool isl_set_involves_locals(__isl_keep isl_set *set)
3022 {
3023 	isl_bool no_locals;
3024 
3025 	no_locals = isl_set_every_basic_set(set, &basic_set_no_locals, NULL);
3026 	return isl_bool_not(no_locals);
3027 }
3028 
3029 /* Drop all constraints in bmap that involve any of the dimensions
3030  * first to first+n-1.
3031  * This function only performs the actual removal of constraints.
3032  *
3033  * This function should not call finalize since it is used by
3034  * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
3035  */
isl_basic_map_drop_constraints_involving(__isl_take isl_basic_map * bmap,unsigned first,unsigned n)3036 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
3037 	__isl_take isl_basic_map *bmap, unsigned first, unsigned n)
3038 {
3039 	int i;
3040 
3041 	if (n == 0)
3042 		return bmap;
3043 
3044 	bmap = isl_basic_map_cow(bmap);
3045 
3046 	if (!bmap)
3047 		return NULL;
3048 
3049 	for (i = bmap->n_eq - 1; i >= 0; --i) {
3050 		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
3051 			continue;
3052 		if (isl_basic_map_drop_equality(bmap, i) < 0)
3053 			return isl_basic_map_free(bmap);
3054 	}
3055 
3056 	for (i = bmap->n_ineq - 1; i >= 0; --i) {
3057 		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
3058 			continue;
3059 		if (isl_basic_map_drop_inequality(bmap, i) < 0)
3060 			return isl_basic_map_free(bmap);
3061 	}
3062 
3063 	return bmap;
3064 }
3065 
3066 /* Drop all constraints in bset that involve any of the dimensions
3067  * first to first+n-1.
3068  * This function only performs the actual removal of constraints.
3069  */
isl_basic_set_drop_constraints_involving(__isl_take isl_basic_set * bset,unsigned first,unsigned n)3070 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
3071 	__isl_take isl_basic_set *bset, unsigned first, unsigned n)
3072 {
3073 	return isl_basic_map_drop_constraints_involving(bset, first, n);
3074 }
3075 
3076 /* Drop all constraints in bmap that do not involve any of the dimensions
3077  * first to first + n - 1 of the given type.
3078  */
isl_basic_map_drop_constraints_not_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)3079 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
3080 	__isl_take isl_basic_map *bmap,
3081 	enum isl_dim_type type, unsigned first, unsigned n)
3082 {
3083 	int i;
3084 
3085 	if (n == 0) {
3086 		isl_space *space = isl_basic_map_get_space(bmap);
3087 		isl_basic_map_free(bmap);
3088 		return isl_basic_map_universe(space);
3089 	}
3090 	bmap = isl_basic_map_cow(bmap);
3091 	if (!bmap)
3092 		return NULL;
3093 
3094 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3095 		return isl_basic_map_free(bmap);
3096 
3097 	first += isl_basic_map_offset(bmap, type) - 1;
3098 
3099 	for (i = bmap->n_eq - 1; i >= 0; --i) {
3100 		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
3101 			continue;
3102 		if (isl_basic_map_drop_equality(bmap, i) < 0)
3103 			return isl_basic_map_free(bmap);
3104 	}
3105 
3106 	for (i = bmap->n_ineq - 1; i >= 0; --i) {
3107 		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
3108 			continue;
3109 		if (isl_basic_map_drop_inequality(bmap, i) < 0)
3110 			return isl_basic_map_free(bmap);
3111 	}
3112 
3113 	bmap = isl_basic_map_add_known_div_constraints(bmap);
3114 	return bmap;
3115 }
3116 
3117 /* Drop all constraints in bset that do not involve any of the dimensions
3118  * first to first + n - 1 of the given type.
3119  */
isl_basic_set_drop_constraints_not_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3120 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
3121 	__isl_take isl_basic_set *bset,
3122 	enum isl_dim_type type, unsigned first, unsigned n)
3123 {
3124 	return isl_basic_map_drop_constraints_not_involving_dims(bset,
3125 							    type, first, n);
3126 }
3127 
3128 /* Drop all constraints in bmap that involve any of the dimensions
3129  * first to first + n - 1 of the given type.
3130  */
isl_basic_map_drop_constraints_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)3131 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
3132 	__isl_take isl_basic_map *bmap,
3133 	enum isl_dim_type type, unsigned first, unsigned n)
3134 {
3135 	if (!bmap)
3136 		return NULL;
3137 	if (n == 0)
3138 		return bmap;
3139 
3140 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3141 		return isl_basic_map_free(bmap);
3142 
3143 	bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
3144 	first += isl_basic_map_offset(bmap, type) - 1;
3145 	bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
3146 	bmap = isl_basic_map_add_known_div_constraints(bmap);
3147 	return bmap;
3148 }
3149 
3150 /* Drop all constraints in bset that involve any of the dimensions
3151  * first to first + n - 1 of the given type.
3152  */
isl_basic_set_drop_constraints_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3153 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
3154 	__isl_take isl_basic_set *bset,
3155 	enum isl_dim_type type, unsigned first, unsigned n)
3156 {
3157 	return isl_basic_map_drop_constraints_involving_dims(bset,
3158 							    type, first, n);
3159 }
3160 
3161 /* Drop constraints from "map" by applying "drop" to each basic map.
3162  */
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))3163 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
3164 	enum isl_dim_type type, unsigned first, unsigned n,
3165 	__isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
3166 		enum isl_dim_type type, unsigned first, unsigned n))
3167 {
3168 	int i;
3169 
3170 	if (isl_map_check_range(map, type, first, n) < 0)
3171 		return isl_map_free(map);
3172 
3173 	map = isl_map_cow(map);
3174 	if (!map)
3175 		return NULL;
3176 
3177 	for (i = 0; i < map->n; ++i) {
3178 		map->p[i] = drop(map->p[i], type, first, n);
3179 		if (!map->p[i])
3180 			return isl_map_free(map);
3181 	}
3182 
3183 	if (map->n > 1)
3184 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
3185 
3186 	return map;
3187 }
3188 
3189 /* Drop all constraints in map that involve any of the dimensions
3190  * first to first + n - 1 of the given type.
3191  */
isl_map_drop_constraints_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3192 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
3193 	__isl_take isl_map *map,
3194 	enum isl_dim_type type, unsigned first, unsigned n)
3195 {
3196 	if (n == 0)
3197 		return map;
3198 	return drop_constraints(map, type, first, n,
3199 				&isl_basic_map_drop_constraints_involving_dims);
3200 }
3201 
3202 /* Drop all constraints in "map" that do not involve any of the dimensions
3203  * first to first + n - 1 of the given type.
3204  */
isl_map_drop_constraints_not_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3205 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3206 	__isl_take isl_map *map,
3207 	enum isl_dim_type type, unsigned first, unsigned n)
3208 {
3209 	if (n == 0) {
3210 		isl_space *space = isl_map_get_space(map);
3211 		isl_map_free(map);
3212 		return isl_map_universe(space);
3213 	}
3214 	return drop_constraints(map, type, first, n,
3215 			    &isl_basic_map_drop_constraints_not_involving_dims);
3216 }
3217 
3218 /* Drop all constraints in set that involve any of the dimensions
3219  * first to first + n - 1 of the given type.
3220  */
isl_set_drop_constraints_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)3221 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3222 	__isl_take isl_set *set,
3223 	enum isl_dim_type type, unsigned first, unsigned n)
3224 {
3225 	return isl_map_drop_constraints_involving_dims(set, type, first, n);
3226 }
3227 
3228 /* Drop all constraints in "set" that do not involve any of the dimensions
3229  * first to first + n - 1 of the given type.
3230  */
isl_set_drop_constraints_not_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)3231 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3232 	__isl_take isl_set *set,
3233 	enum isl_dim_type type, unsigned first, unsigned n)
3234 {
3235 	return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3236 }
3237 
3238 /* Does local variable "div" of "bmap" have a complete explicit representation?
3239  * Having a complete explicit representation requires not only
3240  * an explicit representation, but also that all local variables
3241  * that appear in this explicit representation in turn have
3242  * a complete explicit representation.
3243  */
isl_basic_map_div_is_known(__isl_keep isl_basic_map * bmap,int div)3244 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3245 {
3246 	int i;
3247 	unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3248 	isl_bool marked;
3249 
3250 	marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3251 	if (marked < 0 || marked)
3252 		return isl_bool_not(marked);
3253 
3254 	for (i = bmap->n_div - 1; i >= 0; --i) {
3255 		isl_bool known;
3256 
3257 		if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3258 			continue;
3259 		known = isl_basic_map_div_is_known(bmap, i);
3260 		if (known < 0 || !known)
3261 			return known;
3262 	}
3263 
3264 	return isl_bool_true;
3265 }
3266 
3267 /* Remove all divs that are unknown or defined in terms of unknown divs.
3268  */
isl_basic_map_remove_unknown_divs(__isl_take isl_basic_map * bmap)3269 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3270 	__isl_take isl_basic_map *bmap)
3271 {
3272 	int i;
3273 
3274 	if (!bmap)
3275 		return NULL;
3276 
3277 	for (i = bmap->n_div - 1; i >= 0; --i) {
3278 		if (isl_basic_map_div_is_known(bmap, i))
3279 			continue;
3280 		bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3281 		if (!bmap)
3282 			return NULL;
3283 		i = bmap->n_div;
3284 	}
3285 
3286 	return bmap;
3287 }
3288 
3289 /* Remove all divs that are unknown or defined in terms of unknown divs.
3290  */
isl_basic_set_remove_unknown_divs(__isl_take isl_basic_set * bset)3291 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3292 	__isl_take isl_basic_set *bset)
3293 {
3294 	return isl_basic_map_remove_unknown_divs(bset);
3295 }
3296 
isl_map_remove_unknown_divs(__isl_take isl_map * map)3297 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3298 {
3299 	int i;
3300 
3301 	if (!map)
3302 		return NULL;
3303 	if (map->n == 0)
3304 		return map;
3305 
3306 	map = isl_map_cow(map);
3307 	if (!map)
3308 		return NULL;
3309 
3310 	for (i = 0; i < map->n; ++i) {
3311 		map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3312 		if (!map->p[i])
3313 			goto error;
3314 	}
3315 	return map;
3316 error:
3317 	isl_map_free(map);
3318 	return NULL;
3319 }
3320 
isl_set_remove_unknown_divs(__isl_take isl_set * set)3321 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3322 {
3323 	return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3324 }
3325 
isl_basic_set_remove_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3326 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3327 	__isl_take isl_basic_set *bset,
3328 	enum isl_dim_type type, unsigned first, unsigned n)
3329 {
3330 	isl_basic_map *bmap = bset_to_bmap(bset);
3331 	bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3332 	return bset_from_bmap(bmap);
3333 }
3334 
isl_map_remove_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3335 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3336 	enum isl_dim_type type, unsigned first, unsigned n)
3337 {
3338 	int i;
3339 
3340 	if (n == 0)
3341 		return map;
3342 
3343 	map = isl_map_cow(map);
3344 	if (isl_map_check_range(map, type, first, n) < 0)
3345 		return isl_map_free(map);
3346 
3347 	for (i = 0; i < map->n; ++i) {
3348 		map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3349 			isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3350 		if (!map->p[i])
3351 			goto error;
3352 	}
3353 	map = isl_map_drop(map, type, first, n);
3354 	return map;
3355 error:
3356 	isl_map_free(map);
3357 	return NULL;
3358 }
3359 
isl_set_remove_dims(__isl_take isl_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3360 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3361 	enum isl_dim_type type, unsigned first, unsigned n)
3362 {
3363 	return set_from_map(isl_map_remove_dims(set_to_map(bset),
3364 						type, first, n));
3365 }
3366 
3367 /* Project out n inputs starting at first using Fourier-Motzkin */
isl_map_remove_inputs(__isl_take isl_map * map,unsigned first,unsigned n)3368 __isl_give isl_map *isl_map_remove_inputs(__isl_take isl_map *map,
3369 	unsigned first, unsigned n)
3370 {
3371 	return isl_map_remove_dims(map, isl_dim_in, first, n);
3372 }
3373 
isl_basic_set_print_internal(__isl_keep isl_basic_set * bset,FILE * out,int indent)3374 void isl_basic_set_print_internal(__isl_keep isl_basic_set *bset,
3375 	FILE *out, int indent)
3376 {
3377 	isl_printer *p;
3378 
3379 	if (!bset) {
3380 		fprintf(out, "null basic set\n");
3381 		return;
3382 	}
3383 
3384 	fprintf(out, "%*s", indent, "");
3385 	fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3386 			bset->ref, bset->dim->nparam, bset->dim->n_out,
3387 			bset->extra, bset->flags);
3388 
3389 	p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
3390 	p = isl_printer_set_dump(p, 1);
3391 	p = isl_printer_set_indent(p, indent);
3392 	p = isl_printer_start_line(p);
3393 	p = isl_printer_print_basic_set(p, bset);
3394 	p = isl_printer_end_line(p);
3395 	isl_printer_free(p);
3396 }
3397 
isl_basic_map_print_internal(__isl_keep isl_basic_map * bmap,FILE * out,int indent)3398 void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,
3399 	FILE *out, int indent)
3400 {
3401 	isl_printer *p;
3402 
3403 	if (!bmap) {
3404 		fprintf(out, "null basic map\n");
3405 		return;
3406 	}
3407 
3408 	fprintf(out, "%*s", indent, "");
3409 	fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3410 			"flags: %x, n_name: %d\n",
3411 		bmap->ref,
3412 		bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3413 		bmap->extra, bmap->flags, bmap->dim->n_id);
3414 
3415 	p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
3416 	p = isl_printer_set_dump(p, 1);
3417 	p = isl_printer_set_indent(p, indent);
3418 	p = isl_printer_start_line(p);
3419 	p = isl_printer_print_basic_map(p, bmap);
3420 	p = isl_printer_end_line(p);
3421 	isl_printer_free(p);
3422 }
3423 
isl_inequality_negate(__isl_take isl_basic_map * bmap,unsigned pos)3424 __isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3425 	unsigned pos)
3426 {
3427 	isl_size total;
3428 
3429 	total = isl_basic_map_dim(bmap, isl_dim_all);
3430 	if (total < 0)
3431 		return isl_basic_map_free(bmap);
3432 	if (pos >= bmap->n_ineq)
3433 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3434 			"invalid position", return isl_basic_map_free(bmap));
3435 	isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3436 	isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3437 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3438 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3439 	return bmap;
3440 }
3441 
isl_set_alloc_space(__isl_take isl_space * space,int n,unsigned flags)3442 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3443 	unsigned flags)
3444 {
3445 	if (isl_space_check_is_set(space) < 0)
3446 		goto error;
3447 	return isl_map_alloc_space(space, n, flags);
3448 error:
3449 	isl_space_free(space);
3450 	return NULL;
3451 }
3452 
3453 /* Make sure "map" has room for at least "n" more basic maps.
3454  */
isl_map_grow(__isl_take isl_map * map,int n)3455 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3456 {
3457 	int i;
3458 	struct isl_map *grown = NULL;
3459 
3460 	if (!map)
3461 		return NULL;
3462 	isl_assert(map->ctx, n >= 0, goto error);
3463 	if (map->n + n <= map->size)
3464 		return map;
3465 	grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3466 	if (!grown)
3467 		goto error;
3468 	for (i = 0; i < map->n; ++i) {
3469 		grown->p[i] = isl_basic_map_copy(map->p[i]);
3470 		if (!grown->p[i])
3471 			goto error;
3472 		grown->n++;
3473 	}
3474 	isl_map_free(map);
3475 	return grown;
3476 error:
3477 	isl_map_free(grown);
3478 	isl_map_free(map);
3479 	return NULL;
3480 }
3481 
3482 /* Make sure "set" has room for at least "n" more basic sets.
3483  */
isl_set_grow(__isl_take isl_set * set,int n)3484 __isl_give isl_set *isl_set_grow(__isl_take isl_set *set, int n)
3485 {
3486 	return set_from_map(isl_map_grow(set_to_map(set), n));
3487 }
3488 
isl_set_from_basic_set(__isl_take isl_basic_set * bset)3489 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3490 {
3491 	return isl_map_from_basic_map(bset);
3492 }
3493 
3494 /* This function performs the same operation as isl_set_from_basic_set,
3495  * but is considered as a function on an isl_basic_set when exported.
3496  */
isl_basic_set_to_set(__isl_take isl_basic_set * bset)3497 __isl_give isl_set *isl_basic_set_to_set(__isl_take isl_basic_set *bset)
3498 {
3499 	return isl_set_from_basic_set(bset);
3500 }
3501 
isl_map_from_basic_map(__isl_take isl_basic_map * bmap)3502 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3503 {
3504 	struct isl_map *map;
3505 
3506 	if (!bmap)
3507 		return NULL;
3508 
3509 	map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3510 	return isl_map_add_basic_map(map, bmap);
3511 }
3512 
isl_set_add_basic_set(__isl_take isl_set * set,__isl_take isl_basic_set * bset)3513 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3514 						__isl_take isl_basic_set *bset)
3515 {
3516 	return set_from_map(isl_map_add_basic_map(set_to_map(set),
3517 						bset_to_bmap(bset)));
3518 }
3519 
isl_set_free(__isl_take isl_set * set)3520 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3521 {
3522 	return isl_map_free(set);
3523 }
3524 
isl_set_print_internal(__isl_keep isl_set * set,FILE * out,int indent)3525 void isl_set_print_internal(__isl_keep isl_set *set, FILE *out, int indent)
3526 {
3527 	int i;
3528 
3529 	if (!set) {
3530 		fprintf(out, "null set\n");
3531 		return;
3532 	}
3533 
3534 	fprintf(out, "%*s", indent, "");
3535 	fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3536 			set->ref, set->n, set->dim->nparam, set->dim->n_out,
3537 			set->flags);
3538 	for (i = 0; i < set->n; ++i) {
3539 		fprintf(out, "%*s", indent, "");
3540 		fprintf(out, "basic set %d:\n", i);
3541 		isl_basic_set_print_internal(set->p[i], out, indent+4);
3542 	}
3543 }
3544 
isl_map_print_internal(__isl_keep isl_map * map,FILE * out,int indent)3545 void isl_map_print_internal(__isl_keep isl_map *map, FILE *out, int indent)
3546 {
3547 	int i;
3548 
3549 	if (!map) {
3550 		fprintf(out, "null map\n");
3551 		return;
3552 	}
3553 
3554 	fprintf(out, "%*s", indent, "");
3555 	fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3556 		     "flags: %x, n_name: %d\n",
3557 			map->ref, map->n, map->dim->nparam, map->dim->n_in,
3558 			map->dim->n_out, map->flags, map->dim->n_id);
3559 	for (i = 0; i < map->n; ++i) {
3560 		fprintf(out, "%*s", indent, "");
3561 		fprintf(out, "basic map %d:\n", i);
3562 		isl_basic_map_print_internal(map->p[i], out, indent+4);
3563 	}
3564 }
3565 
3566 /* Check that the space of "bset" is the same as that of the domain of "bmap".
3567  */
isl_basic_map_check_compatible_domain(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)3568 static isl_stat isl_basic_map_check_compatible_domain(
3569 	__isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3570 {
3571 	isl_bool ok;
3572 
3573 	ok = isl_basic_map_compatible_domain(bmap, bset);
3574 	if (ok < 0)
3575 		return isl_stat_error;
3576 	if (!ok)
3577 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3578 			"incompatible spaces", return isl_stat_error);
3579 
3580 	return isl_stat_ok;
3581 }
3582 
isl_basic_map_intersect_domain(__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset)3583 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3584 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3585 {
3586 	struct isl_basic_map *bmap_domain;
3587 	isl_size dim;
3588 
3589 	if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3590 		goto error;
3591 
3592 	dim = isl_basic_set_dim(bset, isl_dim_set);
3593 	if (dim < 0)
3594 		goto error;
3595 	if (dim != 0 &&
3596 	    isl_basic_map_check_compatible_domain(bmap, bset) < 0)
3597 		goto error;
3598 
3599 	bmap = isl_basic_map_cow(bmap);
3600 	if (!bmap)
3601 		goto error;
3602 	bmap = isl_basic_map_extend(bmap,
3603 			bset->n_div, bset->n_eq, bset->n_ineq);
3604 	bmap_domain = isl_basic_map_from_domain(bset);
3605 	bmap = add_constraints(bmap, bmap_domain, 0, 0);
3606 
3607 	bmap = isl_basic_map_simplify(bmap);
3608 	return isl_basic_map_finalize(bmap);
3609 error:
3610 	isl_basic_map_free(bmap);
3611 	isl_basic_set_free(bset);
3612 	return NULL;
3613 }
3614 
3615 /* Check that the space of "bset" is the same as that of the range of "bmap".
3616  */
isl_basic_map_check_compatible_range(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)3617 static isl_stat isl_basic_map_check_compatible_range(
3618 	__isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3619 {
3620 	isl_bool ok;
3621 
3622 	ok = isl_basic_map_compatible_range(bmap, bset);
3623 	if (ok < 0)
3624 		return isl_stat_error;
3625 	if (!ok)
3626 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3627 			"incompatible spaces", return isl_stat_error);
3628 
3629 	return isl_stat_ok;
3630 }
3631 
isl_basic_map_intersect_range(__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset)3632 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3633 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3634 {
3635 	struct isl_basic_map *bmap_range;
3636 	isl_size dim;
3637 
3638 	if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3639 		goto error;
3640 
3641 	dim = isl_basic_set_dim(bset, isl_dim_set);
3642 	if (dim < 0)
3643 		goto error;
3644 	if (dim != 0 && isl_basic_map_check_compatible_range(bmap, bset) < 0)
3645 		goto error;
3646 
3647 	if (isl_basic_set_plain_is_universe(bset)) {
3648 		isl_basic_set_free(bset);
3649 		return bmap;
3650 	}
3651 
3652 	bmap = isl_basic_map_cow(bmap);
3653 	if (!bmap)
3654 		goto error;
3655 	bmap = isl_basic_map_extend(bmap,
3656 			bset->n_div, bset->n_eq, bset->n_ineq);
3657 	bmap_range = bset_to_bmap(bset);
3658 	bmap = add_constraints(bmap, bmap_range, 0, 0);
3659 
3660 	bmap = isl_basic_map_simplify(bmap);
3661 	return isl_basic_map_finalize(bmap);
3662 error:
3663 	isl_basic_map_free(bmap);
3664 	isl_basic_set_free(bset);
3665 	return NULL;
3666 }
3667 
isl_basic_map_contains(__isl_keep isl_basic_map * bmap,__isl_keep isl_vec * vec)3668 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3669 	__isl_keep isl_vec *vec)
3670 {
3671 	int i;
3672 	isl_size total;
3673 	isl_int s;
3674 
3675 	total = isl_basic_map_dim(bmap, isl_dim_all);
3676 	if (total < 0 || !vec)
3677 		return isl_bool_error;
3678 
3679 	if (1 + total != vec->size)
3680 		return isl_bool_false;
3681 
3682 	isl_int_init(s);
3683 
3684 	for (i = 0; i < bmap->n_eq; ++i) {
3685 		isl_seq_inner_product(vec->el, bmap->eq[i], 1 + total, &s);
3686 		if (!isl_int_is_zero(s)) {
3687 			isl_int_clear(s);
3688 			return isl_bool_false;
3689 		}
3690 	}
3691 
3692 	for (i = 0; i < bmap->n_ineq; ++i) {
3693 		isl_seq_inner_product(vec->el, bmap->ineq[i], 1 + total, &s);
3694 		if (isl_int_is_neg(s)) {
3695 			isl_int_clear(s);
3696 			return isl_bool_false;
3697 		}
3698 	}
3699 
3700 	isl_int_clear(s);
3701 
3702 	return isl_bool_true;
3703 }
3704 
isl_basic_set_contains(__isl_keep isl_basic_set * bset,__isl_keep isl_vec * vec)3705 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3706 	__isl_keep isl_vec *vec)
3707 {
3708 	return isl_basic_map_contains(bset_to_bmap(bset), vec);
3709 }
3710 
isl_basic_map_intersect(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)3711 __isl_give isl_basic_map *isl_basic_map_intersect(
3712 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3713 {
3714 	struct isl_vec *sample = NULL;
3715 	isl_space *space1, *space2;
3716 	isl_size dim1, dim2, nparam1, nparam2;
3717 
3718 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3719 		goto error;
3720 	space1 = isl_basic_map_peek_space(bmap1);
3721 	space2 = isl_basic_map_peek_space(bmap2);
3722 	dim1 = isl_space_dim(space1, isl_dim_all);
3723 	dim2 = isl_space_dim(space2, isl_dim_all);
3724 	nparam1 = isl_space_dim(space1, isl_dim_param);
3725 	nparam2 = isl_space_dim(space2, isl_dim_param);
3726 	if (dim1 < 0 || dim2 < 0 || nparam1 < 0 || nparam2 < 0)
3727 		goto error;
3728 	if (dim1 == nparam1 && dim2 != nparam2)
3729 		return isl_basic_map_intersect(bmap2, bmap1);
3730 
3731 	if (dim2 != nparam2 &&
3732 	    isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
3733 		goto error;
3734 
3735 	if (isl_basic_map_plain_is_empty(bmap1)) {
3736 		isl_basic_map_free(bmap2);
3737 		return bmap1;
3738 	}
3739 	if (isl_basic_map_plain_is_empty(bmap2)) {
3740 		isl_basic_map_free(bmap1);
3741 		return bmap2;
3742 	}
3743 
3744 	if (bmap1->sample &&
3745 	    isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3746 	    isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3747 		sample = isl_vec_copy(bmap1->sample);
3748 	else if (bmap2->sample &&
3749 	    isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3750 	    isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3751 		sample = isl_vec_copy(bmap2->sample);
3752 
3753 	bmap1 = isl_basic_map_cow(bmap1);
3754 	if (!bmap1)
3755 		goto error;
3756 	bmap1 = isl_basic_map_extend(bmap1,
3757 			bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3758 	bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3759 
3760 	if (!bmap1)
3761 		isl_vec_free(sample);
3762 	else if (sample) {
3763 		isl_vec_free(bmap1->sample);
3764 		bmap1->sample = sample;
3765 	}
3766 
3767 	bmap1 = isl_basic_map_simplify(bmap1);
3768 	return isl_basic_map_finalize(bmap1);
3769 error:
3770 	if (sample)
3771 		isl_vec_free(sample);
3772 	isl_basic_map_free(bmap1);
3773 	isl_basic_map_free(bmap2);
3774 	return NULL;
3775 }
3776 
isl_basic_set_intersect(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)3777 __isl_give isl_basic_set *isl_basic_set_intersect(
3778 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3779 {
3780 	return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3781 							bset_to_bmap(bset2)));
3782 }
3783 
isl_basic_set_intersect_params(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)3784 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3785 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3786 {
3787 	return isl_basic_set_intersect(bset1, bset2);
3788 }
3789 
3790 /* Does "map" consist of a single disjunct, without any local variables?
3791  */
is_convex_no_locals(__isl_keep isl_map * map)3792 static isl_bool is_convex_no_locals(__isl_keep isl_map *map)
3793 {
3794 	isl_size n_div;
3795 
3796 	if (!map)
3797 		return isl_bool_error;
3798 	if (map->n != 1)
3799 		return isl_bool_false;
3800 	n_div = isl_basic_map_dim(map->p[0], isl_dim_div);
3801 	if (n_div < 0)
3802 		return isl_bool_error;
3803 	if (n_div != 0)
3804 		return isl_bool_false;
3805 	return isl_bool_true;
3806 }
3807 
3808 /* Check that "map" consists of a single disjunct, without any local variables.
3809  */
check_convex_no_locals(__isl_keep isl_map * map)3810 static isl_stat check_convex_no_locals(__isl_keep isl_map *map)
3811 {
3812 	isl_bool ok;
3813 
3814 	ok = is_convex_no_locals(map);
3815 	if (ok < 0)
3816 		return isl_stat_error;
3817 	if (ok)
3818 		return isl_stat_ok;
3819 
3820 	isl_die(isl_map_get_ctx(map), isl_error_internal,
3821 		"unexpectedly not convex or involving local variables",
3822 		return isl_stat_error);
3823 }
3824 
3825 /* Special case of isl_map_intersect, where both map1 and map2
3826  * are convex, without any divs and such that either map1 or map2
3827  * contains a single constraint.  This constraint is then simply
3828  * added to the other map.
3829  */
map_intersect_add_constraint(__isl_take isl_map * map1,__isl_take isl_map * map2)3830 static __isl_give isl_map *map_intersect_add_constraint(
3831 	__isl_take isl_map *map1, __isl_take isl_map *map2)
3832 {
3833 	if (check_convex_no_locals(map1) < 0 ||
3834 	    check_convex_no_locals(map2) < 0)
3835 		goto error;
3836 
3837 	if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3838 		return isl_map_intersect(map2, map1);
3839 
3840 	map1 = isl_map_cow(map1);
3841 	if (!map1)
3842 		goto error;
3843 	if (isl_map_plain_is_empty(map1)) {
3844 		isl_map_free(map2);
3845 		return map1;
3846 	}
3847 	if (map2->p[0]->n_eq == 1)
3848 		map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3849 	else
3850 		map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3851 							map2->p[0]->ineq[0]);
3852 
3853 	map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3854 	map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3855 	if (!map1->p[0])
3856 		goto error;
3857 
3858 	if (isl_basic_map_plain_is_empty(map1->p[0])) {
3859 		isl_basic_map_free(map1->p[0]);
3860 		map1->n = 0;
3861 	}
3862 
3863 	isl_map_free(map2);
3864 
3865 	map1 = isl_map_unmark_normalized(map1);
3866 	return map1;
3867 error:
3868 	isl_map_free(map1);
3869 	isl_map_free(map2);
3870 	return NULL;
3871 }
3872 
3873 /* map2 may be either a parameter domain or a map living in the same
3874  * space as map1.
3875  */
map_intersect_internal(__isl_take isl_map * map1,__isl_take isl_map * map2)3876 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3877 	__isl_take isl_map *map2)
3878 {
3879 	unsigned flags = 0;
3880 	isl_bool equal;
3881 	isl_map *result;
3882 	int i, j;
3883 	isl_size dim2, nparam2;
3884 
3885 	if (!map1 || !map2)
3886 		goto error;
3887 
3888 	if ((isl_map_plain_is_empty(map1) ||
3889 	     isl_map_plain_is_universe(map2)) &&
3890 	    isl_space_is_equal(map1->dim, map2->dim)) {
3891 		isl_map_free(map2);
3892 		return map1;
3893 	}
3894 	if ((isl_map_plain_is_empty(map2) ||
3895 	     isl_map_plain_is_universe(map1)) &&
3896 	    isl_space_is_equal(map1->dim, map2->dim)) {
3897 		isl_map_free(map1);
3898 		return map2;
3899 	}
3900 
3901 	if (is_convex_no_locals(map1) == isl_bool_true &&
3902 	    is_convex_no_locals(map2) == isl_bool_true &&
3903 	    isl_space_is_equal(map1->dim, map2->dim) &&
3904 	    (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3905 	     map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3906 		return map_intersect_add_constraint(map1, map2);
3907 
3908 	equal = isl_map_plain_is_equal(map1, map2);
3909 	if (equal < 0)
3910 		goto error;
3911 	if (equal) {
3912 		isl_map_free(map2);
3913 		return map1;
3914 	}
3915 
3916 	dim2 = isl_map_dim(map2, isl_dim_all);
3917 	nparam2 = isl_map_dim(map2, isl_dim_param);
3918 	if (dim2 < 0 || nparam2 < 0)
3919 		goto error;
3920 	if (dim2 != nparam2)
3921 		isl_assert(map1->ctx,
3922 			    isl_space_is_equal(map1->dim, map2->dim), goto error);
3923 
3924 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3925 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3926 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3927 
3928 	result = isl_map_alloc_space(isl_space_copy(map1->dim),
3929 				map1->n * map2->n, flags);
3930 	if (!result)
3931 		goto error;
3932 	for (i = 0; i < map1->n; ++i)
3933 		for (j = 0; j < map2->n; ++j) {
3934 			struct isl_basic_map *part;
3935 			part = isl_basic_map_intersect(
3936 				    isl_basic_map_copy(map1->p[i]),
3937 				    isl_basic_map_copy(map2->p[j]));
3938 			if (isl_basic_map_is_empty(part) < 0)
3939 				part = isl_basic_map_free(part);
3940 			result = isl_map_add_basic_map(result, part);
3941 			if (!result)
3942 				goto error;
3943 		}
3944 	isl_map_free(map1);
3945 	isl_map_free(map2);
3946 	return result;
3947 error:
3948 	isl_map_free(map1);
3949 	isl_map_free(map2);
3950 	return NULL;
3951 }
3952 
map_intersect(__isl_take isl_map * map1,__isl_take isl_map * map2)3953 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3954 	__isl_take isl_map *map2)
3955 {
3956 	if (isl_map_check_equal_space(map1, map2) < 0)
3957 		goto error;
3958 	return map_intersect_internal(map1, map2);
3959 error:
3960 	isl_map_free(map1);
3961 	isl_map_free(map2);
3962 	return NULL;
3963 }
3964 
isl_map_intersect(__isl_take isl_map * map1,__isl_take isl_map * map2)3965 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3966 	__isl_take isl_map *map2)
3967 {
3968 	isl_map_align_params_bin(&map1, &map2);
3969 	return map_intersect(map1, map2);
3970 }
3971 
isl_set_intersect(__isl_take isl_set * set1,__isl_take isl_set * set2)3972 __isl_give isl_set *isl_set_intersect(__isl_take isl_set *set1,
3973 	__isl_take isl_set *set2)
3974 {
3975 	return set_from_map(isl_map_intersect(set_to_map(set1),
3976 					      set_to_map(set2)));
3977 }
3978 
3979 /* map_intersect_internal accepts intersections
3980  * with parameter domains, so we can just call that function.
3981  */
isl_map_intersect_params(__isl_take isl_map * map,__isl_take isl_set * params)3982 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
3983 	__isl_take isl_set *params)
3984 {
3985 	isl_map_align_params_set(&map, &params);
3986 	return map_intersect_internal(map, params);
3987 }
3988 
isl_set_intersect_params(__isl_take isl_set * set,__isl_take isl_set * params)3989 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3990 		__isl_take isl_set *params)
3991 {
3992 	return isl_map_intersect_params(set, params);
3993 }
3994 
isl_basic_map_reverse(__isl_take isl_basic_map * bmap)3995 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3996 {
3997 	isl_space *space;
3998 	unsigned pos;
3999 	isl_size n1, n2;
4000 
4001 	if (!bmap)
4002 		return NULL;
4003 	bmap = isl_basic_map_cow(bmap);
4004 	if (!bmap)
4005 		return NULL;
4006 	space = isl_space_reverse(isl_space_copy(bmap->dim));
4007 	pos = isl_basic_map_offset(bmap, isl_dim_in);
4008 	n1 = isl_basic_map_dim(bmap, isl_dim_in);
4009 	n2 = isl_basic_map_dim(bmap, isl_dim_out);
4010 	if (n1 < 0 || n2 < 0)
4011 		bmap = isl_basic_map_free(bmap);
4012 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
4013 	return isl_basic_map_reset_space(bmap, space);
4014 }
4015 
4016 /* Given a basic map A -> (B -> C), return the corresponding basic map
4017  * A -> (C -> B).
4018  */
isl_basic_map_range_reverse(__isl_take isl_basic_map * bmap)4019 static __isl_give isl_basic_map *isl_basic_map_range_reverse(
4020 	__isl_take isl_basic_map *bmap)
4021 {
4022 	isl_space *space;
4023 	isl_size offset, n1, n2;
4024 
4025 	space = isl_basic_map_peek_space(bmap);
4026 	if (isl_space_check_range_is_wrapping(space) < 0)
4027 		return isl_basic_map_free(bmap);
4028 	offset = isl_basic_map_var_offset(bmap, isl_dim_out);
4029 	n1 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_in);
4030 	n2 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_out);
4031 	if (offset < 0 || n1 < 0 || n2 < 0)
4032 		return isl_basic_map_free(bmap);
4033 
4034 	bmap = isl_basic_map_swap_vars(bmap, 1 + offset, n1, n2);
4035 
4036 	space = isl_basic_map_take_space(bmap);
4037 	space = isl_space_range_reverse(space);
4038 	bmap = isl_basic_map_restore_space(bmap, space);
4039 
4040 	return bmap;
4041 }
4042 
basic_map_space_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)4043 static __isl_give isl_basic_map *basic_map_space_reset(
4044 	__isl_take isl_basic_map *bmap, enum isl_dim_type type)
4045 {
4046 	isl_space *space;
4047 
4048 	if (!bmap)
4049 		return NULL;
4050 	if (!isl_space_is_named_or_nested(bmap->dim, type))
4051 		return bmap;
4052 
4053 	space = isl_basic_map_get_space(bmap);
4054 	space = isl_space_reset(space, type);
4055 	bmap = isl_basic_map_reset_space(bmap, space);
4056 	return bmap;
4057 }
4058 
isl_basic_map_insert_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,unsigned n)4059 __isl_give isl_basic_map *isl_basic_map_insert_dims(
4060 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
4061 	unsigned pos, unsigned n)
4062 {
4063 	isl_bool rational, is_empty;
4064 	isl_space *res_space;
4065 	struct isl_basic_map *res;
4066 	struct isl_dim_map *dim_map;
4067 	isl_size total;
4068 	unsigned off;
4069 	enum isl_dim_type t;
4070 
4071 	if (n == 0)
4072 		return basic_map_space_reset(bmap, type);
4073 
4074 	is_empty = isl_basic_map_plain_is_empty(bmap);
4075 	total = isl_basic_map_dim(bmap, isl_dim_all);
4076 	if (is_empty < 0 || total < 0)
4077 		return isl_basic_map_free(bmap);
4078 	res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
4079 					type, pos, n);
4080 	if (!res_space)
4081 		return isl_basic_map_free(bmap);
4082 	if (is_empty) {
4083 		isl_basic_map_free(bmap);
4084 		return isl_basic_map_empty(res_space);
4085 	}
4086 
4087 	dim_map = isl_dim_map_alloc(bmap->ctx, total + n);
4088 	off = 0;
4089 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4090 		isl_size dim;
4091 
4092 		if (t != type) {
4093 			isl_dim_map_dim(dim_map, bmap->dim, t, off);
4094 		} else {
4095 			isl_size size = isl_basic_map_dim(bmap, t);
4096 			if (size < 0)
4097 				dim_map = isl_dim_map_free(dim_map);
4098 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4099 						0, pos, off);
4100 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
4101 						pos, size - pos, off + pos + n);
4102 		}
4103 		dim = isl_space_dim(res_space, t);
4104 		if (dim < 0)
4105 			dim_map = isl_dim_map_free(dim_map);
4106 		off += dim;
4107 	}
4108 	isl_dim_map_div(dim_map, bmap, off);
4109 
4110 	res = isl_basic_map_alloc_space(res_space,
4111 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
4112 	rational = isl_basic_map_is_rational(bmap);
4113 	if (rational < 0)
4114 		res = isl_basic_map_free(res);
4115 	if (rational)
4116 		res = isl_basic_map_set_rational(res);
4117 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4118 	return isl_basic_map_finalize(res);
4119 }
4120 
isl_basic_set_insert_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,unsigned n)4121 __isl_give isl_basic_set *isl_basic_set_insert_dims(
4122 	__isl_take isl_basic_set *bset,
4123 	enum isl_dim_type type, unsigned pos, unsigned n)
4124 {
4125 	return isl_basic_map_insert_dims(bset, type, pos, n);
4126 }
4127 
isl_basic_map_add_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned n)4128 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
4129 		enum isl_dim_type type, unsigned n)
4130 {
4131 	isl_size dim;
4132 
4133 	dim = isl_basic_map_dim(bmap, type);
4134 	if (dim < 0)
4135 		return isl_basic_map_free(bmap);
4136 	return isl_basic_map_insert_dims(bmap, type, dim, n);
4137 }
4138 
isl_basic_set_add_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned n)4139 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
4140 		enum isl_dim_type type, unsigned n)
4141 {
4142 	if (!bset)
4143 		return NULL;
4144 	isl_assert(bset->ctx, type != isl_dim_in, goto error);
4145 	return isl_basic_map_add_dims(bset, type, n);
4146 error:
4147 	isl_basic_set_free(bset);
4148 	return NULL;
4149 }
4150 
map_space_reset(__isl_take isl_map * map,enum isl_dim_type type)4151 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
4152 	enum isl_dim_type type)
4153 {
4154 	isl_space *space;
4155 
4156 	if (!map || !isl_space_is_named_or_nested(map->dim, type))
4157 		return map;
4158 
4159 	space = isl_map_get_space(map);
4160 	space = isl_space_reset(space, type);
4161 	map = isl_map_reset_space(map, space);
4162 	return map;
4163 }
4164 
isl_map_insert_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,unsigned n)4165 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
4166 		enum isl_dim_type type, unsigned pos, unsigned n)
4167 {
4168 	int i;
4169 	isl_space *space;
4170 
4171 	if (n == 0)
4172 		return map_space_reset(map, type);
4173 
4174 	map = isl_map_cow(map);
4175 	if (!map)
4176 		return NULL;
4177 
4178 	for (i = 0; i < map->n; ++i) {
4179 		map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
4180 		if (!map->p[i])
4181 			goto error;
4182 	}
4183 
4184 	space = isl_map_take_space(map);
4185 	space = isl_space_insert_dims(space, type, pos, n);
4186 	map = isl_map_restore_space(map, space);
4187 
4188 	return map;
4189 error:
4190 	isl_map_free(map);
4191 	return NULL;
4192 }
4193 
isl_set_insert_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,unsigned n)4194 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
4195 		enum isl_dim_type type, unsigned pos, unsigned n)
4196 {
4197 	return isl_map_insert_dims(set, type, pos, n);
4198 }
4199 
isl_map_add_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned n)4200 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
4201 		enum isl_dim_type type, unsigned n)
4202 {
4203 	isl_size dim;
4204 
4205 	dim = isl_map_dim(map, type);
4206 	if (dim < 0)
4207 		return isl_map_free(map);
4208 	return isl_map_insert_dims(map, type, dim, n);
4209 }
4210 
isl_set_add_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned n)4211 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
4212 		enum isl_dim_type type, unsigned n)
4213 {
4214 	if (!set)
4215 		return NULL;
4216 	isl_assert(set->ctx, type != isl_dim_in, goto error);
4217 	return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
4218 error:
4219 	isl_set_free(set);
4220 	return NULL;
4221 }
4222 
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)4223 __isl_give isl_basic_map *isl_basic_map_move_dims(
4224 	__isl_take isl_basic_map *bmap,
4225 	enum isl_dim_type dst_type, unsigned dst_pos,
4226 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4227 {
4228 	isl_space *space;
4229 	struct isl_dim_map *dim_map;
4230 	struct isl_basic_map *res;
4231 	enum isl_dim_type t;
4232 	isl_size total;
4233 	unsigned off;
4234 
4235 	if (!bmap)
4236 		return NULL;
4237 	if (n == 0) {
4238 		bmap = isl_basic_map_reset(bmap, src_type);
4239 		bmap = isl_basic_map_reset(bmap, dst_type);
4240 		return bmap;
4241 	}
4242 
4243 	if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
4244 		return isl_basic_map_free(bmap);
4245 
4246 	if (dst_type == src_type && dst_pos == src_pos)
4247 		return bmap;
4248 
4249 	isl_assert(bmap->ctx, dst_type != src_type, goto error);
4250 
4251 	if (pos(bmap->dim, dst_type) + dst_pos ==
4252 	    pos(bmap->dim, src_type) + src_pos +
4253 					    ((src_type < dst_type) ? n : 0)) {
4254 		space = isl_basic_map_take_space(bmap);
4255 		space = isl_space_move_dims(space, dst_type, dst_pos,
4256 						src_type, src_pos, n);
4257 		bmap = isl_basic_map_restore_space(bmap, space);
4258 		bmap = isl_basic_map_finalize(bmap);
4259 
4260 		return bmap;
4261 	}
4262 
4263 	total = isl_basic_map_dim(bmap, isl_dim_all);
4264 	if (total < 0)
4265 		return isl_basic_map_free(bmap);
4266 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
4267 
4268 	off = 0;
4269 	space = isl_basic_map_peek_space(bmap);
4270 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4271 		isl_size size = isl_space_dim(space, t);
4272 		if (size < 0)
4273 			dim_map = isl_dim_map_free(dim_map);
4274 		if (t == dst_type) {
4275 			isl_dim_map_dim_range(dim_map, space, t,
4276 					    0, dst_pos, off);
4277 			off += dst_pos;
4278 			isl_dim_map_dim_range(dim_map, space, src_type,
4279 					    src_pos, n, off);
4280 			off += n;
4281 			isl_dim_map_dim_range(dim_map, space, t,
4282 					    dst_pos, size - dst_pos, off);
4283 			off += size - dst_pos;
4284 		} else if (t == src_type) {
4285 			isl_dim_map_dim_range(dim_map, space, t,
4286 					    0, src_pos, off);
4287 			off += src_pos;
4288 			isl_dim_map_dim_range(dim_map, space, t,
4289 					src_pos + n, size - src_pos - n, off);
4290 			off += size - src_pos - n;
4291 		} else {
4292 			isl_dim_map_dim(dim_map, space, t, off);
4293 			off += size;
4294 		}
4295 	}
4296 	isl_dim_map_div(dim_map, bmap, off);
4297 
4298 	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4299 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
4300 	bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4301 	space = isl_basic_map_take_space(bmap);
4302 	space = isl_space_move_dims(space, dst_type, dst_pos,
4303 					src_type, src_pos, n);
4304 	bmap = isl_basic_map_restore_space(bmap, space);
4305 	if (!bmap)
4306 		goto error;
4307 
4308 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4309 	bmap = isl_basic_map_gauss(bmap, NULL);
4310 	bmap = isl_basic_map_finalize(bmap);
4311 
4312 	return bmap;
4313 error:
4314 	isl_basic_map_free(bmap);
4315 	return NULL;
4316 }
4317 
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)4318 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4319 	enum isl_dim_type dst_type, unsigned dst_pos,
4320 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4321 {
4322 	isl_basic_map *bmap = bset_to_bmap(bset);
4323 	bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4324 					src_type, src_pos, n);
4325 	return bset_from_bmap(bmap);
4326 }
4327 
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)4328 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4329 	enum isl_dim_type dst_type, unsigned dst_pos,
4330 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4331 {
4332 	if (!set)
4333 		return NULL;
4334 	isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4335 	return set_from_map(isl_map_move_dims(set_to_map(set),
4336 				    dst_type, dst_pos, src_type, src_pos, n));
4337 error:
4338 	isl_set_free(set);
4339 	return NULL;
4340 }
4341 
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)4342 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4343 	enum isl_dim_type dst_type, unsigned dst_pos,
4344 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4345 {
4346 	int i;
4347 	isl_space *space;
4348 
4349 	if (n == 0) {
4350 		map = isl_map_reset(map, src_type);
4351 		map = isl_map_reset(map, dst_type);
4352 		return map;
4353 	}
4354 
4355 	if (isl_map_check_range(map, src_type, src_pos, n))
4356 		return isl_map_free(map);
4357 
4358 	if (dst_type == src_type && dst_pos == src_pos)
4359 		return map;
4360 
4361 	isl_assert(map->ctx, dst_type != src_type, goto error);
4362 
4363 	map = isl_map_cow(map);
4364 	if (!map)
4365 		return NULL;
4366 
4367 	for (i = 0; i < map->n; ++i) {
4368 		map->p[i] = isl_basic_map_move_dims(map->p[i],
4369 						dst_type, dst_pos,
4370 						src_type, src_pos, n);
4371 		if (!map->p[i])
4372 			goto error;
4373 	}
4374 
4375 	space = isl_map_take_space(map);
4376 	space = isl_space_move_dims(space, dst_type, dst_pos,
4377 					    src_type, src_pos, n);
4378 	map = isl_map_restore_space(map, space);
4379 
4380 	return map;
4381 error:
4382 	isl_map_free(map);
4383 	return NULL;
4384 }
4385 
4386 /* Move the specified dimensions to the last columns right before
4387  * the divs.  Don't change the dimension specification of bmap.
4388  * That's the responsibility of the caller.
4389  */
move_last(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4390 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4391 	enum isl_dim_type type, unsigned first, unsigned n)
4392 {
4393 	isl_space *space;
4394 	struct isl_dim_map *dim_map;
4395 	struct isl_basic_map *res;
4396 	enum isl_dim_type t;
4397 	isl_size total;
4398 	unsigned off;
4399 
4400 	if (!bmap)
4401 		return NULL;
4402 	if (isl_basic_map_offset(bmap, type) + first + n ==
4403 				isl_basic_map_offset(bmap, isl_dim_div))
4404 		return bmap;
4405 
4406 	total = isl_basic_map_dim(bmap, isl_dim_all);
4407 	if (total < 0)
4408 		return isl_basic_map_free(bmap);
4409 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
4410 
4411 	off = 0;
4412 	space = isl_basic_map_peek_space(bmap);
4413 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4414 		isl_size size = isl_space_dim(space, t);
4415 		if (size < 0)
4416 			dim_map = isl_dim_map_free(dim_map);
4417 		if (t == type) {
4418 			isl_dim_map_dim_range(dim_map, space, t,
4419 					    0, first, off);
4420 			off += first;
4421 			isl_dim_map_dim_range(dim_map, space, t,
4422 					    first, n, total - bmap->n_div - n);
4423 			isl_dim_map_dim_range(dim_map, space, t,
4424 					    first + n, size - (first + n), off);
4425 			off += size - (first + n);
4426 		} else {
4427 			isl_dim_map_dim(dim_map, space, t, off);
4428 			off += size;
4429 		}
4430 	}
4431 	isl_dim_map_div(dim_map, bmap, off + n);
4432 
4433 	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4434 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
4435 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4436 	return res;
4437 }
4438 
4439 /* Insert "n" rows in the divs of "bmap".
4440  *
4441  * The number of columns is not changed, which means that the last
4442  * dimensions of "bmap" are being reintepreted as the new divs.
4443  * The space of "bmap" is not adjusted, however, which means
4444  * that "bmap" is left in an inconsistent state.  Removing "n" dimensions
4445  * from the space of "bmap" is the responsibility of the caller.
4446  */
insert_div_rows(__isl_take isl_basic_map * bmap,int n)4447 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4448 	int n)
4449 {
4450 	int i;
4451 	size_t row_size;
4452 	isl_int **new_div;
4453 	isl_int *old;
4454 
4455 	bmap = isl_basic_map_cow(bmap);
4456 	if (!bmap)
4457 		return NULL;
4458 
4459 	row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;
4460 	old = bmap->block2.data;
4461 	bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4462 					(bmap->extra + n) * (1 + row_size));
4463 	if (!bmap->block2.data)
4464 		return isl_basic_map_free(bmap);
4465 	new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4466 	if (!new_div)
4467 		return isl_basic_map_free(bmap);
4468 	for (i = 0; i < n; ++i) {
4469 		new_div[i] = bmap->block2.data +
4470 				(bmap->extra + i) * (1 + row_size);
4471 		isl_seq_clr(new_div[i], 1 + row_size);
4472 	}
4473 	for (i = 0; i < bmap->extra; ++i)
4474 		new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4475 	free(bmap->div);
4476 	bmap->div = new_div;
4477 	bmap->n_div += n;
4478 	bmap->extra += n;
4479 
4480 	return bmap;
4481 }
4482 
4483 /* Drop constraints from "bmap" that only involve the variables
4484  * of "type" in the range [first, first + n] that are not related
4485  * to any of the variables outside that interval.
4486  * These constraints cannot influence the values for the variables
4487  * outside the interval, except in case they cause "bmap" to be empty.
4488  * Only drop the constraints if "bmap" is known to be non-empty.
4489  */
drop_irrelevant_constraints(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4490 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4491 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
4492 	unsigned first, unsigned n)
4493 {
4494 	int i;
4495 	int *groups;
4496 	isl_size dim, n_div;
4497 	isl_bool non_empty;
4498 
4499 	non_empty = isl_basic_map_plain_is_non_empty(bmap);
4500 	if (non_empty < 0)
4501 		return isl_basic_map_free(bmap);
4502 	if (!non_empty)
4503 		return bmap;
4504 
4505 	dim = isl_basic_map_dim(bmap, isl_dim_all);
4506 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
4507 	if (dim < 0 || n_div < 0)
4508 		return isl_basic_map_free(bmap);
4509 	groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4510 	if (!groups)
4511 		return isl_basic_map_free(bmap);
4512 	first += isl_basic_map_offset(bmap, type) - 1;
4513 	for (i = 0; i < first; ++i)
4514 		groups[i] = -1;
4515 	for (i = first + n; i < dim - n_div; ++i)
4516 		groups[i] = -1;
4517 
4518 	bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4519 
4520 	return bmap;
4521 }
4522 
4523 /* Turn the n dimensions of type type, starting at first
4524  * into existentially quantified variables.
4525  *
4526  * If a subset of the projected out variables are unrelated
4527  * to any of the variables that remain, then the constraints
4528  * involving this subset are simply dropped first.
4529  */
isl_basic_map_project_out(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4530 __isl_give isl_basic_map *isl_basic_map_project_out(
4531 		__isl_take isl_basic_map *bmap,
4532 		enum isl_dim_type type, unsigned first, unsigned n)
4533 {
4534 	isl_bool empty;
4535 	isl_space *space;
4536 
4537 	if (n == 0)
4538 		return basic_map_space_reset(bmap, type);
4539 	if (type == isl_dim_div)
4540 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4541 			"cannot project out existentially quantified variables",
4542 			return isl_basic_map_free(bmap));
4543 
4544 	empty = isl_basic_map_plain_is_empty(bmap);
4545 	if (empty < 0)
4546 		return isl_basic_map_free(bmap);
4547 	if (empty)
4548 		bmap = isl_basic_map_set_to_empty(bmap);
4549 
4550 	bmap = drop_irrelevant_constraints(bmap, type, first, n);
4551 	if (!bmap)
4552 		return NULL;
4553 
4554 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4555 		return isl_basic_map_remove_dims(bmap, type, first, n);
4556 
4557 	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4558 		return isl_basic_map_free(bmap);
4559 
4560 	bmap = move_last(bmap, type, first, n);
4561 	bmap = isl_basic_map_cow(bmap);
4562 	bmap = insert_div_rows(bmap, n);
4563 
4564 	space = isl_basic_map_take_space(bmap);
4565 	space = isl_space_drop_dims(space, type, first, n);
4566 	bmap = isl_basic_map_restore_space(bmap, space);
4567 	bmap = isl_basic_map_simplify(bmap);
4568 	bmap = isl_basic_map_drop_redundant_divs(bmap);
4569 	return isl_basic_map_finalize(bmap);
4570 }
4571 
4572 /* Turn the n dimensions of type type, starting at first
4573  * into existentially quantified variables.
4574  */
isl_basic_set_project_out(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)4575 __isl_give isl_basic_set *isl_basic_set_project_out(
4576 	__isl_take isl_basic_set *bset, enum isl_dim_type type,
4577 	unsigned first, unsigned n)
4578 {
4579 	return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4580 							type, first, n));
4581 }
4582 
4583 /* Turn the n dimensions of type type, starting at first
4584  * into existentially quantified variables.
4585  */
isl_map_project_out(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)4586 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4587 		enum isl_dim_type type, unsigned first, unsigned n)
4588 {
4589 	int i;
4590 	isl_space *space;
4591 
4592 	if (n == 0)
4593 		return map_space_reset(map, type);
4594 
4595 	if (isl_map_check_range(map, type, first, n) < 0)
4596 		return isl_map_free(map);
4597 
4598 	map = isl_map_cow(map);
4599 	if (!map)
4600 		return NULL;
4601 
4602 	for (i = 0; i < map->n; ++i) {
4603 		map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4604 		if (!map->p[i])
4605 			goto error;
4606 	}
4607 
4608 	if (map->n > 1)
4609 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
4610 	map = isl_map_unmark_normalized(map);
4611 
4612 	space = isl_map_take_space(map);
4613 	space = isl_space_drop_dims(space, type, first, n);
4614 	map = isl_map_restore_space(map, space);
4615 
4616 	return map;
4617 error:
4618 	isl_map_free(map);
4619 	return NULL;
4620 }
4621 
4622 #undef TYPE
4623 #define TYPE	isl_map
4624 #include "isl_project_out_all_params_templ.c"
4625 
4626 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4627  * into existentially quantified variables.
4628  */
isl_map_project_onto(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)4629 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4630 	enum isl_dim_type type, unsigned first, unsigned n)
4631 {
4632 	isl_size dim;
4633 
4634 	dim = isl_map_dim(map, type);
4635 	if (isl_map_check_range(map, type, first, n) < 0 || dim < 0)
4636 		return isl_map_free(map);
4637 	map = isl_map_project_out(map, type, first + n, dim - (first + n));
4638 	map = isl_map_project_out(map, type, 0, first);
4639 	return map;
4640 }
4641 
4642 /* Turn the n dimensions of type type, starting at first
4643  * into existentially quantified variables.
4644  */
isl_set_project_out(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)4645 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4646 		enum isl_dim_type type, unsigned first, unsigned n)
4647 {
4648 	return set_from_map(isl_map_project_out(set_to_map(set),
4649 						type, first, n));
4650 }
4651 
4652 /* If "set" involves a parameter with identifier "id",
4653  * then turn it into an existentially quantified variable.
4654  */
isl_set_project_out_param_id(__isl_take isl_set * set,__isl_take isl_id * id)4655 __isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,
4656 	__isl_take isl_id *id)
4657 {
4658 	int pos;
4659 
4660 	if (!set || !id)
4661 		goto error;
4662 	pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
4663 	isl_id_free(id);
4664 	if (pos < 0)
4665 		return set;
4666 	return isl_set_project_out(set, isl_dim_param, pos, 1);
4667 error:
4668 	isl_set_free(set);
4669 	isl_id_free(id);
4670 	return NULL;
4671 }
4672 
4673 /* If "set" involves any of the parameters with identifiers in "list",
4674  * then turn them into existentially quantified variables.
4675  */
isl_set_project_out_param_id_list(__isl_take isl_set * set,__isl_take isl_id_list * list)4676 __isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,
4677 	__isl_take isl_id_list *list)
4678 {
4679 	int i;
4680 	isl_size n;
4681 
4682 	n = isl_id_list_size(list);
4683 	if (n < 0)
4684 		goto error;
4685 	for (i = 0; i < n; ++i) {
4686 		isl_id *id;
4687 
4688 		id = isl_id_list_get_at(list, i);
4689 		set = isl_set_project_out_param_id(set, id);
4690 	}
4691 
4692 	isl_id_list_free(list);
4693 	return set;
4694 error:
4695 	isl_id_list_free(list);
4696 	isl_set_free(set);
4697 	return NULL;
4698 }
4699 
4700 /* Project out all parameters from "set" by existentially quantifying
4701  * over them.
4702  */
isl_set_project_out_all_params(__isl_take isl_set * set)4703 __isl_give isl_set *isl_set_project_out_all_params(__isl_take isl_set *set)
4704 {
4705 	return set_from_map(isl_map_project_out_all_params(set_to_map(set)));
4706 }
4707 
4708 /* Return a map that projects the elements in "set" onto their
4709  * "n" set dimensions starting at "first".
4710  * "type" should be equal to isl_dim_set.
4711  */
isl_set_project_onto_map(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)4712 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4713 	enum isl_dim_type type, unsigned first, unsigned n)
4714 {
4715 	int i;
4716 	isl_map *map;
4717 
4718 	if (type != isl_dim_set)
4719 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
4720 			"only set dimensions can be projected out", goto error);
4721 	if (isl_set_check_range(set, type, first, n) < 0)
4722 		return isl_set_free(set);
4723 
4724 	map = isl_map_from_domain(set);
4725 	map = isl_map_add_dims(map, isl_dim_out, n);
4726 	for (i = 0; i < n; ++i)
4727 		map = isl_map_equate(map, isl_dim_in, first + i,
4728 					isl_dim_out, i);
4729 	return map;
4730 error:
4731 	isl_set_free(set);
4732 	return NULL;
4733 }
4734 
add_divs(__isl_take isl_basic_map * bmap,unsigned n)4735 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4736 	unsigned n)
4737 {
4738 	int i, j;
4739 	isl_size total;
4740 
4741 	total = isl_basic_map_dim(bmap, isl_dim_all);
4742 	if (total < 0)
4743 		return isl_basic_map_free(bmap);
4744 	for (i = 0; i < n; ++i) {
4745 		j = isl_basic_map_alloc_div(bmap);
4746 		if (j < 0)
4747 			goto error;
4748 		isl_seq_clr(bmap->div[j], 1 + 1 + total);
4749 	}
4750 	return bmap;
4751 error:
4752 	isl_basic_map_free(bmap);
4753 	return NULL;
4754 }
4755 
4756 /* Does "bmap2" apply to the range of "bmap1" (ignoring parameters)?
4757  */
isl_basic_map_applies_range(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)4758 isl_bool isl_basic_map_applies_range(__isl_keep isl_basic_map *bmap1,
4759 	__isl_keep isl_basic_map *bmap2)
4760 {
4761 	isl_space *space1, *space2;
4762 
4763 	space1 = isl_basic_map_peek_space(bmap1);
4764 	space2 = isl_basic_map_peek_space(bmap2);
4765 	return isl_space_tuple_is_equal(space1, isl_dim_out,
4766 					space2, isl_dim_in);
4767 }
4768 
4769 /* Check that "bmap2" applies to the range of "bmap1" (ignoring parameters).
4770  */
isl_basic_map_check_applies_range(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)4771 static isl_stat isl_basic_map_check_applies_range(
4772 	__isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
4773 {
4774 	isl_bool equal;
4775 
4776 	equal = isl_basic_map_applies_range(bmap1, bmap2);
4777 	if (equal < 0)
4778 		return isl_stat_error;
4779 	if (!equal)
4780 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4781 			"spaces don't match", return isl_stat_error);
4782 	return isl_stat_ok;
4783 }
4784 
isl_basic_map_apply_range(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4785 __isl_give isl_basic_map *isl_basic_map_apply_range(
4786 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
4787 {
4788 	isl_space *space_result = NULL;
4789 	struct isl_basic_map *bmap;
4790 	isl_size n_in, n_out, n, nparam;
4791 	unsigned total, pos;
4792 	struct isl_dim_map *dim_map1, *dim_map2;
4793 
4794 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4795 		goto error;
4796 	if (isl_basic_map_check_applies_range(bmap1, bmap2) < 0)
4797 		goto error;
4798 
4799 	n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4800 	n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4801 	n = isl_basic_map_dim(bmap1, isl_dim_out);
4802 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4803 	if (n_in < 0 || n_out < 0 || n < 0 || nparam < 0)
4804 		goto error;
4805 
4806 	space_result = isl_space_join(isl_basic_map_get_space(bmap1),
4807 				  isl_basic_map_get_space(bmap2));
4808 
4809 	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4810 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4811 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4812 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4813 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4814 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4815 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4816 	isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4817 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4818 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4819 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4820 
4821 	bmap = isl_basic_map_alloc_space(space_result,
4822 			bmap1->n_div + bmap2->n_div + n,
4823 			bmap1->n_eq + bmap2->n_eq,
4824 			bmap1->n_ineq + bmap2->n_ineq);
4825 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4826 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4827 	bmap = add_divs(bmap, n);
4828 	bmap = isl_basic_map_simplify(bmap);
4829 	bmap = isl_basic_map_drop_redundant_divs(bmap);
4830 	return isl_basic_map_finalize(bmap);
4831 error:
4832 	isl_basic_map_free(bmap1);
4833 	isl_basic_map_free(bmap2);
4834 	return NULL;
4835 }
4836 
isl_basic_set_apply(__isl_take isl_basic_set * bset,__isl_take isl_basic_map * bmap)4837 __isl_give isl_basic_set *isl_basic_set_apply(__isl_take isl_basic_set *bset,
4838 	__isl_take isl_basic_map *bmap)
4839 {
4840 	if (isl_basic_map_check_compatible_domain(bmap, bset) < 0)
4841 		goto error;
4842 
4843 	return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4844 							bmap));
4845 error:
4846 	isl_basic_set_free(bset);
4847 	isl_basic_map_free(bmap);
4848 	return NULL;
4849 }
4850 
isl_basic_map_apply_domain(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4851 __isl_give isl_basic_map *isl_basic_map_apply_domain(
4852 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
4853 {
4854 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4855 		goto error;
4856 	if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4857 					bmap2->dim, isl_dim_in))
4858 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4859 			"spaces don't match", goto error);
4860 
4861 	bmap1 = isl_basic_map_reverse(bmap1);
4862 	bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4863 	return isl_basic_map_reverse(bmap1);
4864 error:
4865 	isl_basic_map_free(bmap1);
4866 	isl_basic_map_free(bmap2);
4867 	return NULL;
4868 }
4869 
4870 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4871  * A \cap B -> f(A) + f(B)
4872  */
isl_basic_map_sum(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4873 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4874 	__isl_take isl_basic_map *bmap2)
4875 {
4876 	isl_size n_in, n_out, nparam;
4877 	unsigned total, pos;
4878 	struct isl_basic_map *bmap = NULL;
4879 	struct isl_dim_map *dim_map1, *dim_map2;
4880 	int i;
4881 
4882 	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
4883 		goto error;
4884 
4885 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4886 	n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4887 	n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4888 	if (nparam < 0 || n_in < 0 || n_out < 0)
4889 		goto error;
4890 
4891 	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4892 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4893 	dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4894 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4895 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4896 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4897 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4898 	isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4899 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4900 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4901 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4902 
4903 	bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4904 			bmap1->n_div + bmap2->n_div + 2 * n_out,
4905 			bmap1->n_eq + bmap2->n_eq + n_out,
4906 			bmap1->n_ineq + bmap2->n_ineq);
4907 	for (i = 0; i < n_out; ++i) {
4908 		int j = isl_basic_map_alloc_equality(bmap);
4909 		if (j < 0)
4910 			goto error;
4911 		isl_seq_clr(bmap->eq[j], 1+total);
4912 		isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4913 		isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4914 		isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4915 	}
4916 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4917 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4918 	bmap = add_divs(bmap, 2 * n_out);
4919 
4920 	bmap = isl_basic_map_simplify(bmap);
4921 	return isl_basic_map_finalize(bmap);
4922 error:
4923 	isl_basic_map_free(bmap);
4924 	isl_basic_map_free(bmap1);
4925 	isl_basic_map_free(bmap2);
4926 	return NULL;
4927 }
4928 
4929 /* Given two maps A -> f(A) and B -> g(B), construct a map
4930  * A \cap B -> f(A) + f(B)
4931  */
isl_map_sum(__isl_take isl_map * map1,__isl_take isl_map * map2)4932 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4933 	__isl_take isl_map *map2)
4934 {
4935 	struct isl_map *result;
4936 	int i, j;
4937 
4938 	if (isl_map_check_equal_space(map1, map2) < 0)
4939 		goto error;
4940 
4941 	result = isl_map_alloc_space(isl_space_copy(map1->dim),
4942 				map1->n * map2->n, 0);
4943 	if (!result)
4944 		goto error;
4945 	for (i = 0; i < map1->n; ++i)
4946 		for (j = 0; j < map2->n; ++j) {
4947 			struct isl_basic_map *part;
4948 			part = isl_basic_map_sum(
4949 				    isl_basic_map_copy(map1->p[i]),
4950 				    isl_basic_map_copy(map2->p[j]));
4951 			if (isl_basic_map_is_empty(part))
4952 				isl_basic_map_free(part);
4953 			else
4954 				result = isl_map_add_basic_map(result, part);
4955 			if (!result)
4956 				goto error;
4957 		}
4958 	isl_map_free(map1);
4959 	isl_map_free(map2);
4960 	return result;
4961 error:
4962 	isl_map_free(map1);
4963 	isl_map_free(map2);
4964 	return NULL;
4965 }
4966 
isl_set_sum(__isl_take isl_set * set1,__isl_take isl_set * set2)4967 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4968 	__isl_take isl_set *set2)
4969 {
4970 	return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4971 }
4972 
4973 /* Given a basic map A -> f(A), construct A -> -f(A).
4974  */
isl_basic_map_neg(__isl_take isl_basic_map * bmap)4975 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4976 {
4977 	int i, j;
4978 	unsigned off;
4979 	isl_size n;
4980 
4981 	bmap = isl_basic_map_cow(bmap);
4982 	n = isl_basic_map_dim(bmap, isl_dim_out);
4983 	if (n < 0)
4984 		return isl_basic_map_free(bmap);
4985 
4986 	off = isl_basic_map_offset(bmap, isl_dim_out);
4987 	for (i = 0; i < bmap->n_eq; ++i)
4988 		for (j = 0; j < n; ++j)
4989 			isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4990 	for (i = 0; i < bmap->n_ineq; ++i)
4991 		for (j = 0; j < n; ++j)
4992 			isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4993 	for (i = 0; i < bmap->n_div; ++i)
4994 		for (j = 0; j < n; ++j)
4995 			isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4996 	bmap = isl_basic_map_gauss(bmap, NULL);
4997 	return isl_basic_map_finalize(bmap);
4998 }
4999 
isl_basic_set_neg(__isl_take isl_basic_set * bset)5000 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
5001 {
5002 	return isl_basic_map_neg(bset);
5003 }
5004 
5005 /* Given a map A -> f(A), construct A -> -f(A).
5006  */
isl_map_neg(__isl_take isl_map * map)5007 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
5008 {
5009 	int i;
5010 
5011 	map = isl_map_cow(map);
5012 	if (!map)
5013 		return NULL;
5014 
5015 	for (i = 0; i < map->n; ++i) {
5016 		map->p[i] = isl_basic_map_neg(map->p[i]);
5017 		if (!map->p[i])
5018 			goto error;
5019 	}
5020 
5021 	return map;
5022 error:
5023 	isl_map_free(map);
5024 	return NULL;
5025 }
5026 
isl_set_neg(__isl_take isl_set * set)5027 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
5028 {
5029 	return set_from_map(isl_map_neg(set_to_map(set)));
5030 }
5031 
5032 /* Given a basic map A -> f(A) and an integer d, construct a basic map
5033  * A -> floor(f(A)/d).
5034  */
isl_basic_map_floordiv(__isl_take isl_basic_map * bmap,isl_int d)5035 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
5036 		isl_int d)
5037 {
5038 	isl_size n_in, n_out, nparam;
5039 	unsigned total, pos;
5040 	struct isl_basic_map *result = NULL;
5041 	struct isl_dim_map *dim_map;
5042 	int i;
5043 
5044 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5045 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5046 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
5047 	if (nparam < 0 || n_in < 0 || n_out < 0)
5048 		return isl_basic_map_free(bmap);
5049 
5050 	total = nparam + n_in + n_out + bmap->n_div + n_out;
5051 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
5052 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
5053 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
5054 	isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
5055 	isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
5056 
5057 	result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
5058 			bmap->n_div + n_out,
5059 			bmap->n_eq, bmap->n_ineq + 2 * n_out);
5060 	result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
5061 	result = add_divs(result, n_out);
5062 	for (i = 0; i < n_out; ++i) {
5063 		int j;
5064 		j = isl_basic_map_alloc_inequality(result);
5065 		if (j < 0)
5066 			goto error;
5067 		isl_seq_clr(result->ineq[j], 1+total);
5068 		isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
5069 		isl_int_set_si(result->ineq[j][1+pos+i], 1);
5070 		j = isl_basic_map_alloc_inequality(result);
5071 		if (j < 0)
5072 			goto error;
5073 		isl_seq_clr(result->ineq[j], 1+total);
5074 		isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
5075 		isl_int_set_si(result->ineq[j][1+pos+i], -1);
5076 		isl_int_sub_ui(result->ineq[j][0], d, 1);
5077 	}
5078 
5079 	result = isl_basic_map_simplify(result);
5080 	return isl_basic_map_finalize(result);
5081 error:
5082 	isl_basic_map_free(result);
5083 	return NULL;
5084 }
5085 
5086 /* Given a map A -> f(A) and an integer d, construct a map
5087  * A -> floor(f(A)/d).
5088  */
isl_map_floordiv(__isl_take isl_map * map,isl_int d)5089 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
5090 {
5091 	int i;
5092 
5093 	map = isl_map_cow(map);
5094 	if (!map)
5095 		return NULL;
5096 
5097 	ISL_F_CLR(map, ISL_MAP_DISJOINT);
5098 	for (i = 0; i < map->n; ++i) {
5099 		map->p[i] = isl_basic_map_floordiv(map->p[i], d);
5100 		if (!map->p[i])
5101 			goto error;
5102 	}
5103 	map = isl_map_unmark_normalized(map);
5104 
5105 	return map;
5106 error:
5107 	isl_map_free(map);
5108 	return NULL;
5109 }
5110 
5111 /* Given a map A -> f(A) and an integer d, construct a map
5112  * A -> floor(f(A)/d).
5113  */
isl_map_floordiv_val(__isl_take isl_map * map,__isl_take isl_val * d)5114 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
5115 	__isl_take isl_val *d)
5116 {
5117 	if (!map || !d)
5118 		goto error;
5119 	if (!isl_val_is_int(d))
5120 		isl_die(isl_val_get_ctx(d), isl_error_invalid,
5121 			"expecting integer denominator", goto error);
5122 	map = isl_map_floordiv(map, d->n);
5123 	isl_val_free(d);
5124 	return map;
5125 error:
5126 	isl_map_free(map);
5127 	isl_val_free(d);
5128 	return NULL;
5129 }
5130 
var_equal(__isl_take isl_basic_map * bmap,unsigned pos)5131 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
5132 	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_equality(bmap);
5145 	if (i < 0)
5146 		goto error;
5147 	isl_seq_clr(bmap->eq[i], 1 + total);
5148 	isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
5149 	isl_int_set_si(bmap->eq[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 
5156 /* Add a constraint to "bmap" expressing i_pos < o_pos
5157  */
var_less(__isl_take isl_basic_map * bmap,unsigned pos)5158 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
5159 	unsigned pos)
5160 {
5161 	int i;
5162 	isl_size nparam;
5163 	isl_size n_in;
5164 	isl_size total;
5165 
5166 	total = isl_basic_map_dim(bmap, isl_dim_all);
5167 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5168 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5169 	if (total < 0 || nparam < 0 || n_in < 0)
5170 		return isl_basic_map_free(bmap);
5171 	i = isl_basic_map_alloc_inequality(bmap);
5172 	if (i < 0)
5173 		goto error;
5174 	isl_seq_clr(bmap->ineq[i], 1 + total);
5175 	isl_int_set_si(bmap->ineq[i][0], -1);
5176 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5177 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5178 	return isl_basic_map_finalize(bmap);
5179 error:
5180 	isl_basic_map_free(bmap);
5181 	return NULL;
5182 }
5183 
5184 /* Add a constraint to "bmap" expressing i_pos <= o_pos
5185  */
var_less_or_equal(__isl_take isl_basic_map * bmap,unsigned pos)5186 static __isl_give isl_basic_map *var_less_or_equal(
5187 	__isl_take isl_basic_map *bmap, unsigned pos)
5188 {
5189 	int i;
5190 	isl_size nparam;
5191 	isl_size n_in;
5192 	isl_size total;
5193 
5194 	total = isl_basic_map_dim(bmap, isl_dim_all);
5195 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5196 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5197 	if (total < 0 || nparam < 0 || n_in < 0)
5198 		return isl_basic_map_free(bmap);
5199 	i = isl_basic_map_alloc_inequality(bmap);
5200 	if (i < 0)
5201 		goto error;
5202 	isl_seq_clr(bmap->ineq[i], 1 + total);
5203 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5204 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5205 	return isl_basic_map_finalize(bmap);
5206 error:
5207 	isl_basic_map_free(bmap);
5208 	return NULL;
5209 }
5210 
5211 /* Add a constraint to "bmap" expressing i_pos > o_pos
5212  */
var_more(__isl_take isl_basic_map * bmap,unsigned pos)5213 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
5214 	unsigned pos)
5215 {
5216 	int i;
5217 	isl_size nparam;
5218 	isl_size n_in;
5219 	isl_size total;
5220 
5221 	total = isl_basic_map_dim(bmap, isl_dim_all);
5222 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5223 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5224 	if (total < 0 || nparam < 0 || n_in < 0)
5225 		return isl_basic_map_free(bmap);
5226 	i = isl_basic_map_alloc_inequality(bmap);
5227 	if (i < 0)
5228 		goto error;
5229 	isl_seq_clr(bmap->ineq[i], 1 + total);
5230 	isl_int_set_si(bmap->ineq[i][0], -1);
5231 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5232 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5233 	return isl_basic_map_finalize(bmap);
5234 error:
5235 	isl_basic_map_free(bmap);
5236 	return NULL;
5237 }
5238 
5239 /* Add a constraint to "bmap" expressing i_pos >= o_pos
5240  */
var_more_or_equal(__isl_take isl_basic_map * bmap,unsigned pos)5241 static __isl_give isl_basic_map *var_more_or_equal(
5242 	__isl_take isl_basic_map *bmap, unsigned pos)
5243 {
5244 	int i;
5245 	isl_size nparam;
5246 	isl_size n_in;
5247 	isl_size total;
5248 
5249 	total = isl_basic_map_dim(bmap, isl_dim_all);
5250 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
5251 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
5252 	if (total < 0 || nparam < 0 || n_in < 0)
5253 		return isl_basic_map_free(bmap);
5254 	i = isl_basic_map_alloc_inequality(bmap);
5255 	if (i < 0)
5256 		goto error;
5257 	isl_seq_clr(bmap->ineq[i], 1 + total);
5258 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5259 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5260 	return isl_basic_map_finalize(bmap);
5261 error:
5262 	isl_basic_map_free(bmap);
5263 	return NULL;
5264 }
5265 
isl_basic_map_equal(__isl_take isl_space * space,unsigned n_equal)5266 __isl_give isl_basic_map *isl_basic_map_equal(
5267 	__isl_take isl_space *space, unsigned n_equal)
5268 {
5269 	int i;
5270 	struct isl_basic_map *bmap;
5271 	bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
5272 	if (!bmap)
5273 		return NULL;
5274 	for (i = 0; i < n_equal && bmap; ++i)
5275 		bmap = var_equal(bmap, i);
5276 	return isl_basic_map_finalize(bmap);
5277 }
5278 
5279 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
5280  */
isl_basic_map_less_at(__isl_take isl_space * space,unsigned pos)5281 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
5282 	unsigned pos)
5283 {
5284 	int i;
5285 	struct isl_basic_map *bmap;
5286 	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5287 	if (!bmap)
5288 		return NULL;
5289 	for (i = 0; i < pos && bmap; ++i)
5290 		bmap = var_equal(bmap, i);
5291 	if (bmap)
5292 		bmap = var_less(bmap, pos);
5293 	return isl_basic_map_finalize(bmap);
5294 }
5295 
5296 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
5297  */
isl_basic_map_less_or_equal_at(__isl_take isl_space * space,unsigned pos)5298 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
5299 	__isl_take isl_space *space, unsigned pos)
5300 {
5301 	int i;
5302 	isl_basic_map *bmap;
5303 
5304 	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5305 	for (i = 0; i < pos; ++i)
5306 		bmap = var_equal(bmap, i);
5307 	bmap = var_less_or_equal(bmap, pos);
5308 	return isl_basic_map_finalize(bmap);
5309 }
5310 
5311 /* Return a relation on "space" expressing i_pos > o_pos
5312  */
isl_basic_map_more_at(__isl_take isl_space * space,unsigned pos)5313 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
5314 	unsigned pos)
5315 {
5316 	int i;
5317 	struct isl_basic_map *bmap;
5318 	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5319 	if (!bmap)
5320 		return NULL;
5321 	for (i = 0; i < pos && bmap; ++i)
5322 		bmap = var_equal(bmap, i);
5323 	if (bmap)
5324 		bmap = var_more(bmap, pos);
5325 	return isl_basic_map_finalize(bmap);
5326 }
5327 
5328 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
5329  */
isl_basic_map_more_or_equal_at(__isl_take isl_space * space,unsigned pos)5330 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
5331 	__isl_take isl_space *space, unsigned pos)
5332 {
5333 	int i;
5334 	isl_basic_map *bmap;
5335 
5336 	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5337 	for (i = 0; i < pos; ++i)
5338 		bmap = var_equal(bmap, i);
5339 	bmap = var_more_or_equal(bmap, pos);
5340 	return isl_basic_map_finalize(bmap);
5341 }
5342 
map_lex_lte_first(__isl_take isl_space * space,unsigned n,int equal)5343 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
5344 	unsigned n, int equal)
5345 {
5346 	struct isl_map *map;
5347 	int i;
5348 
5349 	if (n == 0 && equal)
5350 		return isl_map_universe(space);
5351 
5352 	map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5353 
5354 	for (i = 0; i + 1 < n; ++i)
5355 		map = isl_map_add_basic_map(map,
5356 				  isl_basic_map_less_at(isl_space_copy(space), i));
5357 	if (n > 0) {
5358 		if (equal)
5359 			map = isl_map_add_basic_map(map,
5360 			      isl_basic_map_less_or_equal_at(space, n - 1));
5361 		else
5362 			map = isl_map_add_basic_map(map,
5363 			      isl_basic_map_less_at(space, n - 1));
5364 	} else
5365 		isl_space_free(space);
5366 
5367 	return map;
5368 }
5369 
map_lex_lte(__isl_take isl_space * space,int equal)5370 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
5371 {
5372 	if (!space)
5373 		return NULL;
5374 	return map_lex_lte_first(space, space->n_out, equal);
5375 }
5376 
isl_map_lex_lt_first(__isl_take isl_space * space,unsigned n)5377 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *space,
5378 	unsigned n)
5379 {
5380 	return map_lex_lte_first(space, n, 0);
5381 }
5382 
isl_map_lex_le_first(__isl_take isl_space * space,unsigned n)5383 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *space,
5384 	unsigned n)
5385 {
5386 	return map_lex_lte_first(space, n, 1);
5387 }
5388 
isl_map_lex_lt(__isl_take isl_space * set_space)5389 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_space)
5390 {
5391 	return map_lex_lte(isl_space_map_from_set(set_space), 0);
5392 }
5393 
isl_map_lex_le(__isl_take isl_space * set_space)5394 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_space)
5395 {
5396 	return map_lex_lte(isl_space_map_from_set(set_space), 1);
5397 }
5398 
map_lex_gte_first(__isl_take isl_space * space,unsigned n,int equal)5399 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5400 	unsigned n, int equal)
5401 {
5402 	struct isl_map *map;
5403 	int i;
5404 
5405 	if (n == 0 && equal)
5406 		return isl_map_universe(space);
5407 
5408 	map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5409 
5410 	for (i = 0; i + 1 < n; ++i)
5411 		map = isl_map_add_basic_map(map,
5412 				  isl_basic_map_more_at(isl_space_copy(space), i));
5413 	if (n > 0) {
5414 		if (equal)
5415 			map = isl_map_add_basic_map(map,
5416 			      isl_basic_map_more_or_equal_at(space, n - 1));
5417 		else
5418 			map = isl_map_add_basic_map(map,
5419 			      isl_basic_map_more_at(space, n - 1));
5420 	} else
5421 		isl_space_free(space);
5422 
5423 	return map;
5424 }
5425 
map_lex_gte(__isl_take isl_space * space,int equal)5426 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5427 {
5428 	if (!space)
5429 		return NULL;
5430 	return map_lex_gte_first(space, space->n_out, equal);
5431 }
5432 
isl_map_lex_gt_first(__isl_take isl_space * space,unsigned n)5433 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *space,
5434 	unsigned n)
5435 {
5436 	return map_lex_gte_first(space, n, 0);
5437 }
5438 
isl_map_lex_ge_first(__isl_take isl_space * space,unsigned n)5439 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *space,
5440 	unsigned n)
5441 {
5442 	return map_lex_gte_first(space, n, 1);
5443 }
5444 
isl_map_lex_gt(__isl_take isl_space * set_space)5445 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_space)
5446 {
5447 	return map_lex_gte(isl_space_map_from_set(set_space), 0);
5448 }
5449 
isl_map_lex_ge(__isl_take isl_space * set_space)5450 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_space)
5451 {
5452 	return map_lex_gte(isl_space_map_from_set(set_space), 1);
5453 }
5454 
isl_set_lex_le_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5455 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5456 	__isl_take isl_set *set2)
5457 {
5458 	isl_map *map;
5459 	map = isl_map_lex_le(isl_set_get_space(set1));
5460 	map = isl_map_intersect_domain(map, set1);
5461 	map = isl_map_intersect_range(map, set2);
5462 	return map;
5463 }
5464 
isl_set_lex_lt_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5465 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5466 	__isl_take isl_set *set2)
5467 {
5468 	isl_map *map;
5469 	map = isl_map_lex_lt(isl_set_get_space(set1));
5470 	map = isl_map_intersect_domain(map, set1);
5471 	map = isl_map_intersect_range(map, set2);
5472 	return map;
5473 }
5474 
isl_set_lex_ge_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5475 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5476 	__isl_take isl_set *set2)
5477 {
5478 	isl_map *map;
5479 	map = isl_map_lex_ge(isl_set_get_space(set1));
5480 	map = isl_map_intersect_domain(map, set1);
5481 	map = isl_map_intersect_range(map, set2);
5482 	return map;
5483 }
5484 
isl_set_lex_gt_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5485 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5486 	__isl_take isl_set *set2)
5487 {
5488 	isl_map *map;
5489 	map = isl_map_lex_gt(isl_set_get_space(set1));
5490 	map = isl_map_intersect_domain(map, set1);
5491 	map = isl_map_intersect_range(map, set2);
5492 	return map;
5493 }
5494 
isl_map_lex_le_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5495 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5496 	__isl_take isl_map *map2)
5497 {
5498 	isl_map *map;
5499 	map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5500 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5501 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5502 	return map;
5503 }
5504 
isl_map_lex_lt_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5505 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5506 	__isl_take isl_map *map2)
5507 {
5508 	isl_map *map;
5509 	map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5510 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5511 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5512 	return map;
5513 }
5514 
isl_map_lex_ge_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5515 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5516 	__isl_take isl_map *map2)
5517 {
5518 	isl_map *map;
5519 	map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5520 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5521 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5522 	return map;
5523 }
5524 
isl_map_lex_gt_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5525 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5526 	__isl_take isl_map *map2)
5527 {
5528 	isl_map *map;
5529 	map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5530 	map = isl_map_apply_domain(map, isl_map_reverse(map1));
5531 	map = isl_map_apply_range(map, isl_map_reverse(map2));
5532 	return map;
5533 }
5534 
5535 /* For the div d = floor(f/m) at position "div", add the constraint
5536  *
5537  *		f - m d >= 0
5538  */
add_upper_div_constraint(__isl_take isl_basic_map * bmap,unsigned div)5539 static __isl_give isl_basic_map *add_upper_div_constraint(
5540 	__isl_take isl_basic_map *bmap, unsigned div)
5541 {
5542 	int i;
5543 	isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5544 	isl_size n_div;
5545 	unsigned pos;
5546 
5547 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
5548 	if (v_div < 0 || n_div < 0)
5549 		return isl_basic_map_free(bmap);
5550 	pos = v_div + div;
5551 	i = isl_basic_map_alloc_inequality(bmap);
5552 	if (i < 0)
5553 		return isl_basic_map_free(bmap);
5554 	isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5555 	isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5556 
5557 	return bmap;
5558 }
5559 
5560 /* For the div d = floor(f/m) at position "div", add the constraint
5561  *
5562  *		-(f-(m-1)) + m d >= 0
5563  */
add_lower_div_constraint(__isl_take isl_basic_map * bmap,unsigned div)5564 static __isl_give isl_basic_map *add_lower_div_constraint(
5565 	__isl_take isl_basic_map *bmap, unsigned div)
5566 {
5567 	int i;
5568 	isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5569 	isl_size n_div;
5570 	unsigned pos;
5571 
5572 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
5573 	if (v_div < 0 || n_div < 0)
5574 		return isl_basic_map_free(bmap);
5575 	pos = v_div + div;
5576 	i = isl_basic_map_alloc_inequality(bmap);
5577 	if (i < 0)
5578 		return isl_basic_map_free(bmap);
5579 	isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5580 	isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5581 	isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5582 	isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5583 
5584 	return bmap;
5585 }
5586 
5587 /* For the div d = floor(f/m) at position "pos", add the constraints
5588  *
5589  *		f - m d >= 0
5590  *		-(f-(m-1)) + m d >= 0
5591  *
5592  * Note that the second constraint is the negation of
5593  *
5594  *		f - m d >= m
5595  */
isl_basic_map_add_div_constraints(__isl_take isl_basic_map * bmap,unsigned pos)5596 __isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5597 	__isl_take isl_basic_map *bmap, unsigned pos)
5598 {
5599 	bmap = add_upper_div_constraint(bmap, pos);
5600 	bmap = add_lower_div_constraint(bmap, pos);
5601 	return bmap;
5602 }
5603 
5604 /* For each known div d = floor(f/m), add the constraints
5605  *
5606  *		f - m d >= 0
5607  *		-(f-(m-1)) + m d >= 0
5608  *
5609  * Remove duplicate constraints in case of some these div constraints
5610  * already appear in "bmap".
5611  */
isl_basic_map_add_known_div_constraints(__isl_take isl_basic_map * bmap)5612 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5613 	__isl_take isl_basic_map *bmap)
5614 {
5615 	isl_size n_div;
5616 
5617 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
5618 	if (n_div < 0)
5619 		return isl_basic_map_free(bmap);
5620 	if (n_div == 0)
5621 		return bmap;
5622 
5623 	bmap = add_known_div_constraints(bmap);
5624 	bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5625 	bmap = isl_basic_map_finalize(bmap);
5626 	return bmap;
5627 }
5628 
5629 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5630  *
5631  * In particular, if this div is of the form d = floor(f/m),
5632  * then add the constraint
5633  *
5634  *		f - m d >= 0
5635  *
5636  * if sign < 0 or the constraint
5637  *
5638  *		-(f-(m-1)) + m d >= 0
5639  *
5640  * if sign > 0.
5641  */
isl_basic_map_add_div_constraint(__isl_take isl_basic_map * bmap,unsigned div,int sign)5642 __isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5643 	__isl_take isl_basic_map *bmap, unsigned div, int sign)
5644 {
5645 	if (sign < 0)
5646 		return add_upper_div_constraint(bmap, div);
5647 	else
5648 		return add_lower_div_constraint(bmap, div);
5649 }
5650 
isl_basic_map_underlying_set(__isl_take isl_basic_map * bmap)5651 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5652 	__isl_take isl_basic_map *bmap)
5653 {
5654 	isl_space *space;
5655 
5656 	if (!bmap)
5657 		goto error;
5658 	if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5659 	    bmap->n_div == 0 &&
5660 	    !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5661 	    !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5662 		return bset_from_bmap(bmap);
5663 	bmap = isl_basic_map_cow(bmap);
5664 	if (!bmap)
5665 		return NULL;
5666 	space = isl_basic_map_take_space(bmap);
5667 	space = isl_space_underlying(space, bmap->n_div);
5668 	bmap = isl_basic_map_restore_space(bmap, space);
5669 	if (!bmap)
5670 		return NULL;
5671 	bmap->extra -= bmap->n_div;
5672 	bmap->n_div = 0;
5673 	bmap = isl_basic_map_finalize(bmap);
5674 	return bset_from_bmap(bmap);
5675 error:
5676 	isl_basic_map_free(bmap);
5677 	return NULL;
5678 }
5679 
isl_basic_set_underlying_set(__isl_take isl_basic_set * bset)5680 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5681 		__isl_take isl_basic_set *bset)
5682 {
5683 	return isl_basic_map_underlying_set(bset_to_bmap(bset));
5684 }
5685 
5686 /* Replace each element in "list" by the result of applying
5687  * isl_basic_map_underlying_set to the element.
5688  */
isl_basic_map_list_underlying_set(__isl_take isl_basic_map_list * list)5689 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5690 	__isl_take isl_basic_map_list *list)
5691 {
5692 	int i;
5693 	isl_size n;
5694 
5695 	n = isl_basic_map_list_n_basic_map(list);
5696 	if (n < 0)
5697 		goto error;
5698 
5699 	for (i = 0; i < n; ++i) {
5700 		isl_basic_map *bmap;
5701 		isl_basic_set *bset;
5702 
5703 		bmap = isl_basic_map_list_get_basic_map(list, i);
5704 		bset = isl_basic_set_underlying_set(bmap);
5705 		list = isl_basic_set_list_set_basic_set(list, i, bset);
5706 	}
5707 
5708 	return list;
5709 error:
5710 	isl_basic_map_list_free(list);
5711 	return NULL;
5712 }
5713 
isl_basic_map_overlying_set(__isl_take isl_basic_set * bset,__isl_take isl_basic_map * like)5714 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5715 	__isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5716 {
5717 	struct isl_basic_map *bmap;
5718 	struct isl_ctx *ctx;
5719 	isl_size dim, bmap_total;
5720 	unsigned total;
5721 	int i;
5722 
5723 	if (!bset || !like)
5724 		goto error;
5725 	ctx = bset->ctx;
5726 	if (isl_basic_set_check_no_params(bset) < 0 ||
5727 	    isl_basic_set_check_no_locals(bset) < 0)
5728 		goto error;
5729 	dim = isl_basic_set_dim(bset, isl_dim_set);
5730 	bmap_total = isl_basic_map_dim(like, isl_dim_all);
5731 	if (dim < 0 || bmap_total < 0)
5732 		goto error;
5733 	isl_assert(ctx, dim == bmap_total, goto error);
5734 	if (like->n_div == 0) {
5735 		isl_space *space = isl_basic_map_get_space(like);
5736 		isl_basic_map_free(like);
5737 		return isl_basic_map_reset_space(bset, space);
5738 	}
5739 	bset = isl_basic_set_cow(bset);
5740 	if (!bset)
5741 		goto error;
5742 	total = dim + bset->extra;
5743 	bmap = bset_to_bmap(bset);
5744 	isl_space_free(isl_basic_map_take_space(bmap));
5745 	bmap = isl_basic_map_restore_space(bmap, isl_basic_map_get_space(like));
5746 	if (!bmap)
5747 		goto error;
5748 	bmap->n_div = like->n_div;
5749 	bmap->extra += like->n_div;
5750 	if (bmap->extra) {
5751 		unsigned ltotal;
5752 		isl_int **div;
5753 		ltotal = total - bmap->extra + like->extra;
5754 		if (ltotal > total)
5755 			ltotal = total;
5756 		bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5757 					bmap->extra * (1 + 1 + total));
5758 		if (isl_blk_is_error(bmap->block2))
5759 			goto error;
5760 		div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5761 		if (!div)
5762 			goto error;
5763 		bmap->div = div;
5764 		for (i = 0; i < bmap->extra; ++i)
5765 			bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5766 		for (i = 0; i < like->n_div; ++i) {
5767 			isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5768 			isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5769 		}
5770 		bmap = isl_basic_map_add_known_div_constraints(bmap);
5771 	}
5772 	isl_basic_map_free(like);
5773 	bmap = isl_basic_map_simplify(bmap);
5774 	bmap = isl_basic_map_finalize(bmap);
5775 	return bmap;
5776 error:
5777 	isl_basic_map_free(like);
5778 	isl_basic_set_free(bset);
5779 	return NULL;
5780 }
5781 
isl_basic_set_from_underlying_set(__isl_take isl_basic_set * bset,__isl_take isl_basic_set * like)5782 __isl_give isl_basic_set *isl_basic_set_from_underlying_set(
5783 	__isl_take isl_basic_set *bset, __isl_take isl_basic_set *like)
5784 {
5785 	return bset_from_bmap(isl_basic_map_overlying_set(bset,
5786 							bset_to_bmap(like)));
5787 }
5788 
isl_map_underlying_set(__isl_take isl_map * map)5789 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5790 {
5791 	int i;
5792 
5793 	map = isl_map_cow(map);
5794 	if (!map)
5795 		return NULL;
5796 	map->dim = isl_space_cow(map->dim);
5797 	if (!map->dim)
5798 		goto error;
5799 
5800 	for (i = 1; i < map->n; ++i)
5801 		isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5802 				goto error);
5803 	for (i = 0; i < map->n; ++i) {
5804 		map->p[i] = bset_to_bmap(
5805 				isl_basic_map_underlying_set(map->p[i]));
5806 		if (!map->p[i])
5807 			goto error;
5808 	}
5809 	if (map->n == 0)
5810 		map->dim = isl_space_underlying(map->dim, 0);
5811 	else {
5812 		isl_space_free(map->dim);
5813 		map->dim = isl_space_copy(map->p[0]->dim);
5814 	}
5815 	if (!map->dim)
5816 		goto error;
5817 	return set_from_map(map);
5818 error:
5819 	isl_map_free(map);
5820 	return NULL;
5821 }
5822 
5823 /* Replace the space of "bmap" by "space".
5824  *
5825  * If the space of "bmap" is identical to "space" (including the identifiers
5826  * of the input and output dimensions), then simply return the original input.
5827  */
isl_basic_map_reset_space(__isl_take isl_basic_map * bmap,__isl_take isl_space * space)5828 __isl_give isl_basic_map *isl_basic_map_reset_space(
5829 	__isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5830 {
5831 	isl_bool equal;
5832 	isl_space *bmap_space;
5833 
5834 	bmap_space = isl_basic_map_peek_space(bmap);
5835 	equal = isl_space_is_equal(bmap_space, space);
5836 	if (equal >= 0 && equal)
5837 		equal = isl_space_has_equal_ids(bmap_space, space);
5838 	if (equal < 0)
5839 		goto error;
5840 	if (equal) {
5841 		isl_space_free(space);
5842 		return bmap;
5843 	}
5844 	isl_space_free(isl_basic_map_take_space(bmap));
5845 	bmap = isl_basic_map_restore_space(bmap, space);
5846 
5847 	bmap = isl_basic_map_finalize(bmap);
5848 
5849 	return bmap;
5850 error:
5851 	isl_basic_map_free(bmap);
5852 	isl_space_free(space);
5853 	return NULL;
5854 }
5855 
isl_basic_set_reset_space(__isl_take isl_basic_set * bset,__isl_take isl_space * space)5856 __isl_give isl_basic_set *isl_basic_set_reset_space(
5857 	__isl_take isl_basic_set *bset, __isl_take isl_space *space)
5858 {
5859 	return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5860 							space));
5861 }
5862 
5863 /* Check that the total dimensions of "map" and "space" are the same.
5864  */
check_map_space_equal_total_dim(__isl_keep isl_map * map,__isl_keep isl_space * space)5865 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5866 	__isl_keep isl_space *space)
5867 {
5868 	isl_size dim1, dim2;
5869 
5870 	dim1 = isl_map_dim(map, isl_dim_all);
5871 	dim2 = isl_space_dim(space, isl_dim_all);
5872 	if (dim1 < 0 || dim2 < 0)
5873 		return isl_stat_error;
5874 	if (dim1 == dim2)
5875 		return isl_stat_ok;
5876 	isl_die(isl_map_get_ctx(map), isl_error_invalid,
5877 		"total dimensions do not match", return isl_stat_error);
5878 }
5879 
isl_map_reset_space(__isl_take isl_map * map,__isl_take isl_space * space)5880 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5881 	__isl_take isl_space *space)
5882 {
5883 	int i;
5884 
5885 	map = isl_map_cow(map);
5886 	if (!map || !space)
5887 		goto error;
5888 
5889 	for (i = 0; i < map->n; ++i) {
5890 		map->p[i] = isl_basic_map_reset_space(map->p[i],
5891 						    isl_space_copy(space));
5892 		if (!map->p[i])
5893 			goto error;
5894 	}
5895 	isl_space_free(isl_map_take_space(map));
5896 	map = isl_map_restore_space(map, space);
5897 
5898 	return map;
5899 error:
5900 	isl_map_free(map);
5901 	isl_space_free(space);
5902 	return NULL;
5903 }
5904 
5905 /* Replace the space of "map" by "space", without modifying
5906  * the dimension of "map".
5907  *
5908  * If the space of "map" is identical to "space" (including the identifiers
5909  * of the input and output dimensions), then simply return the original input.
5910  */
isl_map_reset_equal_dim_space(__isl_take isl_map * map,__isl_take isl_space * space)5911 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5912 	__isl_take isl_space *space)
5913 {
5914 	isl_bool equal;
5915 	isl_space *map_space;
5916 
5917 	map_space = isl_map_peek_space(map);
5918 	equal = isl_space_is_equal(map_space, space);
5919 	if (equal >= 0 && equal)
5920 		equal = isl_space_has_equal_ids(map_space, space);
5921 	if (equal < 0)
5922 		goto error;
5923 	if (equal) {
5924 		isl_space_free(space);
5925 		return map;
5926 	}
5927 	if (check_map_space_equal_total_dim(map, space) < 0)
5928 		goto error;
5929 	return isl_map_reset_space(map, space);
5930 error:
5931 	isl_map_free(map);
5932 	isl_space_free(space);
5933 	return NULL;
5934 }
5935 
isl_set_reset_space(__isl_take isl_set * set,__isl_take isl_space * space)5936 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5937 	__isl_take isl_space *space)
5938 {
5939 	return set_from_map(isl_map_reset_space(set_to_map(set), space));
5940 }
5941 
5942 /* Compute the parameter domain of the given basic set.
5943  */
isl_basic_set_params(__isl_take isl_basic_set * bset)5944 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5945 {
5946 	isl_bool is_params;
5947 	isl_space *space;
5948 	isl_size n;
5949 
5950 	is_params = isl_basic_set_is_params(bset);
5951 	if (is_params < 0)
5952 		return isl_basic_set_free(bset);
5953 	if (is_params)
5954 		return bset;
5955 
5956 	n = isl_basic_set_dim(bset, isl_dim_set);
5957 	if (n < 0)
5958 		return isl_basic_set_free(bset);
5959 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5960 	space = isl_basic_set_get_space(bset);
5961 	space = isl_space_params(space);
5962 	bset = isl_basic_set_reset_space(bset, space);
5963 	return bset;
5964 }
5965 
5966 /* Construct a zero-dimensional basic set with the given parameter domain.
5967  */
isl_basic_set_from_params(__isl_take isl_basic_set * bset)5968 __isl_give isl_basic_set *isl_basic_set_from_params(
5969 	__isl_take isl_basic_set *bset)
5970 {
5971 	isl_space *space;
5972 	space = isl_basic_set_get_space(bset);
5973 	space = isl_space_set_from_params(space);
5974 	bset = isl_basic_set_reset_space(bset, space);
5975 	return bset;
5976 }
5977 
5978 /* Compute the parameter domain of the given set.
5979  */
isl_set_params(__isl_take isl_set * set)5980 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5981 {
5982 	return isl_map_params(set_to_map(set));
5983 }
5984 
5985 /* Construct a zero-dimensional set with the given parameter domain.
5986  */
isl_set_from_params(__isl_take isl_set * set)5987 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5988 {
5989 	isl_space *space;
5990 	space = isl_set_get_space(set);
5991 	space = isl_space_set_from_params(space);
5992 	set = isl_set_reset_space(set, space);
5993 	return set;
5994 }
5995 
5996 /* Compute the parameter domain of the given map.
5997  */
isl_map_params(__isl_take isl_map * map)5998 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5999 {
6000 	isl_space *space;
6001 	isl_size n_in, n_out;
6002 
6003 	n_in = isl_map_dim(map, isl_dim_in);
6004 	n_out = isl_map_dim(map, isl_dim_out);
6005 	if (n_in < 0 || n_out < 0)
6006 		return isl_map_free(map);
6007 	map = isl_map_project_out(map, isl_dim_in, 0, n_in);
6008 	map = isl_map_project_out(map, isl_dim_out, 0, n_out);
6009 	space = isl_map_get_space(map);
6010 	space = isl_space_params(space);
6011 	map = isl_map_reset_space(map, space);
6012 	return map;
6013 }
6014 
isl_basic_map_domain(__isl_take isl_basic_map * bmap)6015 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
6016 {
6017 	isl_space *space;
6018 	isl_size n_out;
6019 
6020 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
6021 	if (n_out < 0)
6022 		return isl_basic_map_free(bmap);
6023 	space = isl_space_domain(isl_basic_map_get_space(bmap));
6024 
6025 	bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
6026 
6027 	return isl_basic_map_reset_space(bmap, space);
6028 }
6029 
isl_basic_map_may_be_set(__isl_keep isl_basic_map * bmap)6030 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
6031 {
6032 	if (!bmap)
6033 		return isl_bool_error;
6034 	return isl_space_may_be_set(bmap->dim);
6035 }
6036 
6037 /* Is this basic map actually a set?
6038  * Users should never call this function.  Outside of isl,
6039  * the type should indicate whether something is a set or a map.
6040  */
isl_basic_map_is_set(__isl_keep isl_basic_map * bmap)6041 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
6042 {
6043 	if (!bmap)
6044 		return isl_bool_error;
6045 	return isl_space_is_set(bmap->dim);
6046 }
6047 
isl_basic_map_range(__isl_take isl_basic_map * bmap)6048 __isl_give isl_basic_set *isl_basic_map_range(__isl_take isl_basic_map *bmap)
6049 {
6050 	isl_bool is_set;
6051 
6052 	is_set = isl_basic_map_is_set(bmap);
6053 	if (is_set < 0)
6054 		goto error;
6055 	if (is_set)
6056 		return bmap;
6057 	return isl_basic_map_domain(isl_basic_map_reverse(bmap));
6058 error:
6059 	isl_basic_map_free(bmap);
6060 	return NULL;
6061 }
6062 
isl_basic_map_domain_map(__isl_take isl_basic_map * bmap)6063 __isl_give isl_basic_map *isl_basic_map_domain_map(
6064 	__isl_take isl_basic_map *bmap)
6065 {
6066 	int i;
6067 	isl_space *space;
6068 	isl_basic_map *domain;
6069 	isl_size nparam, n_in, n_out;
6070 
6071 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
6072 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
6073 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
6074 	if (nparam < 0 || n_in < 0 || n_out < 0)
6075 		return isl_basic_map_free(bmap);
6076 
6077 	space = isl_basic_map_get_space(bmap);
6078 	space = isl_space_from_range(isl_space_domain(space));
6079 	domain = isl_basic_map_universe(space);
6080 
6081 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
6082 	bmap = isl_basic_map_apply_range(bmap, domain);
6083 	bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
6084 
6085 	for (i = 0; i < n_in; ++i)
6086 		bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
6087 						    isl_dim_out, i);
6088 
6089 	bmap = isl_basic_map_gauss(bmap, NULL);
6090 	return isl_basic_map_finalize(bmap);
6091 }
6092 
isl_basic_map_range_map(__isl_take isl_basic_map * bmap)6093 __isl_give isl_basic_map *isl_basic_map_range_map(
6094 	__isl_take isl_basic_map *bmap)
6095 {
6096 	int i;
6097 	isl_space *space;
6098 	isl_basic_map *range;
6099 	isl_size nparam, n_in, n_out;
6100 
6101 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
6102 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
6103 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
6104 	if (nparam < 0 || n_in < 0 || n_out < 0)
6105 		return isl_basic_map_free(bmap);
6106 
6107 	space = isl_basic_map_get_space(bmap);
6108 	space = isl_space_from_range(isl_space_range(space));
6109 	range = isl_basic_map_universe(space);
6110 
6111 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
6112 	bmap = isl_basic_map_apply_range(bmap, range);
6113 	bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
6114 
6115 	for (i = 0; i < n_out; ++i)
6116 		bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
6117 						    isl_dim_out, i);
6118 
6119 	bmap = isl_basic_map_gauss(bmap, NULL);
6120 	return isl_basic_map_finalize(bmap);
6121 }
6122 
isl_map_may_be_set(__isl_keep isl_map * map)6123 int isl_map_may_be_set(__isl_keep isl_map *map)
6124 {
6125 	if (!map)
6126 		return -1;
6127 	return isl_space_may_be_set(map->dim);
6128 }
6129 
6130 /* Is this map actually a set?
6131  * Users should never call this function.  Outside of isl,
6132  * the type should indicate whether something is a set or a map.
6133  */
isl_map_is_set(__isl_keep isl_map * map)6134 isl_bool isl_map_is_set(__isl_keep isl_map *map)
6135 {
6136 	if (!map)
6137 		return isl_bool_error;
6138 	return isl_space_is_set(map->dim);
6139 }
6140 
isl_map_range(__isl_take isl_map * map)6141 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
6142 {
6143 	isl_space *space;
6144 	isl_size n_in;
6145 
6146 	n_in = isl_map_dim(map, isl_dim_in);
6147 	if (n_in < 0)
6148 		return set_from_map(isl_map_free(map));
6149 	space = isl_space_range(isl_map_get_space(map));
6150 
6151 	map = isl_map_project_out(map, isl_dim_in, 0, n_in);
6152 
6153 	return set_from_map(isl_map_reset_space(map, space));
6154 }
6155 
6156 /* Transform "map" by applying "fn_space" to its space and "fn_bmap"
6157  * to each of its basic maps.
6158  */
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))6159 static __isl_give isl_map *isl_map_transform(__isl_take isl_map *map,
6160 	__isl_give isl_space *(*fn_space)(__isl_take isl_space *space),
6161 	__isl_give isl_basic_map *(*fn_bmap)(__isl_take isl_basic_map *bmap))
6162 {
6163 	int i;
6164 	isl_space *space;
6165 
6166 	map = isl_map_cow(map);
6167 	if (!map)
6168 		return NULL;
6169 
6170 	for (i = 0; i < map->n; ++i) {
6171 		map->p[i] = fn_bmap(map->p[i]);
6172 		if (!map->p[i])
6173 			return isl_map_free(map);
6174 	}
6175 	map = isl_map_unmark_normalized(map);
6176 
6177 	space = isl_map_take_space(map);
6178 	space = fn_space(space);
6179 	map = isl_map_restore_space(map, space);
6180 
6181 	return map;
6182 }
6183 
isl_map_domain_map(__isl_take isl_map * map)6184 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
6185 {
6186 	return isl_map_transform(map, &isl_space_domain_map,
6187 					&isl_basic_map_domain_map);
6188 }
6189 
isl_map_range_map(__isl_take isl_map * map)6190 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
6191 {
6192 	return isl_map_transform(map, &isl_space_range_map,
6193 					&isl_basic_map_range_map);
6194 }
6195 
6196 /* Given a wrapped map of the form A[B -> C],
6197  * return the map A[B -> C] -> B.
6198  */
isl_set_wrapped_domain_map(__isl_take isl_set * set)6199 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
6200 {
6201 	isl_id *id;
6202 	isl_map *map;
6203 
6204 	if (!set)
6205 		return NULL;
6206 	if (!isl_set_has_tuple_id(set))
6207 		return isl_map_domain_map(isl_set_unwrap(set));
6208 
6209 	id = isl_set_get_tuple_id(set);
6210 	map = isl_map_domain_map(isl_set_unwrap(set));
6211 	map = isl_map_set_tuple_id(map, isl_dim_in, id);
6212 
6213 	return map;
6214 }
6215 
isl_basic_map_from_domain(__isl_take isl_basic_set * bset)6216 __isl_give isl_basic_map *isl_basic_map_from_domain(
6217 	__isl_take isl_basic_set *bset)
6218 {
6219 	return isl_basic_map_reverse(isl_basic_map_from_range(bset));
6220 }
6221 
isl_basic_map_from_range(__isl_take isl_basic_set * bset)6222 __isl_give isl_basic_map *isl_basic_map_from_range(
6223 	__isl_take isl_basic_set *bset)
6224 {
6225 	isl_space *space;
6226 	space = isl_basic_set_get_space(bset);
6227 	space = isl_space_from_range(space);
6228 	bset = isl_basic_set_reset_space(bset, space);
6229 	return bset_to_bmap(bset);
6230 }
6231 
6232 /* Create a relation with the given set as range.
6233  * The domain of the created relation is a zero-dimensional
6234  * flat anonymous space.
6235  */
isl_map_from_range(__isl_take isl_set * set)6236 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
6237 {
6238 	isl_space *space;
6239 	space = isl_set_get_space(set);
6240 	space = isl_space_from_range(space);
6241 	set = isl_set_reset_space(set, space);
6242 	return set_to_map(set);
6243 }
6244 
6245 /* Create a relation with the given set as domain.
6246  * The range of the created relation is a zero-dimensional
6247  * flat anonymous space.
6248  */
isl_map_from_domain(__isl_take isl_set * set)6249 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
6250 {
6251 	return isl_map_reverse(isl_map_from_range(set));
6252 }
6253 
isl_basic_map_from_domain_and_range(__isl_take isl_basic_set * domain,__isl_take isl_basic_set * range)6254 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
6255 	__isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
6256 {
6257 	return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
6258 }
6259 
isl_map_from_domain_and_range(__isl_take isl_set * domain,__isl_take isl_set * range)6260 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
6261 	__isl_take isl_set *range)
6262 {
6263 	return isl_map_apply_range(isl_map_reverse(domain), range);
6264 }
6265 
6266 /* Return a newly allocated isl_map with given space and flags and
6267  * room for "n" basic maps.
6268  * Make sure that all cached information is cleared.
6269  */
isl_map_alloc_space(__isl_take isl_space * space,int n,unsigned flags)6270 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
6271 	unsigned flags)
6272 {
6273 	struct isl_map *map;
6274 
6275 	if (!space)
6276 		return NULL;
6277 	if (n < 0)
6278 		isl_die(space->ctx, isl_error_internal,
6279 			"negative number of basic maps", goto error);
6280 	map = isl_calloc(space->ctx, struct isl_map,
6281 			sizeof(struct isl_map) +
6282 			(n - 1) * sizeof(struct isl_basic_map *));
6283 	if (!map)
6284 		goto error;
6285 
6286 	map->ctx = space->ctx;
6287 	isl_ctx_ref(map->ctx);
6288 	map->ref = 1;
6289 	map->size = n;
6290 	map->n = 0;
6291 	map->dim = space;
6292 	map->flags = flags;
6293 	return map;
6294 error:
6295 	isl_space_free(space);
6296 	return NULL;
6297 }
6298 
isl_basic_map_empty(__isl_take isl_space * space)6299 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
6300 {
6301 	struct isl_basic_map *bmap;
6302 	bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
6303 	bmap = isl_basic_map_set_to_empty(bmap);
6304 	return bmap;
6305 }
6306 
isl_basic_set_empty(__isl_take isl_space * space)6307 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
6308 {
6309 	struct isl_basic_set *bset;
6310 	bset = isl_basic_set_alloc_space(space, 0, 1, 0);
6311 	bset = isl_basic_set_set_to_empty(bset);
6312 	return bset;
6313 }
6314 
isl_basic_map_universe(__isl_take isl_space * space)6315 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6316 {
6317 	struct isl_basic_map *bmap;
6318 	bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6319 	bmap = isl_basic_map_finalize(bmap);
6320 	return bmap;
6321 }
6322 
isl_basic_set_universe(__isl_take isl_space * space)6323 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6324 {
6325 	struct isl_basic_set *bset;
6326 	bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6327 	bset = isl_basic_set_finalize(bset);
6328 	return bset;
6329 }
6330 
isl_basic_map_nat_universe(__isl_take isl_space * space)6331 __isl_give isl_basic_map *isl_basic_map_nat_universe(
6332 	__isl_take isl_space *space)
6333 {
6334 	int i;
6335 	isl_size total = isl_space_dim(space, isl_dim_all);
6336 	isl_basic_map *bmap;
6337 
6338 	if (total < 0)
6339 		space = isl_space_free(space);
6340 	bmap = isl_basic_map_alloc_space(space, 0, 0, total);
6341 	for (i = 0; i < total; ++i) {
6342 		int k = isl_basic_map_alloc_inequality(bmap);
6343 		if (k < 0)
6344 			goto error;
6345 		isl_seq_clr(bmap->ineq[k], 1 + total);
6346 		isl_int_set_si(bmap->ineq[k][1 + i], 1);
6347 	}
6348 	return bmap;
6349 error:
6350 	isl_basic_map_free(bmap);
6351 	return NULL;
6352 }
6353 
isl_basic_set_nat_universe(__isl_take isl_space * space)6354 __isl_give isl_basic_set *isl_basic_set_nat_universe(
6355 	__isl_take isl_space *space)
6356 {
6357 	return isl_basic_map_nat_universe(space);
6358 }
6359 
isl_map_nat_universe(__isl_take isl_space * space)6360 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *space)
6361 {
6362 	return isl_map_from_basic_map(isl_basic_map_nat_universe(space));
6363 }
6364 
isl_set_nat_universe(__isl_take isl_space * space)6365 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *space)
6366 {
6367 	return isl_map_nat_universe(space);
6368 }
6369 
isl_map_empty(__isl_take isl_space * space)6370 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6371 {
6372 	return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6373 }
6374 
isl_set_empty(__isl_take isl_space * space)6375 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6376 {
6377 	return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6378 }
6379 
isl_map_universe(__isl_take isl_space * space)6380 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6381 {
6382 	struct isl_map *map;
6383 	if (!space)
6384 		return NULL;
6385 	map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6386 	map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6387 	return map;
6388 }
6389 
6390 /* This function performs the same operation as isl_map_universe,
6391  * but is considered as a function on an isl_space when exported.
6392  */
isl_space_universe_map(__isl_take isl_space * space)6393 __isl_give isl_map *isl_space_universe_map(__isl_take isl_space *space)
6394 {
6395 	return isl_map_universe(space);
6396 }
6397 
isl_set_universe(__isl_take isl_space * space)6398 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6399 {
6400 	struct isl_set *set;
6401 	if (!space)
6402 		return NULL;
6403 	set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6404 	set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6405 	return set;
6406 }
6407 
6408 /* This function performs the same operation as isl_set_universe,
6409  * but is considered as a function on an isl_space when exported.
6410  */
isl_space_universe_set(__isl_take isl_space * space)6411 __isl_give isl_set *isl_space_universe_set(__isl_take isl_space *space)
6412 {
6413 	return isl_set_universe(space);
6414 }
6415 
isl_map_dup(__isl_keep isl_map * map)6416 __isl_give isl_map *isl_map_dup(__isl_keep isl_map *map)
6417 {
6418 	int i;
6419 	struct isl_map *dup;
6420 
6421 	if (!map)
6422 		return NULL;
6423 	dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6424 	for (i = 0; i < map->n; ++i)
6425 		dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6426 	return dup;
6427 }
6428 
isl_map_add_basic_map(__isl_take isl_map * map,__isl_take isl_basic_map * bmap)6429 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6430 						__isl_take isl_basic_map *bmap)
6431 {
6432 	if (!bmap || !map)
6433 		goto error;
6434 	if (isl_basic_map_plain_is_empty(bmap)) {
6435 		isl_basic_map_free(bmap);
6436 		return map;
6437 	}
6438 	if (isl_map_basic_map_check_equal_space(map, bmap) < 0)
6439 		goto error;
6440 	isl_assert(map->ctx, map->n < map->size, goto error);
6441 	map->p[map->n] = bmap;
6442 	map->n++;
6443 	map = isl_map_unmark_normalized(map);
6444 	return map;
6445 error:
6446 	if (map)
6447 		isl_map_free(map);
6448 	if (bmap)
6449 		isl_basic_map_free(bmap);
6450 	return NULL;
6451 }
6452 
isl_map_free(__isl_take isl_map * map)6453 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6454 {
6455 	int i;
6456 
6457 	if (!map)
6458 		return NULL;
6459 
6460 	if (--map->ref > 0)
6461 		return NULL;
6462 
6463 	clear_caches(map);
6464 	isl_ctx_deref(map->ctx);
6465 	for (i = 0; i < map->n; ++i)
6466 		isl_basic_map_free(map->p[i]);
6467 	isl_space_free(map->dim);
6468 	free(map);
6469 
6470 	return NULL;
6471 }
6472 
isl_basic_map_fix_pos_si(__isl_take isl_basic_map * bmap,unsigned pos,int value)6473 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6474 	__isl_take isl_basic_map *bmap, unsigned pos, int value)
6475 {
6476 	int j;
6477 	isl_size total;
6478 
6479 	total = isl_basic_map_dim(bmap, isl_dim_all);
6480 	if (total < 0)
6481 		return isl_basic_map_free(bmap);
6482 
6483 	bmap = isl_basic_map_cow(bmap);
6484 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6485 	j = isl_basic_map_alloc_equality(bmap);
6486 	if (j < 0)
6487 		goto error;
6488 	isl_seq_clr(bmap->eq[j] + 1, total);
6489 	isl_int_set_si(bmap->eq[j][pos], -1);
6490 	isl_int_set_si(bmap->eq[j][0], value);
6491 	bmap = isl_basic_map_simplify(bmap);
6492 	return isl_basic_map_finalize(bmap);
6493 error:
6494 	isl_basic_map_free(bmap);
6495 	return NULL;
6496 }
6497 
isl_basic_map_fix_pos(__isl_take isl_basic_map * bmap,unsigned pos,isl_int value)6498 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6499 	__isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6500 {
6501 	int j;
6502 	isl_size total;
6503 
6504 	total = isl_basic_map_dim(bmap, isl_dim_all);
6505 	if (total < 0)
6506 		return isl_basic_map_free(bmap);
6507 
6508 	bmap = isl_basic_map_cow(bmap);
6509 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6510 	j = isl_basic_map_alloc_equality(bmap);
6511 	if (j < 0)
6512 		goto error;
6513 	isl_seq_clr(bmap->eq[j] + 1, total);
6514 	isl_int_set_si(bmap->eq[j][pos], -1);
6515 	isl_int_set(bmap->eq[j][0], value);
6516 	bmap = isl_basic_map_simplify(bmap);
6517 	return isl_basic_map_finalize(bmap);
6518 error:
6519 	isl_basic_map_free(bmap);
6520 	return NULL;
6521 }
6522 
isl_basic_map_fix_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6523 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6524 		enum isl_dim_type type, unsigned pos, int value)
6525 {
6526 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6527 		return isl_basic_map_free(bmap);
6528 	return isl_basic_map_fix_pos_si(bmap,
6529 		isl_basic_map_offset(bmap, type) + pos, value);
6530 }
6531 
isl_basic_map_fix(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int value)6532 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6533 		enum isl_dim_type type, unsigned pos, isl_int value)
6534 {
6535 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6536 		return isl_basic_map_free(bmap);
6537 	return isl_basic_map_fix_pos(bmap,
6538 		isl_basic_map_offset(bmap, type) + pos, value);
6539 }
6540 
6541 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6542  * to be equal to "v".
6543  */
isl_basic_map_fix_val(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6544 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6545 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6546 {
6547 	if (!bmap || !v)
6548 		goto error;
6549 	if (!isl_val_is_int(v))
6550 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6551 			"expecting integer value", goto error);
6552 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6553 		goto error;
6554 	pos += isl_basic_map_offset(bmap, type);
6555 	bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6556 	isl_val_free(v);
6557 	return bmap;
6558 error:
6559 	isl_basic_map_free(bmap);
6560 	isl_val_free(v);
6561 	return NULL;
6562 }
6563 
6564 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6565  * to be equal to "v".
6566  */
isl_basic_set_fix_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6567 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6568 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6569 {
6570 	return isl_basic_map_fix_val(bset, type, pos, v);
6571 }
6572 
isl_basic_set_fix_si(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,int value)6573 __isl_give isl_basic_set *isl_basic_set_fix_si(__isl_take isl_basic_set *bset,
6574 		enum isl_dim_type type, unsigned pos, int value)
6575 {
6576 	return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6577 						    type, pos, value));
6578 }
6579 
isl_basic_set_fix(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value)6580 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6581 		enum isl_dim_type type, unsigned pos, isl_int value)
6582 {
6583 	return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6584 						    type, pos, value));
6585 }
6586 
6587 /* Remove the basic map at position "i" from "map" if this basic map
6588  * is (obviously) empty.
6589  */
remove_if_empty(__isl_take isl_map * map,int i)6590 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6591 {
6592 	isl_bool empty;
6593 
6594 	if (!map)
6595 		return NULL;
6596 
6597 	empty = isl_basic_map_plain_is_empty(map->p[i]);
6598 	if (empty < 0)
6599 		return isl_map_free(map);
6600 	if (!empty)
6601 		return map;
6602 
6603 	isl_basic_map_free(map->p[i]);
6604 	map->n--;
6605 	if (i != map->n) {
6606 		map->p[i] = map->p[map->n];
6607 		map = isl_map_unmark_normalized(map);
6608 
6609 	}
6610 
6611 	return map;
6612 }
6613 
6614 /* Perform "fn" on each basic map of "map", where we may not be holding
6615  * the only reference to "map".
6616  * In particular, "fn" should be a semantics preserving operation
6617  * that we want to apply to all copies of "map".  We therefore need
6618  * to be careful not to modify "map" in a way that breaks "map"
6619  * in case anything goes wrong.
6620  */
isl_map_inline_foreach_basic_map(__isl_take isl_map * map,__isl_give isl_basic_map * (* fn)(__isl_take isl_basic_map * bmap))6621 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6622 	__isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6623 {
6624 	struct isl_basic_map *bmap;
6625 	int i;
6626 
6627 	if (!map)
6628 		return NULL;
6629 
6630 	for (i = map->n - 1; i >= 0; --i) {
6631 		bmap = isl_basic_map_copy(map->p[i]);
6632 		bmap = fn(bmap);
6633 		if (!bmap)
6634 			goto error;
6635 		isl_basic_map_free(map->p[i]);
6636 		map->p[i] = bmap;
6637 		map = remove_if_empty(map, i);
6638 		if (!map)
6639 			return NULL;
6640 	}
6641 
6642 	return map;
6643 error:
6644 	isl_map_free(map);
6645 	return NULL;
6646 }
6647 
isl_map_fix_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6648 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6649 		enum isl_dim_type type, unsigned pos, int value)
6650 {
6651 	int i;
6652 
6653 	map = isl_map_cow(map);
6654 	if (isl_map_check_range(map, type, pos, 1) < 0)
6655 		return isl_map_free(map);
6656 	for (i = map->n - 1; i >= 0; --i) {
6657 		map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6658 		map = remove_if_empty(map, i);
6659 		if (!map)
6660 			return NULL;
6661 	}
6662 	map = isl_map_unmark_normalized(map);
6663 	return map;
6664 }
6665 
isl_set_fix_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6666 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6667 		enum isl_dim_type type, unsigned pos, int value)
6668 {
6669 	return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6670 }
6671 
isl_map_fix(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6672 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6673 		enum isl_dim_type type, unsigned pos, isl_int value)
6674 {
6675 	int i;
6676 
6677 	map = isl_map_cow(map);
6678 	if (isl_map_check_range(map, type, pos, 1) < 0)
6679 		return isl_map_free(map);
6680 	for (i = 0; i < map->n; ++i) {
6681 		map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6682 		if (!map->p[i])
6683 			goto error;
6684 	}
6685 	map = isl_map_unmark_normalized(map);
6686 	return map;
6687 error:
6688 	isl_map_free(map);
6689 	return NULL;
6690 }
6691 
isl_set_fix(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6692 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6693 		enum isl_dim_type type, unsigned pos, isl_int value)
6694 {
6695 	return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6696 }
6697 
6698 /* Fix the value of the variable at position "pos" of type "type" of "map"
6699  * to be equal to "v".
6700  */
isl_map_fix_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6701 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6702 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6703 {
6704 	int i;
6705 
6706 	map = isl_map_cow(map);
6707 	if (!map || !v)
6708 		goto error;
6709 
6710 	if (!isl_val_is_int(v))
6711 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
6712 			"expecting integer value", goto error);
6713 	if (isl_map_check_range(map, type, pos, 1) < 0)
6714 		goto error;
6715 	for (i = map->n - 1; i >= 0; --i) {
6716 		map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6717 							isl_val_copy(v));
6718 		map = remove_if_empty(map, i);
6719 		if (!map)
6720 			goto error;
6721 	}
6722 	map = isl_map_unmark_normalized(map);
6723 	isl_val_free(v);
6724 	return map;
6725 error:
6726 	isl_map_free(map);
6727 	isl_val_free(v);
6728 	return NULL;
6729 }
6730 
6731 /* Fix the value of the variable at position "pos" of type "type" of "set"
6732  * to be equal to "v".
6733  */
isl_set_fix_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6734 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6735 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6736 {
6737 	return isl_map_fix_val(set, type, pos, v);
6738 }
6739 
isl_map_fix_input_si(__isl_take isl_map * map,unsigned input,int value)6740 __isl_give isl_map *isl_map_fix_input_si(__isl_take isl_map *map,
6741 		unsigned input, int value)
6742 {
6743 	return isl_map_fix_si(map, isl_dim_in, input, value);
6744 }
6745 
isl_set_fix_dim_si(__isl_take isl_set * set,unsigned dim,int value)6746 __isl_give isl_set *isl_set_fix_dim_si(__isl_take isl_set *set, unsigned dim,
6747 	int value)
6748 {
6749 	return set_from_map(isl_map_fix_si(set_to_map(set),
6750 						isl_dim_set, dim, value));
6751 }
6752 
basic_map_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value,int upper)6753 static __isl_give isl_basic_map *basic_map_bound_si(
6754 	__isl_take isl_basic_map *bmap,
6755 	enum isl_dim_type type, unsigned pos, int value, int upper)
6756 {
6757 	int j;
6758 	isl_size total;
6759 
6760 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6761 		return isl_basic_map_free(bmap);
6762 	total = isl_basic_map_dim(bmap, isl_dim_all);
6763 	if (total < 0)
6764 		return isl_basic_map_free(bmap);
6765 	pos += isl_basic_map_offset(bmap, type);
6766 	bmap = isl_basic_map_cow(bmap);
6767 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6768 	j = isl_basic_map_alloc_inequality(bmap);
6769 	if (j < 0)
6770 		goto error;
6771 	isl_seq_clr(bmap->ineq[j], 1 + total);
6772 	if (upper) {
6773 		isl_int_set_si(bmap->ineq[j][pos], -1);
6774 		isl_int_set_si(bmap->ineq[j][0], value);
6775 	} else {
6776 		isl_int_set_si(bmap->ineq[j][pos], 1);
6777 		isl_int_set_si(bmap->ineq[j][0], -value);
6778 	}
6779 	bmap = isl_basic_map_simplify(bmap);
6780 	return isl_basic_map_finalize(bmap);
6781 error:
6782 	isl_basic_map_free(bmap);
6783 	return NULL;
6784 }
6785 
isl_basic_map_lower_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6786 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6787 	__isl_take isl_basic_map *bmap,
6788 	enum isl_dim_type type, unsigned pos, int value)
6789 {
6790 	return basic_map_bound_si(bmap, type, pos, value, 0);
6791 }
6792 
6793 /* Constrain the values of the given dimension to be no greater than "value".
6794  */
isl_basic_map_upper_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6795 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6796 	__isl_take isl_basic_map *bmap,
6797 	enum isl_dim_type type, unsigned pos, int value)
6798 {
6799 	return basic_map_bound_si(bmap, type, pos, value, 1);
6800 }
6801 
map_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value,int upper)6802 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6803 	enum isl_dim_type type, unsigned pos, int value, int upper)
6804 {
6805 	int i;
6806 
6807 	map = isl_map_cow(map);
6808 	if (isl_map_check_range(map, type, pos, 1) < 0)
6809 		return isl_map_free(map);
6810 	for (i = 0; i < map->n; ++i) {
6811 		map->p[i] = basic_map_bound_si(map->p[i],
6812 						 type, pos, value, upper);
6813 		if (!map->p[i])
6814 			goto error;
6815 	}
6816 	map = isl_map_unmark_normalized(map);
6817 	return map;
6818 error:
6819 	isl_map_free(map);
6820 	return NULL;
6821 }
6822 
isl_map_lower_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6823 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6824 	enum isl_dim_type type, unsigned pos, int value)
6825 {
6826 	return map_bound_si(map, type, pos, value, 0);
6827 }
6828 
isl_map_upper_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6829 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6830 	enum isl_dim_type type, unsigned pos, int value)
6831 {
6832 	return map_bound_si(map, type, pos, value, 1);
6833 }
6834 
isl_set_lower_bound_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6835 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6836 		enum isl_dim_type type, unsigned pos, int value)
6837 {
6838 	return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6839 							type, pos, value));
6840 }
6841 
isl_set_upper_bound_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6842 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6843 	enum isl_dim_type type, unsigned pos, int value)
6844 {
6845 	return isl_map_upper_bound_si(set, type, pos, value);
6846 }
6847 
6848 /* Bound the given variable of "bmap" from below (or above is "upper"
6849  * is set) to "value".
6850  */
basic_map_bound(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6851 static __isl_give isl_basic_map *basic_map_bound(
6852 	__isl_take isl_basic_map *bmap,
6853 	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6854 {
6855 	int j;
6856 	isl_size total;
6857 
6858 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6859 		return isl_basic_map_free(bmap);
6860 	total = isl_basic_map_dim(bmap, isl_dim_all);
6861 	if (total < 0)
6862 		return isl_basic_map_free(bmap);
6863 	pos += isl_basic_map_offset(bmap, type);
6864 	bmap = isl_basic_map_cow(bmap);
6865 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6866 	j = isl_basic_map_alloc_inequality(bmap);
6867 	if (j < 0)
6868 		goto error;
6869 	isl_seq_clr(bmap->ineq[j], 1 + total);
6870 	if (upper) {
6871 		isl_int_set_si(bmap->ineq[j][pos], -1);
6872 		isl_int_set(bmap->ineq[j][0], value);
6873 	} else {
6874 		isl_int_set_si(bmap->ineq[j][pos], 1);
6875 		isl_int_neg(bmap->ineq[j][0], value);
6876 	}
6877 	bmap = isl_basic_map_simplify(bmap);
6878 	return isl_basic_map_finalize(bmap);
6879 error:
6880 	isl_basic_map_free(bmap);
6881 	return NULL;
6882 }
6883 
6884 /* Bound the given variable of "map" from below (or above is "upper"
6885  * is set) to "value".
6886  */
map_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6887 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6888 	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6889 {
6890 	int i;
6891 
6892 	map = isl_map_cow(map);
6893 	if (isl_map_check_range(map, type, pos, 1) < 0)
6894 		return isl_map_free(map);
6895 	for (i = map->n - 1; i >= 0; --i) {
6896 		map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6897 		map = remove_if_empty(map, i);
6898 		if (!map)
6899 			return NULL;
6900 	}
6901 	map = isl_map_unmark_normalized(map);
6902 	return map;
6903 }
6904 
isl_map_lower_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6905 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6906 	enum isl_dim_type type, unsigned pos, isl_int value)
6907 {
6908 	return map_bound(map, type, pos, value, 0);
6909 }
6910 
isl_map_upper_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6911 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6912 	enum isl_dim_type type, unsigned pos, isl_int value)
6913 {
6914 	return map_bound(map, type, pos, value, 1);
6915 }
6916 
isl_set_lower_bound(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6917 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6918 	enum isl_dim_type type, unsigned pos, isl_int value)
6919 {
6920 	return isl_map_lower_bound(set, type, pos, value);
6921 }
6922 
isl_set_upper_bound(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6923 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6924 	enum isl_dim_type type, unsigned pos, isl_int value)
6925 {
6926 	return isl_map_upper_bound(set, type, pos, value);
6927 }
6928 
6929 /* Force the values of the variable at position "pos" of type "type" of "map"
6930  * to be no smaller than "value".
6931  */
isl_map_lower_bound_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6932 __isl_give isl_map *isl_map_lower_bound_val(__isl_take isl_map *map,
6933 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6934 {
6935 	if (!value)
6936 		goto error;
6937 	if (!isl_val_is_int(value))
6938 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
6939 			"expecting integer value", goto error);
6940 	map = isl_map_lower_bound(map, type, pos, value->n);
6941 	isl_val_free(value);
6942 	return map;
6943 error:
6944 	isl_val_free(value);
6945 	isl_map_free(map);
6946 	return NULL;
6947 }
6948 
6949 /* Force the values of the variable at position "pos" of type "type" of "set"
6950  * to be no smaller than "value".
6951  */
isl_set_lower_bound_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6952 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6953 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6954 {
6955 	isl_map *map;
6956 
6957 	map = set_to_map(set);
6958 	return set_from_map(isl_map_lower_bound_val(map, type, pos, value));
6959 }
6960 
6961 /* Force the values of the variable at position "pos" of type "type" of "map"
6962  * to be no greater than "value".
6963  */
isl_map_upper_bound_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6964 __isl_give isl_map *isl_map_upper_bound_val(__isl_take isl_map *map,
6965 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6966 {
6967 	if (!value)
6968 		goto error;
6969 	if (!isl_val_is_int(value))
6970 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
6971 			"expecting integer value", goto error);
6972 	map = isl_map_upper_bound(map, type, pos, value->n);
6973 	isl_val_free(value);
6974 	return map;
6975 error:
6976 	isl_val_free(value);
6977 	isl_map_free(map);
6978 	return NULL;
6979 }
6980 
6981 /* Force the values of the variable at position "pos" of type "type" of "set"
6982  * to be no greater than "value".
6983  */
isl_set_upper_bound_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6984 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6985 	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6986 {
6987 	isl_map *map;
6988 
6989 	map = set_to_map(set);
6990 	return set_from_map(isl_map_upper_bound_val(map, type, pos, value));
6991 }
6992 
6993 /* If "mv" has an explicit domain, then intersect the domain of "map"
6994  * with this explicit domain.
6995  *
6996  * An isl_multi_val object never has an explicit domain,
6997  * so simply return "map".
6998  */
isl_map_intersect_multi_val_explicit_domain(__isl_take isl_map * map,__isl_keep isl_multi_val * mv)6999 static __isl_give isl_map *isl_map_intersect_multi_val_explicit_domain(
7000 	__isl_take isl_map *map, __isl_keep isl_multi_val *mv)
7001 {
7002 	return map;
7003 }
7004 
7005 #undef BASE
7006 #define BASE	val
7007 #include "isl_map_bound_templ.c"
7008 
7009 /* Apply "map_bound" to "set" with the corresponding value in "bound"
7010  * for each set dimension, by treating the set as a map.
7011  */
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))7012 static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,
7013 	__isl_take isl_multi_val *bound,
7014 	__isl_give isl_map *map_bound(__isl_take isl_map *map,
7015 		unsigned pos, __isl_take isl_val *value))
7016 {
7017 	isl_map *map;
7018 
7019 	map = set_to_map(set);
7020 	return set_from_map(map_bound_multi_val(map, bound, map_bound));
7021 }
7022 
7023 #undef BASE
7024 #define BASE	pw_aff
7025 #include "isl_map_bound_templ.c"
7026 
7027 /* Apply "map_bound" to "set" with the corresponding value in "bound"
7028  * for each set dimension, by converting the set and the bound
7029  * to objects living in a map space.
7030  */
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))7031 static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,
7032 	__isl_take isl_multi_pw_aff *bound,
7033 	__isl_give isl_map *set_bound(__isl_take isl_map *map,
7034 		unsigned pos, __isl_take TYPE *value))
7035 {
7036 	isl_map *map;
7037 
7038 	map = isl_map_from_range(set);
7039 	bound = isl_multi_pw_aff_from_range(bound);
7040 	map = map_bound_multi_pw_aff(map, bound, set_bound);
7041 	return isl_map_range(map);
7042 }
7043 
7044 /* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,
7045  * setting a bound on the given output dimension.
7046  */
map_lower_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)7047 static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,
7048 	unsigned pos, __isl_take isl_val *v)
7049 {
7050 	return isl_map_lower_bound_val(map, isl_dim_out, pos, v);
7051 }
7052 
7053 /* Force the values of the set dimensions of "set"
7054  * to be no smaller than the corresponding values in "lower".
7055  */
isl_set_lower_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * lower)7056 __isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
7057 	__isl_take isl_multi_val *lower)
7058 {
7059 	return set_bound_multi_val(set, lower, &map_lower_bound_val);
7060 }
7061 
7062 /* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,
7063  * setting a bound on the given output dimension.
7064  */
map_upper_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)7065 static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,
7066 	unsigned pos, __isl_take isl_val *v)
7067 {
7068 	return isl_map_upper_bound_val(map, isl_dim_out, pos, v);
7069 }
7070 
7071 /* Force the values of the set dimensions of "set"
7072  * to be no greater than the corresponding values in "upper".
7073  */
isl_set_upper_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * upper)7074 __isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
7075 	__isl_take isl_multi_val *upper)
7076 {
7077 	return set_bound_multi_val(set, upper, &map_upper_bound_val);
7078 }
7079 
7080 /* Force the symbolic constant expression "bound"
7081  * to satisfy the relation "order" with respect to
7082  * the output variable at position "pos" of "map".
7083  *
7084  * Create an affine expression representing the output variable
7085  * in terms of the range and
7086  * compare it using "order" to "bound" (defined on the domain).
7087  * The result is a relation between elements in domain and range that
7088  * can be intersected with "map".
7089  */
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))7090 static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,
7091 	unsigned pos, __isl_take isl_pw_aff *bound,
7092 	__isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,
7093 		__isl_take isl_pw_aff *pa2))
7094 {
7095 	isl_space *space;
7096 	isl_local_space *ls;
7097 	isl_pw_aff *var;
7098 
7099 	space = isl_space_range(isl_map_get_space(map));
7100 	ls = isl_local_space_from_space(space);
7101 	var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);
7102 	map = isl_map_intersect(map, order(bound, var));
7103 	return map;
7104 }
7105 
7106 /* Force the values of the output variable at position "pos" of "map"
7107  * to be no smaller than the symbolic constant expression "lower".
7108  */
map_lower_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * lower)7109 static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,
7110 	unsigned pos, __isl_take isl_pw_aff *lower)
7111 {
7112 	return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);
7113 }
7114 
7115 /* Force the values of the output variable at position "pos" of "map"
7116  * to be no greater than the symbolic constant expression "upper".
7117  */
map_upper_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * upper)7118 static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,
7119 	unsigned pos, __isl_take isl_pw_aff *upper)
7120 {
7121 	return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);
7122 }
7123 
7124 /* Force the values of the set dimensions of "set"
7125  * to be no smaller than the corresponding constant symbolic expressions
7126  * in "lower".
7127  */
isl_set_lower_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * lower)7128 __isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
7129 	__isl_take isl_multi_pw_aff *lower)
7130 {
7131 	return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);
7132 }
7133 
7134 /* Force the values of the set dimensions of "set"
7135  * to be no greater than the corresponding constant symbolic expressions
7136  * in "upper".
7137  */
isl_set_upper_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * upper)7138 __isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
7139 	__isl_take isl_multi_pw_aff *upper)
7140 {
7141 	return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);
7142 }
7143 
7144 /* Force the values of the output dimensions of "map"
7145  * to be no smaller than the corresponding constant symbolic expressions
7146  * in "lower".
7147  */
isl_map_lower_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * lower)7148 __isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
7149 	__isl_take isl_multi_pw_aff *lower)
7150 {
7151 	return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);
7152 }
7153 
7154 /* Force the values of the output dimensions of "map"
7155  * to be no greater than the corresponding constant symbolic expressions
7156  * in "upper".
7157  */
isl_map_upper_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * upper)7158 __isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
7159 	__isl_take isl_multi_pw_aff *upper)
7160 {
7161 	return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);
7162 }
7163 
7164 /* Bound the given variable of "bset" from below (or above is "upper"
7165  * is set) to "value".
7166  */
isl_basic_set_bound(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value,int upper)7167 static __isl_give isl_basic_set *isl_basic_set_bound(
7168 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7169 	isl_int value, int upper)
7170 {
7171 	return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
7172 						type, pos, value, upper));
7173 }
7174 
7175 /* Bound the given variable of "bset" from below (or above is "upper"
7176  * is set) to "value".
7177  */
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)7178 static __isl_give isl_basic_set *isl_basic_set_bound_val(
7179 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7180 	__isl_take isl_val *value, int upper)
7181 {
7182 	if (!value)
7183 		goto error;
7184 	if (!isl_val_is_int(value))
7185 		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
7186 			"expecting integer value", goto error);
7187 	bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
7188 	isl_val_free(value);
7189 	return bset;
7190 error:
7191 	isl_val_free(value);
7192 	isl_basic_set_free(bset);
7193 	return NULL;
7194 }
7195 
7196 /* Bound the given variable of "bset" from below to "value".
7197  */
isl_basic_set_lower_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7198 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
7199 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7200 	__isl_take isl_val *value)
7201 {
7202 	return isl_basic_set_bound_val(bset, type, pos, value, 0);
7203 }
7204 
7205 /* Bound the given variable of "bset" from above to "value".
7206  */
isl_basic_set_upper_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7207 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
7208 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7209 	__isl_take isl_val *value)
7210 {
7211 	return isl_basic_set_bound_val(bset, type, pos, value, 1);
7212 }
7213 
isl_map_reverse(__isl_take isl_map * map)7214 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
7215 {
7216 	return isl_map_transform(map, &isl_space_reverse,
7217 					&isl_basic_map_reverse);
7218 }
7219 
7220 /* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).
7221  */
isl_map_range_reverse(__isl_take isl_map * map)7222 __isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)
7223 {
7224 	return isl_map_transform(map, &isl_space_range_reverse,
7225 					&isl_basic_map_range_reverse);
7226 }
7227 
7228 #undef TYPE
7229 #define TYPE	isl_pw_multi_aff
7230 #undef SUFFIX
7231 #define SUFFIX	_pw_multi_aff
7232 #undef EMPTY
7233 #define EMPTY	isl_pw_multi_aff_empty
7234 #undef ADD
7235 #define ADD	isl_pw_multi_aff_union_add
7236 #include "isl_map_lexopt_templ.c"
7237 
7238 /* Given a map "map", compute the lexicographically minimal
7239  * (or maximal) image element for each domain element in dom,
7240  * in the form of an isl_pw_multi_aff.
7241  * If "empty" is not NULL, then set *empty to those elements in dom that
7242  * do not have an image element.
7243  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7244  * should be computed over the domain of "map".  "empty" is also NULL
7245  * in this case.
7246  *
7247  * We first compute the lexicographically minimal or maximal element
7248  * in the first basic map.  This results in a partial solution "res"
7249  * and a subset "todo" of dom that still need to be handled.
7250  * We then consider each of the remaining maps in "map" and successively
7251  * update both "res" and "todo".
7252  * If "empty" is NULL, then the todo sets are not needed and therefore
7253  * also not computed.
7254  */
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)7255 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
7256 	__isl_take isl_map *map, __isl_take isl_set *dom,
7257 	__isl_give isl_set **empty, unsigned flags)
7258 {
7259 	int i;
7260 	int full;
7261 	isl_pw_multi_aff *res;
7262 	isl_set *todo;
7263 
7264 	full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7265 	if (!map || (!full && !dom))
7266 		goto error;
7267 
7268 	if (isl_map_plain_is_empty(map)) {
7269 		if (empty)
7270 			*empty = dom;
7271 		else
7272 			isl_set_free(dom);
7273 		return isl_pw_multi_aff_from_map(map);
7274 	}
7275 
7276 	res = basic_map_partial_lexopt_pw_multi_aff(
7277 					    isl_basic_map_copy(map->p[0]),
7278 					    isl_set_copy(dom), empty, flags);
7279 
7280 	if (empty)
7281 		todo = *empty;
7282 	for (i = 1; i < map->n; ++i) {
7283 		isl_pw_multi_aff *res_i;
7284 
7285 		res_i = basic_map_partial_lexopt_pw_multi_aff(
7286 					    isl_basic_map_copy(map->p[i]),
7287 					    isl_set_copy(dom), empty, flags);
7288 
7289 		if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
7290 			res = isl_pw_multi_aff_union_lexmax(res, res_i);
7291 		else
7292 			res = isl_pw_multi_aff_union_lexmin(res, res_i);
7293 
7294 		if (empty)
7295 			todo = isl_set_intersect(todo, *empty);
7296 	}
7297 
7298 	isl_set_free(dom);
7299 	isl_map_free(map);
7300 
7301 	if (empty)
7302 		*empty = todo;
7303 
7304 	return res;
7305 error:
7306 	if (empty)
7307 		*empty = NULL;
7308 	isl_set_free(dom);
7309 	isl_map_free(map);
7310 	return NULL;
7311 }
7312 
7313 #undef TYPE
7314 #define TYPE	isl_map
7315 #undef SUFFIX
7316 #define SUFFIX
7317 #undef EMPTY
7318 #define EMPTY	isl_map_empty
7319 #undef ADD
7320 #define ADD	isl_map_union_disjoint
7321 #include "isl_map_lexopt_templ.c"
7322 
7323 /* Given a map "map", compute the lexicographically minimal
7324  * (or maximal) image element for each domain element in "dom",
7325  * in the form of an isl_map.
7326  * If "empty" is not NULL, then set *empty to those elements in "dom" that
7327  * do not have an image element.
7328  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7329  * should be computed over the domain of "map".  "empty" is also NULL
7330  * in this case.
7331  *
7332  * If the input consists of more than one disjunct, then first
7333  * compute the desired result in the form of an isl_pw_multi_aff and
7334  * then convert that into an isl_map.
7335  *
7336  * This function used to have an explicit implementation in terms
7337  * of isl_maps, but it would continually intersect the domains of
7338  * partial results with the complement of the domain of the next
7339  * partial solution, potentially leading to an explosion in the number
7340  * of disjuncts if there are several disjuncts in the input.
7341  * An even earlier implementation of this function would look for
7342  * better results in the domain of the partial result and for extra
7343  * results in the complement of this domain, which would lead to
7344  * even more splintering.
7345  */
isl_map_partial_lexopt_aligned(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty,unsigned flags)7346 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
7347 	__isl_take isl_map *map, __isl_take isl_set *dom,
7348 	__isl_give isl_set **empty, unsigned flags)
7349 {
7350 	int full;
7351 	struct isl_map *res;
7352 	isl_pw_multi_aff *pma;
7353 
7354 	full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7355 	if (!map || (!full && !dom))
7356 		goto error;
7357 
7358 	if (isl_map_plain_is_empty(map)) {
7359 		if (empty)
7360 			*empty = dom;
7361 		else
7362 			isl_set_free(dom);
7363 		return map;
7364 	}
7365 
7366 	if (map->n == 1) {
7367 		res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
7368 						dom, empty, flags);
7369 		isl_map_free(map);
7370 		return res;
7371 	}
7372 
7373 	pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
7374 							flags);
7375 	return isl_map_from_pw_multi_aff_internal(pma);
7376 error:
7377 	if (empty)
7378 		*empty = NULL;
7379 	isl_set_free(dom);
7380 	isl_map_free(map);
7381 	return NULL;
7382 }
7383 
isl_map_partial_lexmax(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7384 __isl_give isl_map *isl_map_partial_lexmax(
7385 		__isl_take isl_map *map, __isl_take isl_set *dom,
7386 		__isl_give isl_set **empty)
7387 {
7388 	return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
7389 }
7390 
isl_map_partial_lexmin(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7391 __isl_give isl_map *isl_map_partial_lexmin(
7392 		__isl_take isl_map *map, __isl_take isl_set *dom,
7393 		__isl_give isl_set **empty)
7394 {
7395 	return isl_map_partial_lexopt(map, dom, empty, 0);
7396 }
7397 
isl_set_partial_lexmin(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7398 __isl_give isl_set *isl_set_partial_lexmin(
7399 		__isl_take isl_set *set, __isl_take isl_set *dom,
7400 		__isl_give isl_set **empty)
7401 {
7402 	return set_from_map(isl_map_partial_lexmin(set_to_map(set),
7403 						    dom, empty));
7404 }
7405 
isl_set_partial_lexmax(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7406 __isl_give isl_set *isl_set_partial_lexmax(
7407 		__isl_take isl_set *set, __isl_take isl_set *dom,
7408 		__isl_give isl_set **empty)
7409 {
7410 	return set_from_map(isl_map_partial_lexmax(set_to_map(set),
7411 						    dom, empty));
7412 }
7413 
7414 /* Compute the lexicographic minimum (or maximum if "flags" includes
7415  * ISL_OPT_MAX) of "bset" over its parametric domain.
7416  */
isl_basic_set_lexopt(__isl_take isl_basic_set * bset,unsigned flags)7417 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
7418 	unsigned flags)
7419 {
7420 	return isl_basic_map_lexopt(bset, flags);
7421 }
7422 
isl_basic_map_lexmax(__isl_take isl_basic_map * bmap)7423 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
7424 {
7425 	return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
7426 }
7427 
isl_basic_set_lexmin(__isl_take isl_basic_set * bset)7428 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
7429 {
7430 	return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
7431 }
7432 
isl_basic_set_lexmax(__isl_take isl_basic_set * bset)7433 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
7434 {
7435 	return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
7436 }
7437 
7438 /* Compute the lexicographic minimum of "bset" over its parametric domain
7439  * for the purpose of quantifier elimination.
7440  * That is, find an explicit representation for all the existentially
7441  * quantified variables in "bset" by computing their lexicographic
7442  * minimum.
7443  */
isl_basic_set_lexmin_compute_divs(__isl_take isl_basic_set * bset)7444 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
7445 	__isl_take isl_basic_set *bset)
7446 {
7447 	return isl_basic_set_lexopt(bset, ISL_OPT_QE);
7448 }
7449 
7450 /* Given a basic map with one output dimension, compute the minimum or
7451  * maximum of that dimension as an isl_pw_aff.
7452  *
7453  * Compute the optimum as a lexicographic optimum over the single
7454  * output dimension and extract the single isl_pw_aff from the result.
7455  */
basic_map_dim_opt(__isl_keep isl_basic_map * bmap,int max)7456 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
7457 	int max)
7458 {
7459 	isl_pw_multi_aff *pma;
7460 	isl_pw_aff *pwaff;
7461 
7462 	bmap = isl_basic_map_copy(bmap);
7463 	pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
7464 	pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
7465 	isl_pw_multi_aff_free(pma);
7466 
7467 	return pwaff;
7468 }
7469 
7470 /* Compute the minimum or maximum of the given output dimension
7471  * as a function of the parameters and the input dimensions,
7472  * but independently of the other output dimensions.
7473  *
7474  * We first project out the other output dimension and then compute
7475  * the "lexicographic" maximum in each basic map, combining the results
7476  * using isl_pw_aff_union_max.
7477  */
map_dim_opt(__isl_take isl_map * map,int pos,int max)7478 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
7479 	int max)
7480 {
7481 	int i;
7482 	isl_pw_aff *pwaff;
7483 	isl_size n_out;
7484 
7485 	n_out = isl_map_dim(map, isl_dim_out);
7486 	if (n_out < 0)
7487 		map = isl_map_free(map);
7488 	map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7489 	map = isl_map_project_out(map, isl_dim_out, 0, pos);
7490 	if (!map)
7491 		return NULL;
7492 
7493 	if (map->n == 0) {
7494 		isl_space *space = isl_map_get_space(map);
7495 		isl_map_free(map);
7496 		return isl_pw_aff_empty(space);
7497 	}
7498 
7499 	pwaff = basic_map_dim_opt(map->p[0], max);
7500 	for (i = 1; i < map->n; ++i) {
7501 		isl_pw_aff *pwaff_i;
7502 
7503 		pwaff_i = basic_map_dim_opt(map->p[i], max);
7504 		pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7505 	}
7506 
7507 	isl_map_free(map);
7508 
7509 	return pwaff;
7510 }
7511 
7512 /* Compute the minimum of the given output dimension as a function of the
7513  * parameters and input dimensions, but independently of
7514  * the other output dimensions.
7515  */
isl_map_dim_min(__isl_take isl_map * map,int pos)7516 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7517 {
7518 	return map_dim_opt(map, pos, 0);
7519 }
7520 
7521 /* Compute the maximum of the given output dimension as a function of the
7522  * parameters and input dimensions, but independently of
7523  * the other output dimensions.
7524  */
isl_map_dim_max(__isl_take isl_map * map,int pos)7525 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7526 {
7527 	return map_dim_opt(map, pos, 1);
7528 }
7529 
7530 /* Compute the minimum or maximum of the given set dimension
7531  * as a function of the parameters,
7532  * but independently of the other set dimensions.
7533  */
set_dim_opt(__isl_take isl_set * set,int pos,int max)7534 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7535 	int max)
7536 {
7537 	return map_dim_opt(set, pos, max);
7538 }
7539 
7540 /* Compute the maximum of the given set dimension as a function of the
7541  * parameters, but independently of the other set dimensions.
7542  */
isl_set_dim_max(__isl_take isl_set * set,int pos)7543 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7544 {
7545 	return set_dim_opt(set, pos, 1);
7546 }
7547 
7548 /* Compute the minimum of the given set dimension as a function of the
7549  * parameters, but independently of the other set dimensions.
7550  */
isl_set_dim_min(__isl_take isl_set * set,int pos)7551 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7552 {
7553 	return set_dim_opt(set, pos, 0);
7554 }
7555 
7556 /* Apply a preimage specified by "mat" on the parameters of "bset".
7557  * bset is assumed to have only parameters and divs.
7558  */
basic_set_parameter_preimage(__isl_take isl_basic_set * bset,__isl_take isl_mat * mat)7559 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7560 	__isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7561 {
7562 	isl_size nparam;
7563 
7564 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7565 	if (nparam < 0 || !mat)
7566 		goto error;
7567 
7568 	bset->dim = isl_space_cow(bset->dim);
7569 	if (!bset->dim)
7570 		goto error;
7571 
7572 	isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7573 
7574 	bset->dim->nparam = 0;
7575 	bset->dim->n_out = nparam;
7576 	bset = isl_basic_set_preimage(bset, mat);
7577 	if (bset) {
7578 		bset->dim->nparam = bset->dim->n_out;
7579 		bset->dim->n_out = 0;
7580 	}
7581 	return bset;
7582 error:
7583 	isl_mat_free(mat);
7584 	isl_basic_set_free(bset);
7585 	return NULL;
7586 }
7587 
7588 /* Apply a preimage specified by "mat" on the parameters of "set".
7589  * set is assumed to have only parameters and divs.
7590  */
set_parameter_preimage(__isl_take isl_set * set,__isl_take isl_mat * mat)7591 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7592 	__isl_take isl_mat *mat)
7593 {
7594 	isl_space *space;
7595 	isl_size nparam;
7596 
7597 	nparam = isl_set_dim(set, isl_dim_param);
7598 	if (nparam < 0 || !mat)
7599 		goto error;
7600 
7601 	if (mat->n_row != 1 + nparam)
7602 		isl_die(isl_set_get_ctx(set), isl_error_internal,
7603 			"unexpected number of rows", goto error);
7604 
7605 	space = isl_set_get_space(set);
7606 	space = isl_space_move_dims(space, isl_dim_set, 0,
7607 				    isl_dim_param, 0, nparam);
7608 	set = isl_set_reset_space(set, space);
7609 	set = isl_set_preimage(set, mat);
7610 	nparam = isl_set_dim(set, isl_dim_out);
7611 	if (nparam < 0)
7612 		set = isl_set_free(set);
7613 	space = isl_set_get_space(set);
7614 	space = isl_space_move_dims(space, isl_dim_param, 0,
7615 				    isl_dim_out, 0, nparam);
7616 	set = isl_set_reset_space(set, space);
7617 	return set;
7618 error:
7619 	isl_mat_free(mat);
7620 	isl_set_free(set);
7621 	return NULL;
7622 }
7623 
7624 /* Intersect the basic set "bset" with the affine space specified by the
7625  * equalities in "eq".
7626  */
basic_set_append_equalities(__isl_take isl_basic_set * bset,__isl_take isl_mat * eq)7627 static __isl_give isl_basic_set *basic_set_append_equalities(
7628 	__isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7629 {
7630 	int i, k;
7631 	unsigned len;
7632 
7633 	if (!bset || !eq)
7634 		goto error;
7635 
7636 	bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);
7637 	if (!bset)
7638 		goto error;
7639 
7640 	len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7641 	for (i = 0; i < eq->n_row; ++i) {
7642 		k = isl_basic_set_alloc_equality(bset);
7643 		if (k < 0)
7644 			goto error;
7645 		isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7646 		isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7647 	}
7648 	isl_mat_free(eq);
7649 
7650 	bset = isl_basic_set_gauss(bset, NULL);
7651 	bset = isl_basic_set_finalize(bset);
7652 
7653 	return bset;
7654 error:
7655 	isl_mat_free(eq);
7656 	isl_basic_set_free(bset);
7657 	return NULL;
7658 }
7659 
7660 /* Intersect the set "set" with the affine space specified by the
7661  * equalities in "eq".
7662  */
set_append_equalities(__isl_take isl_set * set,__isl_take isl_mat * eq)7663 static __isl_give isl_set *set_append_equalities(__isl_take isl_set *set,
7664 	__isl_take isl_mat *eq)
7665 {
7666 	int i;
7667 
7668 	if (!set || !eq)
7669 		goto error;
7670 
7671 	for (i = 0; i < set->n; ++i) {
7672 		set->p[i] = basic_set_append_equalities(set->p[i],
7673 					isl_mat_copy(eq));
7674 		if (!set->p[i])
7675 			goto error;
7676 	}
7677 	isl_mat_free(eq);
7678 	return set;
7679 error:
7680 	isl_mat_free(eq);
7681 	isl_set_free(set);
7682 	return NULL;
7683 }
7684 
7685 /* Given a basic set "bset" that only involves parameters and existentially
7686  * quantified variables, return the index of the first equality
7687  * that only involves parameters.  If there is no such equality then
7688  * return bset->n_eq.
7689  *
7690  * This function assumes that isl_basic_set_gauss has been called on "bset".
7691  */
first_parameter_equality(__isl_keep isl_basic_set * bset)7692 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7693 {
7694 	int i, j;
7695 	isl_size nparam, n_div;
7696 
7697 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7698 	n_div = isl_basic_set_dim(bset, isl_dim_div);
7699 	if (nparam < 0 || n_div < 0)
7700 		return -1;
7701 
7702 	for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7703 		if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7704 			++i;
7705 	}
7706 
7707 	return i;
7708 }
7709 
7710 /* Compute an explicit representation for the existentially quantified
7711  * variables in "bset" by computing the "minimal value" of the set
7712  * variables.  Since there are no set variables, the computation of
7713  * the minimal value essentially computes an explicit representation
7714  * of the non-empty part(s) of "bset".
7715  *
7716  * The input only involves parameters and existentially quantified variables.
7717  * All equalities among parameters have been removed.
7718  *
7719  * Since the existentially quantified variables in the result are in general
7720  * going to be different from those in the input, we first replace
7721  * them by the minimal number of variables based on their equalities.
7722  * This should simplify the parametric integer programming.
7723  */
base_compute_divs(__isl_take isl_basic_set * bset)7724 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7725 {
7726 	isl_morph *morph1, *morph2;
7727 	isl_set *set;
7728 	isl_size n;
7729 
7730 	if (!bset)
7731 		return NULL;
7732 	if (bset->n_eq == 0)
7733 		return isl_basic_set_lexmin_compute_divs(bset);
7734 
7735 	morph1 = isl_basic_set_parameter_compression(bset);
7736 	bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7737 	bset = isl_basic_set_lift(bset);
7738 	morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7739 	bset = isl_morph_basic_set(morph2, bset);
7740 	n = isl_basic_set_dim(bset, isl_dim_set);
7741 	if (n < 0)
7742 		bset = isl_basic_set_free(bset);
7743 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7744 
7745 	set = isl_basic_set_lexmin_compute_divs(bset);
7746 
7747 	set = isl_morph_set(isl_morph_inverse(morph1), set);
7748 
7749 	return set;
7750 }
7751 
7752 /* Project the given basic set onto its parameter domain, possibly introducing
7753  * new, explicit, existential variables in the constraints.
7754  * The input has parameters and (possibly implicit) existential variables.
7755  * The output has the same parameters, but only
7756  * explicit existentially quantified variables.
7757  *
7758  * The actual projection is performed by pip, but pip doesn't seem
7759  * to like equalities very much, so we first remove the equalities
7760  * among the parameters by performing a variable compression on
7761  * the parameters.  Afterward, an inverse transformation is performed
7762  * and the equalities among the parameters are inserted back in.
7763  *
7764  * The variable compression on the parameters may uncover additional
7765  * equalities that were only implicit before.  We therefore check
7766  * if there are any new parameter equalities in the result and
7767  * if so recurse.  The removal of parameter equalities is required
7768  * for the parameter compression performed by base_compute_divs.
7769  */
parameter_compute_divs(__isl_take isl_basic_set * bset)7770 static __isl_give isl_set *parameter_compute_divs(
7771 	__isl_take isl_basic_set *bset)
7772 {
7773 	int i;
7774 	struct isl_mat *eq;
7775 	struct isl_mat *T, *T2;
7776 	struct isl_set *set;
7777 	isl_size nparam;
7778 
7779 	bset = isl_basic_set_cow(bset);
7780 	if (!bset)
7781 		return NULL;
7782 
7783 	if (bset->n_eq == 0)
7784 		return base_compute_divs(bset);
7785 
7786 	bset = isl_basic_set_gauss(bset, NULL);
7787 	if (!bset)
7788 		return NULL;
7789 	if (isl_basic_set_plain_is_empty(bset))
7790 		return isl_set_from_basic_set(bset);
7791 
7792 	i = first_parameter_equality(bset);
7793 	if (i == bset->n_eq)
7794 		return base_compute_divs(bset);
7795 
7796 	nparam = isl_basic_set_dim(bset, isl_dim_param);
7797 	if (nparam < 0)
7798 		return isl_set_from_basic_set(isl_basic_set_free(bset));
7799 	eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7800 		0, 1 + nparam);
7801 	eq = isl_mat_cow(eq);
7802 	T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7803 	if (T && T->n_col == 0) {
7804 		isl_mat_free(T);
7805 		isl_mat_free(T2);
7806 		isl_mat_free(eq);
7807 		bset = isl_basic_set_set_to_empty(bset);
7808 		return isl_set_from_basic_set(bset);
7809 	}
7810 	bset = basic_set_parameter_preimage(bset, T);
7811 
7812 	i = first_parameter_equality(bset);
7813 	if (!bset)
7814 		set = NULL;
7815 	else if (i == bset->n_eq)
7816 		set = base_compute_divs(bset);
7817 	else
7818 		set = parameter_compute_divs(bset);
7819 	set = set_parameter_preimage(set, T2);
7820 	set = set_append_equalities(set, eq);
7821 	return set;
7822 }
7823 
7824 /* Insert the divs from "ls" before those of "bmap".
7825  *
7826  * The number of columns is not changed, which means that the last
7827  * dimensions of "bmap" are being reintepreted as the divs from "ls".
7828  * The caller is responsible for removing the same number of dimensions
7829  * from the space of "bmap".
7830  */
insert_divs_from_local_space(__isl_take isl_basic_map * bmap,__isl_keep isl_local_space * ls)7831 static __isl_give isl_basic_map *insert_divs_from_local_space(
7832 	__isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7833 {
7834 	int i;
7835 	isl_size n_div;
7836 	int old_n_div;
7837 
7838 	n_div = isl_local_space_dim(ls, isl_dim_div);
7839 	if (n_div < 0)
7840 		return isl_basic_map_free(bmap);
7841 	if (n_div == 0)
7842 		return bmap;
7843 
7844 	old_n_div = bmap->n_div;
7845 	bmap = insert_div_rows(bmap, n_div);
7846 	if (!bmap)
7847 		return NULL;
7848 
7849 	for (i = 0; i < n_div; ++i) {
7850 		isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7851 		isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7852 	}
7853 
7854 	return bmap;
7855 }
7856 
7857 /* Replace the space of "bmap" by the space and divs of "ls".
7858  *
7859  * If "ls" has any divs, then we simplify the result since we may
7860  * have discovered some additional equalities that could simplify
7861  * the div expressions.
7862  */
basic_replace_space_by_local_space(__isl_take isl_basic_map * bmap,__isl_take isl_local_space * ls)7863 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7864 	__isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7865 {
7866 	isl_size n_div;
7867 
7868 	bmap = isl_basic_map_cow(bmap);
7869 	n_div = isl_local_space_dim(ls, isl_dim_div);
7870 	if (!bmap || n_div < 0)
7871 		goto error;
7872 
7873 	bmap = insert_divs_from_local_space(bmap, ls);
7874 	if (!bmap)
7875 		goto error;
7876 
7877 	isl_space_free(bmap->dim);
7878 	bmap->dim = isl_local_space_get_space(ls);
7879 	if (!bmap->dim)
7880 		goto error;
7881 
7882 	isl_local_space_free(ls);
7883 	if (n_div > 0)
7884 		bmap = isl_basic_map_simplify(bmap);
7885 	bmap = isl_basic_map_finalize(bmap);
7886 	return bmap;
7887 error:
7888 	isl_basic_map_free(bmap);
7889 	isl_local_space_free(ls);
7890 	return NULL;
7891 }
7892 
7893 /* Replace the space of "map" by the space and divs of "ls".
7894  */
replace_space_by_local_space(__isl_take isl_map * map,__isl_take isl_local_space * ls)7895 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7896 	__isl_take isl_local_space *ls)
7897 {
7898 	int i;
7899 
7900 	map = isl_map_cow(map);
7901 	if (!map || !ls)
7902 		goto error;
7903 
7904 	for (i = 0; i < map->n; ++i) {
7905 		map->p[i] = basic_replace_space_by_local_space(map->p[i],
7906 						    isl_local_space_copy(ls));
7907 		if (!map->p[i])
7908 			goto error;
7909 	}
7910 	isl_space_free(isl_map_take_space(map));
7911 	map = isl_map_restore_space(map, isl_local_space_get_space(ls));
7912 
7913 	isl_local_space_free(ls);
7914 	return map;
7915 error:
7916 	isl_local_space_free(ls);
7917 	isl_map_free(map);
7918 	return NULL;
7919 }
7920 
7921 /* Compute an explicit representation for the existentially
7922  * quantified variables for which do not know any explicit representation yet.
7923  *
7924  * We first sort the existentially quantified variables so that the
7925  * existentially quantified variables for which we already have an explicit
7926  * representation are placed before those for which we do not.
7927  * The input dimensions, the output dimensions and the existentially
7928  * quantified variables for which we already have an explicit
7929  * representation are then turned into parameters.
7930  * compute_divs returns a map with the same parameters and
7931  * no input or output dimensions and the dimension specification
7932  * is reset to that of the input, including the existentially quantified
7933  * variables for which we already had an explicit representation.
7934  */
compute_divs(__isl_take isl_basic_map * bmap)7935 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7936 {
7937 	struct isl_basic_set *bset;
7938 	struct isl_set *set;
7939 	struct isl_map *map;
7940 	isl_space *space;
7941 	isl_local_space *ls;
7942 	isl_size nparam;
7943 	isl_size n_in;
7944 	isl_size n_out;
7945 	int n_known;
7946 	int i;
7947 
7948 	bmap = isl_basic_map_sort_divs(bmap);
7949 	bmap = isl_basic_map_cow(bmap);
7950 	if (!bmap)
7951 		return NULL;
7952 
7953 	n_known = isl_basic_map_first_unknown_div(bmap);
7954 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
7955 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
7956 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
7957 	if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
7958 		return isl_map_from_basic_map(isl_basic_map_free(bmap));
7959 
7960 	space = isl_space_set_alloc(bmap->ctx,
7961 				    nparam + n_in + n_out + n_known, 0);
7962 	if (!space)
7963 		goto error;
7964 
7965 	ls = isl_basic_map_get_local_space(bmap);
7966 	ls = isl_local_space_drop_dims(ls, isl_dim_div,
7967 					n_known, bmap->n_div - n_known);
7968 	if (n_known > 0) {
7969 		for (i = n_known; i < bmap->n_div; ++i)
7970 			swap_div(bmap, i - n_known, i);
7971 		bmap->n_div -= n_known;
7972 		bmap->extra -= n_known;
7973 	}
7974 	bmap = isl_basic_map_reset_space(bmap, space);
7975 	bset = bset_from_bmap(bmap);
7976 
7977 	set = parameter_compute_divs(bset);
7978 	map = set_to_map(set);
7979 	map = replace_space_by_local_space(map, ls);
7980 
7981 	return map;
7982 error:
7983 	isl_basic_map_free(bmap);
7984 	return NULL;
7985 }
7986 
7987 /* Remove the explicit representation of local variable "div",
7988  * if there is any.
7989  */
isl_basic_map_mark_div_unknown(__isl_take isl_basic_map * bmap,int div)7990 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7991 	__isl_take isl_basic_map *bmap, int div)
7992 {
7993 	isl_bool unknown;
7994 
7995 	unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7996 	if (unknown < 0)
7997 		return isl_basic_map_free(bmap);
7998 	if (unknown)
7999 		return bmap;
8000 
8001 	bmap = isl_basic_map_cow(bmap);
8002 	if (!bmap)
8003 		return NULL;
8004 	isl_int_set_si(bmap->div[div][0], 0);
8005 	return bmap;
8006 }
8007 
8008 /* Is local variable "div" of "bmap" marked as not having an explicit
8009  * representation?
8010  * Note that even if "div" is not marked in this way and therefore
8011  * has an explicit representation, this representation may still
8012  * depend (indirectly) on other local variables that do not
8013  * have an explicit representation.
8014  */
isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map * bmap,int div)8015 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
8016 	int div)
8017 {
8018 	if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
8019 		return isl_bool_error;
8020 	return isl_int_is_zero(bmap->div[div][0]);
8021 }
8022 
8023 /* Return the position of the first local variable that does not
8024  * have an explicit representation.
8025  * Return the total number of local variables if they all have
8026  * an explicit representation.
8027  * Return -1 on error.
8028  */
isl_basic_map_first_unknown_div(__isl_keep isl_basic_map * bmap)8029 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
8030 {
8031 	int i;
8032 
8033 	if (!bmap)
8034 		return -1;
8035 
8036 	for (i = 0; i < bmap->n_div; ++i) {
8037 		if (!isl_basic_map_div_is_known(bmap, i))
8038 			return i;
8039 	}
8040 	return bmap->n_div;
8041 }
8042 
8043 /* Return the position of the first local variable that does not
8044  * have an explicit representation.
8045  * Return the total number of local variables if they all have
8046  * an explicit representation.
8047  * Return -1 on error.
8048  */
isl_basic_set_first_unknown_div(__isl_keep isl_basic_set * bset)8049 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
8050 {
8051 	return isl_basic_map_first_unknown_div(bset);
8052 }
8053 
8054 /* Does "bmap" have an explicit representation for all local variables?
8055  */
isl_basic_map_divs_known(__isl_keep isl_basic_map * bmap)8056 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
8057 {
8058 	int first;
8059 	isl_size n;
8060 
8061 	n = isl_basic_map_dim(bmap, isl_dim_div);
8062 	first = isl_basic_map_first_unknown_div(bmap);
8063 	if (n < 0 || first < 0)
8064 		return isl_bool_error;
8065 	return first == n;
8066 }
8067 
8068 /* Do all basic maps in "map" have an explicit representation
8069  * for all local variables?
8070  */
isl_map_divs_known(__isl_keep isl_map * map)8071 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
8072 {
8073 	int i;
8074 
8075 	if (!map)
8076 		return isl_bool_error;
8077 
8078 	for (i = 0; i < map->n; ++i) {
8079 		int known = isl_basic_map_divs_known(map->p[i]);
8080 		if (known <= 0)
8081 			return known;
8082 	}
8083 
8084 	return isl_bool_true;
8085 }
8086 
8087 /* If bmap contains any unknown divs, then compute explicit
8088  * expressions for them.  However, this computation may be
8089  * quite expensive, so first try to remove divs that aren't
8090  * strictly needed.
8091  */
isl_basic_map_compute_divs(__isl_take isl_basic_map * bmap)8092 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
8093 {
8094 	int known;
8095 	struct isl_map *map;
8096 
8097 	known = isl_basic_map_divs_known(bmap);
8098 	if (known < 0)
8099 		goto error;
8100 	if (known)
8101 		return isl_map_from_basic_map(bmap);
8102 
8103 	bmap = isl_basic_map_drop_redundant_divs(bmap);
8104 
8105 	known = isl_basic_map_divs_known(bmap);
8106 	if (known < 0)
8107 		goto error;
8108 	if (known)
8109 		return isl_map_from_basic_map(bmap);
8110 
8111 	map = compute_divs(bmap);
8112 	return map;
8113 error:
8114 	isl_basic_map_free(bmap);
8115 	return NULL;
8116 }
8117 
isl_map_compute_divs(__isl_take isl_map * map)8118 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
8119 {
8120 	int i;
8121 	int known;
8122 	struct isl_map *res;
8123 
8124 	if (!map)
8125 		return NULL;
8126 	if (map->n == 0)
8127 		return map;
8128 
8129 	known = isl_map_divs_known(map);
8130 	if (known < 0) {
8131 		isl_map_free(map);
8132 		return NULL;
8133 	}
8134 	if (known)
8135 		return map;
8136 
8137 	res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
8138 	for (i = 1 ; i < map->n; ++i) {
8139 		struct isl_map *r2;
8140 		r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
8141 		if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
8142 			res = isl_map_union_disjoint(res, r2);
8143 		else
8144 			res = isl_map_union(res, r2);
8145 	}
8146 	isl_map_free(map);
8147 
8148 	return res;
8149 }
8150 
isl_basic_set_compute_divs(__isl_take isl_basic_set * bset)8151 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
8152 {
8153 	return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
8154 }
8155 
isl_set_compute_divs(__isl_take isl_set * set)8156 __isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set)
8157 {
8158 	return set_from_map(isl_map_compute_divs(set_to_map(set)));
8159 }
8160 
isl_map_domain(__isl_take isl_map * map)8161 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
8162 {
8163 	isl_space *space;
8164 	isl_size n_out;
8165 
8166 	n_out = isl_map_dim(map, isl_dim_out);
8167 	if (n_out < 0)
8168 		return set_from_map(isl_map_free(map));
8169 	space = isl_space_domain(isl_map_get_space(map));
8170 
8171 	map = isl_map_project_out(map, isl_dim_out, 0, n_out);
8172 
8173 	return set_from_map(isl_map_reset_space(map, space));
8174 }
8175 
8176 /* Return the union of "map1" and "map2", where we assume for now that
8177  * "map1" and "map2" are disjoint.  Note that the basic maps inside
8178  * "map1" or "map2" may not be disjoint from each other.
8179  * Also note that this function is also called from isl_map_union,
8180  * which takes care of handling the situation where "map1" and "map2"
8181  * may not be disjoint.
8182  *
8183  * If one of the inputs is empty, we can simply return the other input.
8184  * Similarly, if one of the inputs is universal, then it is equal to the union.
8185  */
map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8186 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
8187 	__isl_take isl_map *map2)
8188 {
8189 	int i;
8190 	unsigned flags = 0;
8191 	struct isl_map *map = NULL;
8192 	int is_universe;
8193 
8194 	if (isl_map_check_equal_space(map1, map2) < 0)
8195 		goto error;
8196 
8197 	if (map1->n == 0) {
8198 		isl_map_free(map1);
8199 		return map2;
8200 	}
8201 	if (map2->n == 0) {
8202 		isl_map_free(map2);
8203 		return map1;
8204 	}
8205 
8206 	is_universe = isl_map_plain_is_universe(map1);
8207 	if (is_universe < 0)
8208 		goto error;
8209 	if (is_universe) {
8210 		isl_map_free(map2);
8211 		return map1;
8212 	}
8213 
8214 	is_universe = isl_map_plain_is_universe(map2);
8215 	if (is_universe < 0)
8216 		goto error;
8217 	if (is_universe) {
8218 		isl_map_free(map1);
8219 		return map2;
8220 	}
8221 
8222 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
8223 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
8224 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8225 
8226 	map = isl_map_alloc_space(isl_space_copy(map1->dim),
8227 				map1->n + map2->n, flags);
8228 	if (!map)
8229 		goto error;
8230 	for (i = 0; i < map1->n; ++i) {
8231 		map = isl_map_add_basic_map(map,
8232 				  isl_basic_map_copy(map1->p[i]));
8233 		if (!map)
8234 			goto error;
8235 	}
8236 	for (i = 0; i < map2->n; ++i) {
8237 		map = isl_map_add_basic_map(map,
8238 				  isl_basic_map_copy(map2->p[i]));
8239 		if (!map)
8240 			goto error;
8241 	}
8242 	isl_map_free(map1);
8243 	isl_map_free(map2);
8244 	return map;
8245 error:
8246 	isl_map_free(map);
8247 	isl_map_free(map1);
8248 	isl_map_free(map2);
8249 	return NULL;
8250 }
8251 
8252 /* Return the union of "map1" and "map2", where "map1" and "map2" are
8253  * guaranteed to be disjoint by the caller.
8254  *
8255  * Note that this functions is called from within isl_map_make_disjoint,
8256  * so we have to be careful not to touch the constraints of the inputs
8257  * in any way.
8258  */
isl_map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8259 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
8260 	__isl_take isl_map *map2)
8261 {
8262 	isl_map_align_params_bin(&map1, &map2);
8263 	return map_union_disjoint(map1, map2);
8264 }
8265 
8266 /* Return the union of "map1" and "map2", where "map1" and "map2" may
8267  * not be disjoint.
8268  *
8269  * We currently simply call map_union_disjoint, the internal operation
8270  * of which does not really depend on the inputs being disjoint.
8271  * If the result contains more than one basic map, then we clear
8272  * the disjoint flag since the result may contain basic maps from
8273  * both inputs and these are not guaranteed to be disjoint.
8274  *
8275  * As a special case, if "map1" and "map2" are obviously equal,
8276  * then we simply return "map1".
8277  */
isl_map_union(__isl_take isl_map * map1,__isl_take isl_map * map2)8278 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
8279 	__isl_take isl_map *map2)
8280 {
8281 	int equal;
8282 
8283 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8284 		goto error;
8285 
8286 	equal = isl_map_plain_is_equal(map1, map2);
8287 	if (equal < 0)
8288 		goto error;
8289 	if (equal) {
8290 		isl_map_free(map2);
8291 		return map1;
8292 	}
8293 
8294 	map1 = map_union_disjoint(map1, map2);
8295 	if (!map1)
8296 		return NULL;
8297 	if (map1->n > 1)
8298 		ISL_F_CLR(map1, ISL_MAP_DISJOINT);
8299 	return map1;
8300 error:
8301 	isl_map_free(map1);
8302 	isl_map_free(map2);
8303 	return NULL;
8304 }
8305 
isl_set_union_disjoint(__isl_take isl_set * set1,__isl_take isl_set * set2)8306 __isl_give isl_set *isl_set_union_disjoint(
8307 	__isl_take isl_set *set1, __isl_take isl_set *set2)
8308 {
8309 	return set_from_map(isl_map_union_disjoint(set_to_map(set1),
8310 						    set_to_map(set2)));
8311 }
8312 
isl_set_union(__isl_take isl_set * set1,__isl_take isl_set * set2)8313 __isl_give isl_set *isl_set_union(__isl_take isl_set *set1,
8314 	__isl_take isl_set *set2)
8315 {
8316 	return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
8317 }
8318 
8319 /* Apply "fn" to pairs of elements from "map" and "set" and collect
8320  * the results in a map living in "space".
8321  *
8322  * "map" and "set" are assumed to be compatible and non-NULL.
8323  */
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))8324 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
8325 	__isl_take isl_space *space, __isl_take isl_set *set,
8326 	__isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
8327 		__isl_take isl_basic_set *bset))
8328 {
8329 	unsigned flags = 0;
8330 	struct isl_map *result;
8331 	int i, j;
8332 
8333 	if (isl_set_plain_is_universe(set)) {
8334 		isl_set_free(set);
8335 		return isl_map_reset_equal_dim_space(map, space);
8336 	}
8337 
8338 	if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
8339 	    ISL_F_ISSET(set, ISL_MAP_DISJOINT))
8340 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8341 
8342 	result = isl_map_alloc_space(space, map->n * set->n, flags);
8343 	for (i = 0; result && i < map->n; ++i)
8344 		for (j = 0; j < set->n; ++j) {
8345 			result = isl_map_add_basic_map(result,
8346 					fn(isl_basic_map_copy(map->p[i]),
8347 					    isl_basic_set_copy(set->p[j])));
8348 			if (!result)
8349 				break;
8350 		}
8351 
8352 	isl_map_free(map);
8353 	isl_set_free(set);
8354 	return result;
8355 }
8356 
isl_map_intersect_range(__isl_take isl_map * map,__isl_take isl_set * set)8357 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
8358 	__isl_take isl_set *set)
8359 {
8360 	isl_bool ok;
8361 	isl_space *space;
8362 
8363 	isl_map_align_params_set(&map, &set);
8364 	ok = isl_map_compatible_range(map, set);
8365 	if (ok < 0)
8366 		goto error;
8367 	if (!ok)
8368 		isl_die(set->ctx, isl_error_invalid,
8369 			"incompatible spaces", goto error);
8370 
8371 	space = isl_map_get_space(map);
8372 	return map_intersect_set(map, space, set,
8373 				&isl_basic_map_intersect_range);
8374 error:
8375 	isl_map_free(map);
8376 	isl_set_free(set);
8377 	return NULL;
8378 }
8379 
8380 /* Intersect the domain of "map" with "set".
8381  *
8382  * If the domain dimensions of "map" do not have any identifiers,
8383  * then copy them over from "set".
8384  */
isl_map_intersect_domain(__isl_take isl_map * map,__isl_take isl_set * set)8385 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
8386 	__isl_take isl_set *set)
8387 {
8388 	isl_bool ok;
8389 	isl_space *space;
8390 
8391 	isl_map_align_params_set(&map, &set);
8392 	ok = isl_map_compatible_domain(map, set);
8393 	if (ok < 0)
8394 		goto error;
8395 	if (!ok)
8396 		isl_die(set->ctx, isl_error_invalid,
8397 			"incompatible spaces", goto error);
8398 
8399 	space = isl_map_get_space(map);
8400 	space = isl_space_copy_ids_if_unset(space, isl_dim_in,
8401 					isl_set_peek_space(set), isl_dim_set);
8402 	return map_intersect_set(map, space, set,
8403 				&isl_basic_map_intersect_domain);
8404 error:
8405 	isl_map_free(map);
8406 	isl_set_free(set);
8407 	return NULL;
8408 }
8409 
8410 #undef TYPE
8411 #define TYPE isl_map
8412 static
8413 #include "isl_copy_tuple_id_templ.c"
8414 
8415 /* Data structure that specifies how isl_map_intersect_factor
8416  * should operate.
8417  *
8418  * "preserve_type" is the tuple where the factor differs from
8419  * the input map and of which the identifiers needs
8420  * to be preserved explicitly.
8421  * "other_factor" is used to extract the space of the other factor
8422  * from the space of the product ("map").
8423  * "product" is used to combine the given factor and a universe map
8424  * in the space returned by "other_factor" to produce a map
8425  * that lives in the same space as the input map.
8426  */
8427 struct isl_intersect_factor_control {
8428 	enum isl_dim_type preserve_type;
8429 	__isl_give isl_space *(*other_factor)(__isl_take isl_space *space);
8430 	__isl_give isl_map *(*product)(__isl_take isl_map *factor,
8431 		__isl_take isl_map *other);
8432 };
8433 
8434 /* Given a map "map" in some product space and a map "factor"
8435  * living in some factor space, return the intersection.
8436  *
8437  * After aligning the parameters,
8438  * the map "factor" is first extended to a map living in the same space
8439  * as "map" and then a regular intersection is computed.
8440  *
8441  * Note that the extension is computed as a product, which is anonymous
8442  * by default.  If "map" has an identifier on the corresponding tuple,
8443  * then this identifier needs to be set on the product
8444  * before the intersection is computed.
8445  */
isl_map_intersect_factor(__isl_take isl_map * map,__isl_take isl_map * factor,struct isl_intersect_factor_control * control)8446 static __isl_give isl_map *isl_map_intersect_factor(
8447 	__isl_take isl_map *map, __isl_take isl_map *factor,
8448 	struct isl_intersect_factor_control *control)
8449 {
8450 	isl_bool equal;
8451 	isl_space *space;
8452 	isl_map *other, *product;
8453 
8454 	equal = isl_map_has_equal_params(map, factor);
8455 	if (equal < 0)
8456 		goto error;
8457 	if (!equal) {
8458 		map = isl_map_align_params(map, isl_map_get_space(factor));
8459 		factor = isl_map_align_params(factor, isl_map_get_space(map));
8460 	}
8461 
8462 	space = isl_map_get_space(map);
8463 	other = isl_map_universe(control->other_factor(space));
8464 	product = control->product(factor, other);
8465 
8466 	space = isl_map_peek_space(map);
8467 	product = isl_map_copy_tuple_id(product, control->preserve_type,
8468 					space, control->preserve_type);
8469 	return map_intersect(map, product);
8470 error:
8471 	isl_map_free(map);
8472 	isl_map_free(factor);
8473 	return NULL;
8474 }
8475 
8476 /* Return the domain product of "map2" and "map1".
8477  */
isl_map_reverse_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8478 static __isl_give isl_map *isl_map_reverse_domain_product(
8479 	__isl_take isl_map *map1, __isl_take isl_map *map2)
8480 {
8481 	return isl_map_domain_product(map2, map1);
8482 }
8483 
8484 /* Return the range product of "map2" and "map1".
8485  */
isl_map_reverse_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8486 static __isl_give isl_map *isl_map_reverse_range_product(
8487 	__isl_take isl_map *map1, __isl_take isl_map *map2)
8488 {
8489 	return isl_map_range_product(map2, map1);
8490 }
8491 
8492 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8493  * in the space A -> C, return the intersection.
8494  */
isl_map_intersect_domain_factor_domain(__isl_take isl_map * map,__isl_take isl_map * factor)8495 __isl_give isl_map *isl_map_intersect_domain_factor_domain(
8496 	__isl_take isl_map *map, __isl_take isl_map *factor)
8497 {
8498 	struct isl_intersect_factor_control control = {
8499 		.preserve_type = isl_dim_in,
8500 		.other_factor = isl_space_domain_factor_range,
8501 		.product = isl_map_domain_product,
8502 	};
8503 
8504 	return isl_map_intersect_factor(map, factor, &control);
8505 }
8506 
8507 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8508  * in the space B -> C, return the intersection.
8509  */
isl_map_intersect_domain_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8510 __isl_give isl_map *isl_map_intersect_domain_factor_range(
8511 	__isl_take isl_map *map, __isl_take isl_map *factor)
8512 {
8513 	struct isl_intersect_factor_control control = {
8514 		.preserve_type = isl_dim_in,
8515 		.other_factor = isl_space_domain_factor_domain,
8516 		.product = isl_map_reverse_domain_product,
8517 	};
8518 
8519 	return isl_map_intersect_factor(map, factor, &control);
8520 }
8521 
8522 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8523  * in the space A -> B, return the intersection.
8524  */
isl_map_intersect_range_factor_domain(__isl_take isl_map * map,__isl_take isl_map * factor)8525 __isl_give isl_map *isl_map_intersect_range_factor_domain(
8526 	__isl_take isl_map *map, __isl_take isl_map *factor)
8527 {
8528 	struct isl_intersect_factor_control control = {
8529 		.preserve_type = isl_dim_out,
8530 		.other_factor = isl_space_range_factor_range,
8531 		.product = isl_map_range_product,
8532 	};
8533 
8534 	return isl_map_intersect_factor(map, factor, &control);
8535 }
8536 
8537 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8538  * in the space A -> C, return the intersection.
8539  */
isl_map_intersect_range_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8540 __isl_give isl_map *isl_map_intersect_range_factor_range(
8541 	__isl_take isl_map *map, __isl_take isl_map *factor)
8542 {
8543 	struct isl_intersect_factor_control control = {
8544 		.preserve_type = isl_dim_out,
8545 		.other_factor = isl_space_range_factor_domain,
8546 		.product = isl_map_reverse_range_product,
8547 	};
8548 
8549 	return isl_map_intersect_factor(map, factor, &control);
8550 }
8551 
8552 /* Given a set "set" in a space [A -> B] and a set "domain"
8553  * in the space A, return the intersection.
8554  *
8555  * The set "domain" is first extended to a set living in the space
8556  * [A -> B] and then a regular intersection is computed.
8557  */
isl_set_intersect_factor_domain(__isl_take isl_set * set,__isl_take isl_set * domain)8558 __isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
8559 	__isl_take isl_set *domain)
8560 {
8561 	struct isl_intersect_factor_control control = {
8562 		.preserve_type = isl_dim_set,
8563 		.other_factor = isl_space_factor_range,
8564 		.product = isl_map_range_product,
8565 	};
8566 
8567 	return set_from_map(isl_map_intersect_factor(set_to_map(set),
8568 						set_to_map(domain), &control));
8569 }
8570 
8571 /* Given a set "set" in a space [A -> B] and a set "range"
8572  * in the space B, return the intersection.
8573  *
8574  * The set "range" is first extended to a set living in the space
8575  * [A -> B] and then a regular intersection is computed.
8576  */
isl_set_intersect_factor_range(__isl_take isl_set * set,__isl_take isl_set * range)8577 __isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
8578 	__isl_take isl_set *range)
8579 {
8580 	struct isl_intersect_factor_control control = {
8581 		.preserve_type = isl_dim_set,
8582 		.other_factor = isl_space_factor_domain,
8583 		.product = isl_map_reverse_range_product,
8584 	};
8585 
8586 	return set_from_map(isl_map_intersect_factor(set_to_map(set),
8587 						set_to_map(range), &control));
8588 }
8589 
isl_map_apply_domain(__isl_take isl_map * map1,__isl_take isl_map * map2)8590 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8591 	__isl_take isl_map *map2)
8592 {
8593 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8594 		goto error;
8595 	map1 = isl_map_reverse(map1);
8596 	map1 = isl_map_apply_range(map1, map2);
8597 	return isl_map_reverse(map1);
8598 error:
8599 	isl_map_free(map1);
8600 	isl_map_free(map2);
8601 	return NULL;
8602 }
8603 
isl_map_apply_range(__isl_take isl_map * map1,__isl_take isl_map * map2)8604 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8605 	__isl_take isl_map *map2)
8606 {
8607 	isl_space *space;
8608 	struct isl_map *result;
8609 	int i, j;
8610 
8611 	if (isl_map_align_params_bin(&map1, &map2) < 0)
8612 		goto error;
8613 
8614 	space = isl_space_join(isl_space_copy(map1->dim),
8615 				  isl_space_copy(map2->dim));
8616 
8617 	result = isl_map_alloc_space(space, map1->n * map2->n, 0);
8618 	if (!result)
8619 		goto error;
8620 	for (i = 0; i < map1->n; ++i)
8621 		for (j = 0; j < map2->n; ++j) {
8622 			result = isl_map_add_basic_map(result,
8623 			    isl_basic_map_apply_range(
8624 				isl_basic_map_copy(map1->p[i]),
8625 				isl_basic_map_copy(map2->p[j])));
8626 			if (!result)
8627 				goto error;
8628 		}
8629 	isl_map_free(map1);
8630 	isl_map_free(map2);
8631 	if (result && result->n <= 1)
8632 		ISL_F_SET(result, ISL_MAP_DISJOINT);
8633 	return result;
8634 error:
8635 	isl_map_free(map1);
8636 	isl_map_free(map2);
8637 	return NULL;
8638 }
8639 
8640 /* Is "bmap" a transformation, i.e.,
8641  * does it relate elements from the same space.
8642  */
isl_basic_map_is_transformation(__isl_keep isl_basic_map * bmap)8643 isl_bool isl_basic_map_is_transformation(__isl_keep isl_basic_map *bmap)
8644 {
8645 	isl_space *space;
8646 
8647 	space = isl_basic_map_peek_space(bmap);
8648 	return isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8649 }
8650 
8651 /* Check that "bmap" is a transformation, i.e.,
8652  * that it relates elements from the same space.
8653  */
isl_basic_map_check_transformation(__isl_keep isl_basic_map * bmap)8654 static isl_stat isl_basic_map_check_transformation(
8655 	__isl_keep isl_basic_map *bmap)
8656 {
8657 	isl_bool equal;
8658 
8659 	equal = isl_basic_map_is_transformation(bmap);
8660 	if (equal < 0)
8661 		return isl_stat_error;
8662 	if (!equal)
8663 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
8664 			"domain and range don't match", return isl_stat_error);
8665 	return isl_stat_ok;
8666 }
8667 
8668 /*
8669  * returns range - domain
8670  */
isl_basic_map_deltas(__isl_take isl_basic_map * bmap)8671 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8672 {
8673 	isl_space *target_space;
8674 	struct isl_basic_set *bset;
8675 	isl_size dim;
8676 	isl_size nparam;
8677 	isl_size total;
8678 	int i;
8679 
8680 	if (isl_basic_map_check_transformation(bmap) < 0)
8681 		return isl_basic_map_free(bmap);
8682 	dim = isl_basic_map_dim(bmap, isl_dim_in);
8683 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
8684 	if (dim < 0 || nparam < 0)
8685 		goto error;
8686 	target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8687 	bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8688 	bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8689 	total = isl_basic_map_dim(bmap, isl_dim_all);
8690 	if (total < 0)
8691 		bmap = isl_basic_map_free(bmap);
8692 	bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8693 	for (i = 0; i < dim; ++i) {
8694 		int j = isl_basic_map_alloc_equality(bmap);
8695 		if (j < 0) {
8696 			bmap = isl_basic_map_free(bmap);
8697 			break;
8698 		}
8699 		isl_seq_clr(bmap->eq[j], 1 + total);
8700 		isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8701 		isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8702 		isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8703 	}
8704 	bset = isl_basic_map_domain(bmap);
8705 	bset = isl_basic_set_reset_space(bset, target_space);
8706 	return bset;
8707 error:
8708 	isl_basic_map_free(bmap);
8709 	return NULL;
8710 }
8711 
8712 /* Is the tuple of type "type1" of "map" the same as
8713  * the tuple of type "type2" of "space"?
8714  */
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)8715 isl_bool isl_map_space_tuple_is_equal(__isl_keep isl_map *map,
8716 	enum isl_dim_type type1, __isl_keep isl_space *space,
8717 	enum isl_dim_type type2)
8718 {
8719 	isl_space *map_space;
8720 
8721 	map_space = isl_map_peek_space(map);
8722 	return isl_space_tuple_is_equal(map_space, type1, space, type2);
8723 }
8724 
8725 /* Is the tuple of type "type1" of "map1" the same as
8726  * the tuple of type "type2" of "map2"?
8727  */
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)8728 isl_bool isl_map_tuple_is_equal(__isl_keep isl_map *map1,
8729 	enum isl_dim_type type1, __isl_keep isl_map *map2,
8730 	enum isl_dim_type type2)
8731 {
8732 	isl_space *space1, *space2;
8733 
8734 	space1 = isl_map_peek_space(map1);
8735 	space2 = isl_map_peek_space(map2);
8736 	return isl_space_tuple_is_equal(space1, type1, space2, type2);
8737 }
8738 
8739 /* Is the space of "obj" equal to "space", ignoring parameters?
8740  */
isl_map_has_space_tuples(__isl_keep isl_map * map,__isl_keep isl_space * space)8741 isl_bool isl_map_has_space_tuples(__isl_keep isl_map *map,
8742 	__isl_keep isl_space *space)
8743 {
8744 	isl_space *map_space;
8745 
8746 	map_space = isl_map_peek_space(map);
8747 	return isl_space_has_equal_tuples(map_space, space);
8748 }
8749 
8750 /* Check that "map" is a transformation, i.e.,
8751  * that it relates elements from the same space.
8752  */
isl_map_check_transformation(__isl_keep isl_map * map)8753 isl_stat isl_map_check_transformation(__isl_keep isl_map *map)
8754 {
8755 	isl_bool equal;
8756 
8757 	equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
8758 	if (equal < 0)
8759 		return isl_stat_error;
8760 	if (!equal)
8761 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
8762 			"domain and range don't match", return isl_stat_error);
8763 	return isl_stat_ok;
8764 }
8765 
8766 /*
8767  * returns range - domain
8768  */
isl_map_deltas(__isl_take isl_map * map)8769 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8770 {
8771 	int i;
8772 	isl_space *space;
8773 	struct isl_set *result;
8774 
8775 	if (isl_map_check_transformation(map) < 0)
8776 		goto error;
8777 	space = isl_map_get_space(map);
8778 	space = isl_space_domain(space);
8779 	result = isl_set_alloc_space(space, map->n, 0);
8780 	if (!result)
8781 		goto error;
8782 	for (i = 0; i < map->n; ++i)
8783 		result = isl_set_add_basic_set(result,
8784 			  isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8785 	isl_map_free(map);
8786 	return result;
8787 error:
8788 	isl_map_free(map);
8789 	return NULL;
8790 }
8791 
8792 /*
8793  * returns [domain -> range] -> range - domain
8794  */
isl_basic_map_deltas_map(__isl_take isl_basic_map * bmap)8795 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8796 	__isl_take isl_basic_map *bmap)
8797 {
8798 	int i, k;
8799 	isl_space *space;
8800 	isl_basic_map *domain;
8801 	isl_size nparam, n;
8802 	isl_size total;
8803 
8804 	if (isl_basic_map_check_transformation(bmap) < 0)
8805 		return isl_basic_map_free(bmap);
8806 
8807 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
8808 	n = isl_basic_map_dim(bmap, isl_dim_in);
8809 	if (nparam < 0 || n < 0)
8810 		return isl_basic_map_free(bmap);
8811 
8812 	space = isl_basic_map_get_space(bmap);
8813 	space = isl_space_from_range(isl_space_domain(space));
8814 	domain = isl_basic_map_universe(space);
8815 
8816 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8817 	bmap = isl_basic_map_apply_range(bmap, domain);
8818 	bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8819 
8820 	total = isl_basic_map_dim(bmap, isl_dim_all);
8821 	if (total < 0)
8822 		return isl_basic_map_free(bmap);
8823 
8824 	for (i = 0; i < n; ++i) {
8825 		k = isl_basic_map_alloc_equality(bmap);
8826 		if (k < 0)
8827 			goto error;
8828 		isl_seq_clr(bmap->eq[k], 1 + total);
8829 		isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8830 		isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8831 		isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8832 	}
8833 
8834 	bmap = isl_basic_map_gauss(bmap, NULL);
8835 	return isl_basic_map_finalize(bmap);
8836 error:
8837 	isl_basic_map_free(bmap);
8838 	return NULL;
8839 }
8840 
8841 /*
8842  * returns [domain -> range] -> range - domain
8843  */
isl_map_deltas_map(__isl_take isl_map * map)8844 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8845 {
8846 	if (isl_map_check_transformation(map) < 0)
8847 		return isl_map_free(map);
8848 
8849 	return isl_map_transform(map, &isl_space_range_map,
8850 					&isl_basic_map_deltas_map);
8851 }
8852 
8853 /* Return pairs of elements { x -> y } such that y - x is in "deltas".
8854  */
isl_set_translation(__isl_take isl_set * deltas)8855 __isl_give isl_map *isl_set_translation(__isl_take isl_set *deltas)
8856 {
8857 	isl_space *space;
8858 	isl_map *map;
8859 
8860 	space = isl_space_map_from_set(isl_set_get_space(deltas));
8861 	map = isl_map_deltas_map(isl_map_universe(space));
8862 	map = isl_map_intersect_range(map, deltas);
8863 
8864 	return isl_set_unwrap(isl_map_domain(map));
8865 }
8866 
isl_basic_map_identity(__isl_take isl_space * space)8867 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8868 {
8869 	isl_size n_in, n_out;
8870 
8871 	n_in = isl_space_dim(space, isl_dim_in);
8872 	n_out = isl_space_dim(space, isl_dim_out);
8873 	if (n_in < 0 || n_out < 0)
8874 		goto error;
8875 	if (n_in != n_out)
8876 		isl_die(space->ctx, isl_error_invalid,
8877 			"number of input and output dimensions needs to be "
8878 			"the same", goto error);
8879 	return isl_basic_map_equal(space, n_in);
8880 error:
8881 	isl_space_free(space);
8882 	return NULL;
8883 }
8884 
isl_map_identity(__isl_take isl_space * space)8885 __isl_give isl_map *isl_map_identity(__isl_take isl_space *space)
8886 {
8887 	return isl_map_from_basic_map(isl_basic_map_identity(space));
8888 }
8889 
isl_set_identity(__isl_take isl_set * set)8890 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8891 {
8892 	isl_space *space = isl_set_get_space(set);
8893 	isl_map *id;
8894 	id = isl_map_identity(isl_space_map_from_set(space));
8895 	return isl_map_intersect_range(id, set);
8896 }
8897 
8898 /* Construct a basic set with all set dimensions having only non-negative
8899  * values.
8900  */
isl_basic_set_positive_orthant(__isl_take isl_space * space)8901 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8902 	__isl_take isl_space *space)
8903 {
8904 	int i;
8905 	isl_size nparam;
8906 	isl_size dim;
8907 	isl_size total;
8908 	struct isl_basic_set *bset;
8909 
8910 	nparam = isl_space_dim(space, isl_dim_param);
8911 	dim = isl_space_dim(space, isl_dim_set);
8912 	total = isl_space_dim(space, isl_dim_all);
8913 	if (nparam < 0 || dim < 0 || total < 0)
8914 		space = isl_space_free(space);
8915 	bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8916 	if (!bset)
8917 		return NULL;
8918 	for (i = 0; i < dim; ++i) {
8919 		int k = isl_basic_set_alloc_inequality(bset);
8920 		if (k < 0)
8921 			goto error;
8922 		isl_seq_clr(bset->ineq[k], 1 + total);
8923 		isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8924 	}
8925 	return bset;
8926 error:
8927 	isl_basic_set_free(bset);
8928 	return NULL;
8929 }
8930 
8931 /* Construct the half-space x_pos >= 0.
8932  */
nonneg_halfspace(__isl_take isl_space * space,int pos)8933 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8934 	int pos)
8935 {
8936 	int k;
8937 	isl_size total;
8938 	isl_basic_set *nonneg;
8939 
8940 	total = isl_space_dim(space, isl_dim_all);
8941 	if (total < 0)
8942 		space = isl_space_free(space);
8943 	nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8944 	k = isl_basic_set_alloc_inequality(nonneg);
8945 	if (k < 0)
8946 		goto error;
8947 	isl_seq_clr(nonneg->ineq[k], 1 + total);
8948 	isl_int_set_si(nonneg->ineq[k][pos], 1);
8949 
8950 	return isl_basic_set_finalize(nonneg);
8951 error:
8952 	isl_basic_set_free(nonneg);
8953 	return NULL;
8954 }
8955 
8956 /* Construct the half-space x_pos <= -1.
8957  */
neg_halfspace(__isl_take isl_space * space,int pos)8958 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8959 	int pos)
8960 {
8961 	int k;
8962 	isl_size total;
8963 	isl_basic_set *neg;
8964 
8965 	total = isl_space_dim(space, isl_dim_all);
8966 	if (total < 0)
8967 		space = isl_space_free(space);
8968 	neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8969 	k = isl_basic_set_alloc_inequality(neg);
8970 	if (k < 0)
8971 		goto error;
8972 	isl_seq_clr(neg->ineq[k], 1 + total);
8973 	isl_int_set_si(neg->ineq[k][0], -1);
8974 	isl_int_set_si(neg->ineq[k][pos], -1);
8975 
8976 	return isl_basic_set_finalize(neg);
8977 error:
8978 	isl_basic_set_free(neg);
8979 	return NULL;
8980 }
8981 
isl_set_split_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)8982 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8983 	enum isl_dim_type type, unsigned first, unsigned n)
8984 {
8985 	int i;
8986 	unsigned offset;
8987 	isl_basic_set *nonneg;
8988 	isl_basic_set *neg;
8989 
8990 	if (n == 0)
8991 		return set;
8992 
8993 	if (isl_set_check_range(set, type, first, n) < 0)
8994 		return isl_set_free(set);
8995 
8996 	offset = pos(set->dim, type);
8997 	for (i = 0; i < n; ++i) {
8998 		nonneg = nonneg_halfspace(isl_set_get_space(set),
8999 					  offset + first + i);
9000 		neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
9001 
9002 		set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
9003 	}
9004 
9005 	return set;
9006 }
9007 
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)9008 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
9009 	int len,
9010 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
9011 	void *user)
9012 {
9013 	isl_set *half;
9014 
9015 	if (!set)
9016 		return isl_stat_error;
9017 	if (isl_set_plain_is_empty(set)) {
9018 		isl_set_free(set);
9019 		return isl_stat_ok;
9020 	}
9021 	if (first == len)
9022 		return fn(set, signs, user);
9023 
9024 	signs[first] = 1;
9025 	half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
9026 							1 + first));
9027 	half = isl_set_intersect(half, isl_set_copy(set));
9028 	if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
9029 		goto error;
9030 
9031 	signs[first] = -1;
9032 	half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
9033 							1 + first));
9034 	half = isl_set_intersect(half, set);
9035 	return foreach_orthant(half, signs, first + 1, len, fn, user);
9036 error:
9037 	isl_set_free(set);
9038 	return isl_stat_error;
9039 }
9040 
9041 /* Call "fn" on the intersections of "set" with each of the orthants
9042  * (except for obviously empty intersections).  The orthant is identified
9043  * by the signs array, with each entry having value 1 or -1 according
9044  * to the sign of the corresponding variable.
9045  */
isl_set_foreach_orthant(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_set * orthant,int * signs,void * user),void * user)9046 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
9047 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
9048 	void *user)
9049 {
9050 	isl_size nparam;
9051 	isl_size nvar;
9052 	int *signs;
9053 	isl_stat r;
9054 
9055 	if (!set)
9056 		return isl_stat_error;
9057 	if (isl_set_plain_is_empty(set))
9058 		return isl_stat_ok;
9059 
9060 	nparam = isl_set_dim(set, isl_dim_param);
9061 	nvar = isl_set_dim(set, isl_dim_set);
9062 	if (nparam < 0 || nvar < 0)
9063 		return isl_stat_error;
9064 
9065 	signs = isl_alloc_array(set->ctx, int, nparam + nvar);
9066 
9067 	r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
9068 			    fn, user);
9069 
9070 	free(signs);
9071 
9072 	return r;
9073 }
9074 
isl_set_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9075 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9076 {
9077 	return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
9078 }
9079 
isl_basic_map_is_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9080 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
9081 	__isl_keep isl_basic_map *bmap2)
9082 {
9083 	isl_bool is_subset;
9084 	struct isl_map *map1;
9085 	struct isl_map *map2;
9086 
9087 	if (!bmap1 || !bmap2)
9088 		return isl_bool_error;
9089 
9090 	map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
9091 	map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
9092 
9093 	is_subset = isl_map_is_subset(map1, map2);
9094 
9095 	isl_map_free(map1);
9096 	isl_map_free(map2);
9097 
9098 	return is_subset;
9099 }
9100 
isl_basic_set_is_subset(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9101 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
9102 	__isl_keep isl_basic_set *bset2)
9103 {
9104 	return isl_basic_map_is_subset(bset1, bset2);
9105 }
9106 
isl_basic_map_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9107 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
9108 	__isl_keep isl_basic_map *bmap2)
9109 {
9110 	isl_bool is_subset;
9111 
9112 	if (!bmap1 || !bmap2)
9113 		return isl_bool_error;
9114 	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9115 	if (is_subset != isl_bool_true)
9116 		return is_subset;
9117 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9118 	return is_subset;
9119 }
9120 
isl_basic_set_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9121 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
9122 	__isl_keep isl_basic_set *bset2)
9123 {
9124 	return isl_basic_map_is_equal(
9125 		bset_to_bmap(bset1), bset_to_bmap(bset2));
9126 }
9127 
isl_map_is_empty(__isl_keep isl_map * map)9128 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
9129 {
9130 	int i;
9131 	int is_empty;
9132 
9133 	if (!map)
9134 		return isl_bool_error;
9135 	for (i = 0; i < map->n; ++i) {
9136 		is_empty = isl_basic_map_is_empty(map->p[i]);
9137 		if (is_empty < 0)
9138 			return isl_bool_error;
9139 		if (!is_empty)
9140 			return isl_bool_false;
9141 	}
9142 	return isl_bool_true;
9143 }
9144 
isl_map_plain_is_empty(__isl_keep isl_map * map)9145 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
9146 {
9147 	return map ? map->n == 0 : isl_bool_error;
9148 }
9149 
isl_set_plain_is_empty(__isl_keep isl_set * set)9150 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
9151 {
9152 	return set ? set->n == 0 : isl_bool_error;
9153 }
9154 
isl_set_is_empty(__isl_keep isl_set * set)9155 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
9156 {
9157 	return isl_map_is_empty(set_to_map(set));
9158 }
9159 
9160 #undef TYPE
9161 #define TYPE	isl_basic_map
9162 
9163 static
9164 #include "isl_type_has_equal_space_bin_templ.c"
9165 #include "isl_type_check_equal_space_templ.c"
9166 
9167 /* Check that "bset1" and "bset2" live in the same space,
9168  * reporting an error if they do not.
9169  */
isl_basic_set_check_equal_space(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9170 isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
9171 	__isl_keep isl_basic_set *bset2)
9172 {
9173 	return isl_basic_map_check_equal_space(bset_to_bmap(bset1),
9174 						bset_to_bmap(bset1));
9175 }
9176 
9177 #undef TYPE
9178 #define TYPE	isl_map
9179 
9180 #include "isl_type_has_equal_space_bin_templ.c"
9181 #include "isl_type_check_equal_space_templ.c"
9182 #include "isl_type_has_space_templ.c"
9183 
isl_set_has_equal_space(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9184 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
9185 	__isl_keep isl_set *set2)
9186 {
9187 	return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));
9188 }
9189 
9190 #undef TYPE1
9191 #define TYPE1		isl_map
9192 #undef TYPE2
9193 #define TYPE2		isl_basic_map
9194 #undef TYPE_PAIR
9195 #define TYPE_PAIR	isl_map_basic_map
9196 
9197 static
9198 #include "isl_type_has_equal_space_templ.c"
9199 #include "isl_type_check_equal_space_templ.c"
9200 
9201 /* Check that "set" and "bset" live in the same space,
9202  * reporting an error if they do not.
9203  */
isl_set_basic_set_check_equal_space(__isl_keep isl_set * set,__isl_keep isl_basic_set * bset)9204 isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
9205 	__isl_keep isl_basic_set *bset)
9206 {
9207 	return isl_map_basic_map_check_equal_space(set_to_map(set),
9208 						    bset_to_bmap(bset));
9209 }
9210 
map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9211 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9212 {
9213 	isl_bool is_subset;
9214 
9215 	if (!map1 || !map2)
9216 		return isl_bool_error;
9217 	is_subset = isl_map_is_subset(map1, map2);
9218 	if (is_subset != isl_bool_true)
9219 		return is_subset;
9220 	is_subset = isl_map_is_subset(map2, map1);
9221 	return is_subset;
9222 }
9223 
9224 /* Is "map1" equal to "map2"?
9225  *
9226  * First check if they are obviously equal.
9227  * If not, then perform a more detailed analysis.
9228  */
isl_map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9229 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9230 {
9231 	isl_bool equal;
9232 
9233 	equal = isl_map_plain_is_equal(map1, map2);
9234 	if (equal < 0 || equal)
9235 		return equal;
9236 	return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
9237 }
9238 
isl_basic_map_is_strict_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9239 isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
9240 	__isl_keep isl_basic_map *bmap2)
9241 {
9242 	isl_bool is_subset;
9243 
9244 	if (!bmap1 || !bmap2)
9245 		return isl_bool_error;
9246 	is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9247 	if (is_subset != isl_bool_true)
9248 		return is_subset;
9249 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9250 	return isl_bool_not(is_subset);
9251 }
9252 
isl_map_is_strict_subset(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9253 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
9254 	__isl_keep isl_map *map2)
9255 {
9256 	isl_bool is_subset;
9257 
9258 	if (!map1 || !map2)
9259 		return isl_bool_error;
9260 	is_subset = isl_map_is_subset(map1, map2);
9261 	if (is_subset != isl_bool_true)
9262 		return is_subset;
9263 	is_subset = isl_map_is_subset(map2, map1);
9264 	return isl_bool_not(is_subset);
9265 }
9266 
isl_set_is_strict_subset(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9267 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
9268 	__isl_keep isl_set *set2)
9269 {
9270 	return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
9271 }
9272 
9273 /* Is "bmap" obviously equal to the universe with the same space?
9274  *
9275  * That is, does it not have any constraints?
9276  */
isl_basic_map_plain_is_universe(__isl_keep isl_basic_map * bmap)9277 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
9278 {
9279 	if (!bmap)
9280 		return isl_bool_error;
9281 	return bmap->n_eq == 0 && bmap->n_ineq == 0;
9282 }
9283 
9284 /* Is "bset" obviously equal to the universe with the same space?
9285  */
isl_basic_set_plain_is_universe(__isl_keep isl_basic_set * bset)9286 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
9287 {
9288 	return isl_basic_map_plain_is_universe(bset);
9289 }
9290 
9291 /* If "c" does not involve any existentially quantified variables,
9292  * then set *univ to false and abort
9293  */
involves_divs(__isl_take isl_constraint * c,void * user)9294 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
9295 {
9296 	isl_bool *univ = user;
9297 	isl_size n;
9298 
9299 	n = isl_constraint_dim(c, isl_dim_div);
9300 	if (n < 0)
9301 		c = isl_constraint_free(c);
9302 	*univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
9303 	isl_constraint_free(c);
9304 	if (*univ < 0 || !*univ)
9305 		return isl_stat_error;
9306 	return isl_stat_ok;
9307 }
9308 
9309 /* Is "bmap" equal to the universe with the same space?
9310  *
9311  * First check if it is obviously equal to the universe.
9312  * If not and if there are any constraints not involving
9313  * existentially quantified variables, then it is certainly
9314  * not equal to the universe.
9315  * Otherwise, check if the universe is a subset of "bmap".
9316  */
isl_basic_map_is_universe(__isl_keep isl_basic_map * bmap)9317 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
9318 {
9319 	isl_size n_div;
9320 	isl_bool univ;
9321 	isl_basic_map *test;
9322 
9323 	univ = isl_basic_map_plain_is_universe(bmap);
9324 	if (univ < 0 || univ)
9325 		return univ;
9326 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
9327 	if (n_div < 0)
9328 		return isl_bool_error;
9329 	if (n_div == 0)
9330 		return isl_bool_false;
9331 	univ = isl_bool_true;
9332 	if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
9333 	    univ)
9334 		return isl_bool_error;
9335 	if (univ < 0 || !univ)
9336 		return univ;
9337 	test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
9338 	univ = isl_basic_map_is_subset(test, bmap);
9339 	isl_basic_map_free(test);
9340 	return univ;
9341 }
9342 
9343 /* Is "bset" equal to the universe with the same space?
9344  */
isl_basic_set_is_universe(__isl_keep isl_basic_set * bset)9345 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
9346 {
9347 	return isl_basic_map_is_universe(bset);
9348 }
9349 
isl_map_plain_is_universe(__isl_keep isl_map * map)9350 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
9351 {
9352 	int i;
9353 
9354 	if (!map)
9355 		return isl_bool_error;
9356 
9357 	for (i = 0; i < map->n; ++i) {
9358 		isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
9359 		if (r < 0 || r)
9360 			return r;
9361 	}
9362 
9363 	return isl_bool_false;
9364 }
9365 
isl_set_plain_is_universe(__isl_keep isl_set * set)9366 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
9367 {
9368 	return isl_map_plain_is_universe(set_to_map(set));
9369 }
9370 
isl_basic_map_is_empty(__isl_keep isl_basic_map * bmap)9371 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
9372 {
9373 	struct isl_basic_set *bset = NULL;
9374 	struct isl_vec *sample = NULL;
9375 	isl_bool empty, non_empty;
9376 
9377 	if (!bmap)
9378 		return isl_bool_error;
9379 
9380 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
9381 		return isl_bool_true;
9382 
9383 	if (isl_basic_map_plain_is_universe(bmap))
9384 		return isl_bool_false;
9385 
9386 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
9387 		struct isl_basic_map *copy = isl_basic_map_copy(bmap);
9388 		copy = isl_basic_map_remove_redundancies(copy);
9389 		empty = isl_basic_map_plain_is_empty(copy);
9390 		isl_basic_map_free(copy);
9391 		return empty;
9392 	}
9393 
9394 	non_empty = isl_basic_map_plain_is_non_empty(bmap);
9395 	if (non_empty < 0)
9396 		return isl_bool_error;
9397 	if (non_empty)
9398 		return isl_bool_false;
9399 	isl_vec_free(bmap->sample);
9400 	bmap->sample = NULL;
9401 	bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
9402 	if (!bset)
9403 		return isl_bool_error;
9404 	sample = isl_basic_set_sample_vec(bset);
9405 	if (!sample)
9406 		return isl_bool_error;
9407 	empty = sample->size == 0;
9408 	isl_vec_free(bmap->sample);
9409 	bmap->sample = sample;
9410 	if (empty)
9411 		ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
9412 
9413 	return empty;
9414 }
9415 
isl_basic_map_plain_is_empty(__isl_keep isl_basic_map * bmap)9416 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
9417 {
9418 	if (!bmap)
9419 		return isl_bool_error;
9420 	return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
9421 }
9422 
isl_basic_set_plain_is_empty(__isl_keep isl_basic_set * bset)9423 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
9424 {
9425 	if (!bset)
9426 		return isl_bool_error;
9427 	return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
9428 }
9429 
9430 /* Is "bmap" known to be non-empty?
9431  *
9432  * That is, is the cached sample still valid?
9433  */
isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map * bmap)9434 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
9435 {
9436 	isl_size total;
9437 
9438 	if (!bmap)
9439 		return isl_bool_error;
9440 	if (!bmap->sample)
9441 		return isl_bool_false;
9442 	total = isl_basic_map_dim(bmap, isl_dim_all);
9443 	if (total < 0)
9444 		return isl_bool_error;
9445 	if (bmap->sample->size != 1 + total)
9446 		return isl_bool_false;
9447 	return isl_basic_map_contains(bmap, bmap->sample);
9448 }
9449 
isl_basic_set_is_empty(__isl_keep isl_basic_set * bset)9450 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
9451 {
9452 	return isl_basic_map_is_empty(bset_to_bmap(bset));
9453 }
9454 
isl_basic_map_union(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)9455 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
9456 	__isl_take isl_basic_map *bmap2)
9457 {
9458 	struct isl_map *map;
9459 
9460 	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
9461 		goto error;
9462 
9463 	map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
9464 	if (!map)
9465 		goto error;
9466 	map = isl_map_add_basic_map(map, bmap1);
9467 	map = isl_map_add_basic_map(map, bmap2);
9468 	return map;
9469 error:
9470 	isl_basic_map_free(bmap1);
9471 	isl_basic_map_free(bmap2);
9472 	return NULL;
9473 }
9474 
isl_basic_set_union(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)9475 __isl_give isl_set *isl_basic_set_union(__isl_take isl_basic_set *bset1,
9476 	__isl_take isl_basic_set *bset2)
9477 {
9478 	return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
9479 						bset_to_bmap(bset2)));
9480 }
9481 
9482 /* Order divs such that any div only depends on previous divs */
isl_basic_map_order_divs(__isl_take isl_basic_map * bmap)9483 __isl_give isl_basic_map *isl_basic_map_order_divs(
9484 	__isl_take isl_basic_map *bmap)
9485 {
9486 	int i;
9487 	isl_size off;
9488 
9489 	off = isl_basic_map_var_offset(bmap, isl_dim_div);
9490 	if (off < 0)
9491 		return isl_basic_map_free(bmap);
9492 
9493 	for (i = 0; i < bmap->n_div; ++i) {
9494 		int pos;
9495 		if (isl_int_is_zero(bmap->div[i][0]))
9496 			continue;
9497 		pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
9498 							    bmap->n_div-i);
9499 		if (pos == -1)
9500 			continue;
9501 		if (pos == 0)
9502 			isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
9503 				"integer division depends on itself",
9504 				return isl_basic_map_free(bmap));
9505 		bmap = isl_basic_map_swap_div(bmap, i, i + pos);
9506 		if (!bmap)
9507 			return NULL;
9508 		--i;
9509 	}
9510 	return bmap;
9511 }
9512 
isl_map_order_divs(__isl_take isl_map * map)9513 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
9514 {
9515 	int i;
9516 
9517 	if (!map)
9518 		return 0;
9519 
9520 	for (i = 0; i < map->n; ++i) {
9521 		map->p[i] = isl_basic_map_order_divs(map->p[i]);
9522 		if (!map->p[i])
9523 			goto error;
9524 	}
9525 
9526 	return map;
9527 error:
9528 	isl_map_free(map);
9529 	return NULL;
9530 }
9531 
9532 /* Sort the local variables of "bset".
9533  */
isl_basic_set_sort_divs(__isl_take isl_basic_set * bset)9534 __isl_give isl_basic_set *isl_basic_set_sort_divs(
9535 	__isl_take isl_basic_set *bset)
9536 {
9537 	return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
9538 }
9539 
9540 /* Apply the expansion computed by isl_merge_divs.
9541  * The expansion itself is given by "exp" while the resulting
9542  * list of divs is given by "div".
9543  *
9544  * Move the integer divisions of "bmap" into the right position
9545  * according to "exp" and then introduce the additional integer
9546  * divisions, adding div constraints.
9547  * The moving should be done first to avoid moving coefficients
9548  * in the definitions of the extra integer divisions.
9549  */
isl_basic_map_expand_divs(__isl_take isl_basic_map * bmap,__isl_take isl_mat * div,int * exp)9550 __isl_give isl_basic_map *isl_basic_map_expand_divs(
9551 	__isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
9552 {
9553 	int i, j;
9554 	int n_div;
9555 
9556 	bmap = isl_basic_map_cow(bmap);
9557 	if (!bmap || !div)
9558 		goto error;
9559 
9560 	if (div->n_row < bmap->n_div)
9561 		isl_die(isl_mat_get_ctx(div), isl_error_invalid,
9562 			"not an expansion", goto error);
9563 
9564 	n_div = bmap->n_div;
9565 	bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,
9566 					    2 * (div->n_row - n_div));
9567 
9568 	for (i = n_div; i < div->n_row; ++i)
9569 		if (isl_basic_map_alloc_div(bmap) < 0)
9570 			goto error;
9571 
9572 	for (j = n_div - 1; j >= 0; --j) {
9573 		if (exp[j] == j)
9574 			break;
9575 		bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
9576 		if (!bmap)
9577 			goto error;
9578 	}
9579 	j = 0;
9580 	for (i = 0; i < div->n_row; ++i) {
9581 		if (j < n_div && exp[j] == i) {
9582 			j++;
9583 		} else {
9584 			isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
9585 			if (isl_basic_map_div_is_marked_unknown(bmap, i))
9586 				continue;
9587 			bmap = isl_basic_map_add_div_constraints(bmap, i);
9588 			if (!bmap)
9589 				goto error;
9590 		}
9591 	}
9592 
9593 	isl_mat_free(div);
9594 	return bmap;
9595 error:
9596 	isl_basic_map_free(bmap);
9597 	isl_mat_free(div);
9598 	return NULL;
9599 }
9600 
9601 /* Apply the expansion computed by isl_merge_divs.
9602  * The expansion itself is given by "exp" while the resulting
9603  * list of divs is given by "div".
9604  */
isl_basic_set_expand_divs(__isl_take isl_basic_set * bset,__isl_take isl_mat * div,int * exp)9605 __isl_give isl_basic_set *isl_basic_set_expand_divs(
9606 	__isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
9607 {
9608 	return isl_basic_map_expand_divs(bset, div, exp);
9609 }
9610 
9611 /* Look for a div in dst that corresponds to the div "div" in src.
9612  * The divs before "div" in src and dst are assumed to be the same.
9613  *
9614  * Return the position of the corresponding div in dst
9615  * if there is one.  Otherwise, return a position beyond the integer divisions.
9616  * Return -1 on error.
9617  */
find_div(__isl_keep isl_basic_map * dst,__isl_keep isl_basic_map * src,unsigned div)9618 static int find_div(__isl_keep isl_basic_map *dst,
9619 	__isl_keep isl_basic_map *src, unsigned div)
9620 {
9621 	int i;
9622 	isl_size n_div;
9623 	isl_size v_div;
9624 
9625 	v_div = isl_basic_map_var_offset(src, isl_dim_div);
9626 	n_div = isl_basic_map_dim(dst, isl_dim_div);
9627 	if (n_div < 0 || v_div < 0)
9628 		return -1;
9629 	isl_assert(dst->ctx, div <= n_div, return -1);
9630 	for (i = div; i < n_div; ++i)
9631 		if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
9632 		    isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
9633 						n_div - div) == -1)
9634 			return i;
9635 	return n_div;
9636 }
9637 
9638 /* Align the divs of "dst" to those of "src", adding divs from "src"
9639  * if needed.  That is, make sure that the first src->n_div divs
9640  * of the result are equal to those of src.
9641  * The integer division of "src" are assumed to be ordered.
9642  *
9643  * The integer divisions are swapped into the right position
9644  * (possibly after adding them first).  This may result
9645  * in the remaining integer divisions appearing in the wrong order,
9646  * i.e., with some integer division appearing before
9647  * some other integer division on which it depends.
9648  * The integer divisions therefore need to be ordered.
9649  * This will not affect the integer divisions aligned to those of "src",
9650  * since "src" is assumed to have ordered integer divisions.
9651  *
9652  * The result is not finalized as by design it will have redundant
9653  * divs if any divs from "src" were copied.
9654  */
isl_basic_map_align_divs(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)9655 __isl_give isl_basic_map *isl_basic_map_align_divs(
9656 	__isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
9657 {
9658 	int i;
9659 	isl_bool known;
9660 	int extended;
9661 	isl_size v_div;
9662 	isl_size dst_n_div;
9663 
9664 	if (!dst || !src)
9665 		return isl_basic_map_free(dst);
9666 
9667 	if (src->n_div == 0)
9668 		return dst;
9669 
9670 	known = isl_basic_map_divs_known(src);
9671 	if (known < 0)
9672 		return isl_basic_map_free(dst);
9673 	if (!known)
9674 		isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9675 			"some src divs are unknown",
9676 			return isl_basic_map_free(dst));
9677 
9678 	v_div = isl_basic_map_var_offset(src, isl_dim_div);
9679 	if (v_div < 0)
9680 		return isl_basic_map_free(dst);
9681 
9682 	extended = 0;
9683 	dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
9684 	if (dst_n_div < 0)
9685 		dst = isl_basic_map_free(dst);
9686 	for (i = 0; i < src->n_div; ++i) {
9687 		int j = find_div(dst, src, i);
9688 		if (j < 0)
9689 			dst = isl_basic_map_free(dst);
9690 		if (j == dst_n_div) {
9691 			if (!extended) {
9692 				int extra = src->n_div - i;
9693 				dst = isl_basic_map_cow(dst);
9694 				if (!dst)
9695 					return isl_basic_map_free(dst);
9696 				dst = isl_basic_map_extend(dst,
9697 						extra, 0, 2 * extra);
9698 				extended = 1;
9699 			}
9700 			j = isl_basic_map_alloc_div(dst);
9701 			if (j < 0)
9702 				return isl_basic_map_free(dst);
9703 			isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
9704 			isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
9705 			dst_n_div++;
9706 			dst = isl_basic_map_add_div_constraints(dst, j);
9707 			if (!dst)
9708 				return isl_basic_map_free(dst);
9709 		}
9710 		if (j != i)
9711 			dst = isl_basic_map_swap_div(dst, i, j);
9712 		if (!dst)
9713 			return isl_basic_map_free(dst);
9714 	}
9715 	return isl_basic_map_order_divs(dst);
9716 }
9717 
isl_map_align_divs_internal(__isl_take isl_map * map)9718 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9719 {
9720 	int i;
9721 
9722 	if (!map)
9723 		return NULL;
9724 	if (map->n == 0)
9725 		return map;
9726 	map = isl_map_compute_divs(map);
9727 	map = isl_map_order_divs(map);
9728 	map = isl_map_cow(map);
9729 	if (!map)
9730 		return NULL;
9731 
9732 	for (i = 1; i < map->n; ++i)
9733 		map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9734 	for (i = 1; i < map->n; ++i) {
9735 		map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9736 		if (!map->p[i])
9737 			return isl_map_free(map);
9738 	}
9739 
9740 	map = isl_map_unmark_normalized(map);
9741 	return map;
9742 }
9743 
isl_map_align_divs(__isl_take isl_map * map)9744 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9745 {
9746 	return isl_map_align_divs_internal(map);
9747 }
9748 
isl_set_align_divs(__isl_take isl_set * set)9749 __isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set)
9750 {
9751 	return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9752 }
9753 
9754 /* Align the divs of the basic maps in "map" to those
9755  * of the basic maps in "list", as well as to the other basic maps in "map".
9756  * The elements in "list" are assumed to have known divs.
9757  */
isl_map_align_divs_to_basic_map_list(__isl_take isl_map * map,__isl_keep isl_basic_map_list * list)9758 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9759 	__isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9760 {
9761 	int i;
9762 	isl_size n;
9763 
9764 	n = isl_basic_map_list_n_basic_map(list);
9765 	map = isl_map_compute_divs(map);
9766 	map = isl_map_cow(map);
9767 	if (!map || n < 0)
9768 		return isl_map_free(map);
9769 	if (map->n == 0)
9770 		return map;
9771 
9772 	for (i = 0; i < n; ++i) {
9773 		isl_basic_map *bmap;
9774 
9775 		bmap = isl_basic_map_list_get_basic_map(list, i);
9776 		bmap = isl_basic_map_order_divs(bmap);
9777 		map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9778 		isl_basic_map_free(bmap);
9779 	}
9780 	if (!map->p[0])
9781 		return isl_map_free(map);
9782 
9783 	return isl_map_align_divs_internal(map);
9784 }
9785 
9786 /* Align the divs of each element of "list" to those of "bmap".
9787  * Both "bmap" and the elements of "list" are assumed to have known divs.
9788  */
isl_basic_map_list_align_divs_to_basic_map(__isl_take isl_basic_map_list * list,__isl_keep isl_basic_map * bmap)9789 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9790 	__isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9791 {
9792 	int i;
9793 	isl_size n;
9794 
9795 	n = isl_basic_map_list_n_basic_map(list);
9796 	if (n < 0 || !bmap)
9797 		return isl_basic_map_list_free(list);
9798 
9799 	for (i = 0; i < n; ++i) {
9800 		isl_basic_map *bmap_i;
9801 
9802 		bmap_i = isl_basic_map_list_get_basic_map(list, i);
9803 		bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9804 		list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9805 	}
9806 
9807 	return list;
9808 }
9809 
isl_set_apply(__isl_take isl_set * set,__isl_take isl_map * map)9810 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9811 	__isl_take isl_map *map)
9812 {
9813 	isl_bool ok;
9814 
9815 	isl_map_align_params_set(&map, &set);
9816 	ok = isl_map_compatible_domain(map, set);
9817 	if (ok < 0)
9818 		goto error;
9819 	if (!ok)
9820 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
9821 			"incompatible spaces", goto error);
9822 	map = isl_map_intersect_domain(map, set);
9823 	set = isl_map_range(map);
9824 	return set;
9825 error:
9826 	isl_set_free(set);
9827 	isl_map_free(map);
9828 	return NULL;
9829 }
9830 
9831 /* There is no need to cow as removing empty parts doesn't change
9832  * the meaning of the set.
9833  */
isl_map_remove_empty_parts(__isl_take isl_map * map)9834 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9835 {
9836 	int i;
9837 
9838 	if (!map)
9839 		return NULL;
9840 
9841 	for (i = map->n - 1; i >= 0; --i)
9842 		map = remove_if_empty(map, i);
9843 
9844 	return map;
9845 }
9846 
isl_set_remove_empty_parts(__isl_take isl_set * set)9847 __isl_give isl_set *isl_set_remove_empty_parts(__isl_take isl_set *set)
9848 {
9849 	return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9850 }
9851 
9852 /* Create a binary relation that maps the shared initial "pos" dimensions
9853  * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9854  */
join_initial(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9855 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9856 	__isl_keep isl_basic_set *bset2, int pos)
9857 {
9858 	isl_basic_map *bmap1;
9859 	isl_basic_map *bmap2;
9860 
9861 	bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9862 	bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9863 	bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9864 					isl_dim_out, 0, pos);
9865 	bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9866 					isl_dim_out, 0, pos);
9867 	return isl_basic_map_range_product(bmap1, bmap2);
9868 }
9869 
9870 /* Given two basic sets bset1 and bset2, compute the maximal difference
9871  * between the values of dimension pos in bset1 and those in bset2
9872  * for any common value of the parameters and dimensions preceding pos.
9873  */
basic_set_maximal_difference_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos,isl_int * opt)9874 static enum isl_lp_result basic_set_maximal_difference_at(
9875 	__isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9876 	int pos, isl_int *opt)
9877 {
9878 	isl_basic_map *bmap1;
9879 	struct isl_ctx *ctx;
9880 	struct isl_vec *obj;
9881 	isl_size total;
9882 	isl_size nparam;
9883 	isl_size dim1;
9884 	enum isl_lp_result res;
9885 
9886 	nparam = isl_basic_set_dim(bset1, isl_dim_param);
9887 	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9888 	if (nparam < 0 || dim1 < 0 || !bset2)
9889 		return isl_lp_error;
9890 
9891 	bmap1 = join_initial(bset1, bset2, pos);
9892 	total = isl_basic_map_dim(bmap1, isl_dim_all);
9893 	if (total < 0)
9894 		return isl_lp_error;
9895 
9896 	ctx = bmap1->ctx;
9897 	obj = isl_vec_alloc(ctx, 1 + total);
9898 	if (!obj)
9899 		goto error;
9900 	isl_seq_clr(obj->block.data, 1 + total);
9901 	isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9902 	isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9903 	res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9904 					opt, NULL, NULL);
9905 	isl_basic_map_free(bmap1);
9906 	isl_vec_free(obj);
9907 	return res;
9908 error:
9909 	isl_basic_map_free(bmap1);
9910 	return isl_lp_error;
9911 }
9912 
9913 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9914  * for any common value of the parameters and dimensions preceding pos
9915  * in both basic sets, the values of dimension pos in bset1 are
9916  * smaller or larger than those in bset2.
9917  *
9918  * Returns
9919  *	 1 if bset1 follows bset2
9920  *	-1 if bset1 precedes bset2
9921  *	 0 if bset1 and bset2 are incomparable
9922  *	-2 if some error occurred.
9923  */
isl_basic_set_compare_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9924 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9925 	__isl_keep isl_basic_set *bset2, int pos)
9926 {
9927 	isl_int opt;
9928 	enum isl_lp_result res;
9929 	int cmp;
9930 
9931 	isl_int_init(opt);
9932 
9933 	res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9934 
9935 	if (res == isl_lp_empty)
9936 		cmp = 0;
9937 	else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9938 		  res == isl_lp_unbounded)
9939 		cmp = 1;
9940 	else if (res == isl_lp_ok && isl_int_is_neg(opt))
9941 		cmp = -1;
9942 	else
9943 		cmp = -2;
9944 
9945 	isl_int_clear(opt);
9946 	return cmp;
9947 }
9948 
9949 /* Given two basic sets bset1 and bset2, check whether
9950  * for any common value of the parameters and dimensions preceding pos
9951  * there is a value of dimension pos in bset1 that is larger
9952  * than a value of the same dimension in bset2.
9953  *
9954  * Return
9955  *	 1 if there exists such a pair
9956  *	 0 if there is no such pair, but there is a pair of equal values
9957  *	-1 otherwise
9958  *	-2 if some error occurred.
9959  */
isl_basic_set_follows_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9960 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9961 	__isl_keep isl_basic_set *bset2, int pos)
9962 {
9963 	isl_bool empty;
9964 	isl_basic_map *bmap;
9965 	isl_size dim1;
9966 
9967 	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9968 	if (dim1 < 0)
9969 		return -2;
9970 	bmap = join_initial(bset1, bset2, pos);
9971 	bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9972 					    isl_dim_out, dim1 - pos);
9973 	empty = isl_basic_map_is_empty(bmap);
9974 	if (empty < 0)
9975 		goto error;
9976 	if (empty) {
9977 		isl_basic_map_free(bmap);
9978 		return -1;
9979 	}
9980 	bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9981 					    isl_dim_out, dim1 - pos);
9982 	empty = isl_basic_map_is_empty(bmap);
9983 	if (empty < 0)
9984 		goto error;
9985 	isl_basic_map_free(bmap);
9986 	if (empty)
9987 		return 0;
9988 	return 1;
9989 error:
9990 	isl_basic_map_free(bmap);
9991 	return -2;
9992 }
9993 
9994 /* Given two sets set1 and set2, check whether
9995  * for any common value of the parameters and dimensions preceding pos
9996  * there is a value of dimension pos in set1 that is larger
9997  * than a value of the same dimension in set2.
9998  *
9999  * Return
10000  *	 1 if there exists such a pair
10001  *	 0 if there is no such pair, but there is a pair of equal values
10002  *	-1 otherwise
10003  *	-2 if some error occurred.
10004  */
isl_set_follows_at(__isl_keep isl_set * set1,__isl_keep isl_set * set2,int pos)10005 int isl_set_follows_at(__isl_keep isl_set *set1,
10006 	__isl_keep isl_set *set2, int pos)
10007 {
10008 	int i, j;
10009 	int follows = -1;
10010 
10011 	if (!set1 || !set2)
10012 		return -2;
10013 
10014 	for (i = 0; i < set1->n; ++i)
10015 		for (j = 0; j < set2->n; ++j) {
10016 			int f;
10017 			f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
10018 			if (f == 1 || f == -2)
10019 				return f;
10020 			if (f > follows)
10021 				follows = f;
10022 		}
10023 
10024 	return follows;
10025 }
10026 
isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * val)10027 static isl_bool isl_basic_map_plain_has_fixed_var(
10028 	__isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
10029 {
10030 	int i;
10031 	int d;
10032 	isl_size total;
10033 
10034 	total = isl_basic_map_dim(bmap, isl_dim_all);
10035 	if (total < 0)
10036 		return isl_bool_error;
10037 	for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
10038 		for (; d+1 > pos; --d)
10039 			if (!isl_int_is_zero(bmap->eq[i][1+d]))
10040 				break;
10041 		if (d != pos)
10042 			continue;
10043 		if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
10044 			return isl_bool_false;
10045 		if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
10046 			return isl_bool_false;
10047 		if (!isl_int_is_one(bmap->eq[i][1+d]))
10048 			return isl_bool_false;
10049 		if (val)
10050 			isl_int_neg(*val, bmap->eq[i][0]);
10051 		return isl_bool_true;
10052 	}
10053 	return isl_bool_false;
10054 }
10055 
isl_map_plain_has_fixed_var(__isl_keep isl_map * map,unsigned pos,isl_int * val)10056 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
10057 	unsigned pos, isl_int *val)
10058 {
10059 	int i;
10060 	isl_int v;
10061 	isl_int tmp;
10062 	isl_bool fixed;
10063 
10064 	if (!map)
10065 		return isl_bool_error;
10066 	if (map->n == 0)
10067 		return isl_bool_false;
10068 	if (map->n == 1)
10069 		return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
10070 	isl_int_init(v);
10071 	isl_int_init(tmp);
10072 	fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
10073 	for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
10074 		fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
10075 		if (fixed == isl_bool_true && isl_int_ne(tmp, v))
10076 			fixed = isl_bool_false;
10077 	}
10078 	if (val)
10079 		isl_int_set(*val, v);
10080 	isl_int_clear(tmp);
10081 	isl_int_clear(v);
10082 	return fixed;
10083 }
10084 
isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set * bset,unsigned pos,isl_int * val)10085 static isl_bool isl_basic_set_plain_has_fixed_var(
10086 	__isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
10087 {
10088 	return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
10089 						pos, val);
10090 }
10091 
isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int * val)10092 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
10093 	enum isl_dim_type type, unsigned pos, isl_int *val)
10094 {
10095 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10096 		return isl_bool_error;
10097 	return isl_basic_map_plain_has_fixed_var(bmap,
10098 		isl_basic_map_offset(bmap, type) - 1 + pos, val);
10099 }
10100 
10101 /* If "bmap" obviously lies on a hyperplane where the given dimension
10102  * has a fixed value, then return that value.
10103  * Otherwise return NaN.
10104  */
isl_basic_map_plain_get_val_if_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)10105 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
10106 	__isl_keep isl_basic_map *bmap,
10107 	enum isl_dim_type type, unsigned pos)
10108 {
10109 	isl_ctx *ctx;
10110 	isl_val *v;
10111 	isl_bool fixed;
10112 
10113 	if (!bmap)
10114 		return NULL;
10115 	ctx = isl_basic_map_get_ctx(bmap);
10116 	v = isl_val_alloc(ctx);
10117 	if (!v)
10118 		return NULL;
10119 	fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
10120 	if (fixed < 0)
10121 		return isl_val_free(v);
10122 	if (fixed) {
10123 		isl_int_set_si(v->d, 1);
10124 		return v;
10125 	}
10126 	isl_val_free(v);
10127 	return isl_val_nan(ctx);
10128 }
10129 
isl_map_plain_is_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_int * val)10130 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
10131 	enum isl_dim_type type, unsigned pos, isl_int *val)
10132 {
10133 	if (isl_map_check_range(map, type, pos, 1) < 0)
10134 		return isl_bool_error;
10135 	return isl_map_plain_has_fixed_var(map,
10136 		map_offset(map, type) - 1 + pos, val);
10137 }
10138 
10139 /* If "map" obviously lies on a hyperplane where the given dimension
10140  * has a fixed value, then return that value.
10141  * Otherwise return NaN.
10142  */
isl_map_plain_get_val_if_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)10143 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
10144 	enum isl_dim_type type, unsigned pos)
10145 {
10146 	isl_ctx *ctx;
10147 	isl_val *v;
10148 	isl_bool fixed;
10149 
10150 	if (!map)
10151 		return NULL;
10152 	ctx = isl_map_get_ctx(map);
10153 	v = isl_val_alloc(ctx);
10154 	if (!v)
10155 		return NULL;
10156 	fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
10157 	if (fixed < 0)
10158 		return isl_val_free(v);
10159 	if (fixed) {
10160 		isl_int_set_si(v->d, 1);
10161 		return v;
10162 	}
10163 	isl_val_free(v);
10164 	return isl_val_nan(ctx);
10165 }
10166 
10167 /* If "set" obviously lies on a hyperplane where the given dimension
10168  * has a fixed value, then return that value.
10169  * Otherwise return NaN.
10170  */
isl_set_plain_get_val_if_fixed(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10171 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
10172 	enum isl_dim_type type, unsigned pos)
10173 {
10174 	return isl_map_plain_get_val_if_fixed(set, type, pos);
10175 }
10176 
10177 /* Return a sequence of values in the same space as "set"
10178  * that are equal to the corresponding set dimensions of "set"
10179  * for those set dimensions that obviously lie on a hyperplane
10180  * where the dimension has a fixed value.
10181  * The other elements are set to NaN.
10182  */
isl_set_get_plain_multi_val_if_fixed(__isl_keep isl_set * set)10183 __isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
10184 	__isl_keep isl_set *set)
10185 {
10186 	int i;
10187 	isl_size n;
10188 	isl_space *space;
10189 	isl_multi_val *mv;
10190 
10191 	space = isl_space_drop_all_params(isl_set_get_space(set));
10192 	mv = isl_multi_val_alloc(space);
10193 	n = isl_multi_val_size(mv);
10194 	if (n < 0)
10195 		return isl_multi_val_free(mv);
10196 
10197 	for (i = 0; i < n; ++i) {
10198 		isl_val *v;
10199 
10200 		v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);
10201 		mv = isl_multi_val_set_val(mv, i, v);
10202 	}
10203 
10204 	return mv;
10205 }
10206 
10207 /* Check if dimension dim has fixed value and if so and if val is not NULL,
10208  * then return this fixed value in *val.
10209  */
isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set * bset,unsigned dim,isl_int * val)10210 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
10211 	unsigned dim, isl_int *val)
10212 {
10213 	isl_size nparam;
10214 
10215 	nparam = isl_basic_set_dim(bset, isl_dim_param);
10216 	if (nparam < 0)
10217 		return isl_bool_error;
10218 	return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
10219 }
10220 
10221 /* Return -1 if the constraint "c1" should be sorted before "c2"
10222  * and 1 if it should be sorted after "c2".
10223  * Return 0 if the two constraints are the same (up to the constant term).
10224  *
10225  * In particular, if a constraint involves later variables than another
10226  * then it is sorted after this other constraint.
10227  * uset_gist depends on constraints without existentially quantified
10228  * variables sorting first.
10229  *
10230  * For constraints that have the same latest variable, those
10231  * with the same coefficient for this latest variable (first in absolute value
10232  * and then in actual value) are grouped together.
10233  * This is useful for detecting pairs of constraints that can
10234  * be chained in their printed representation.
10235  *
10236  * Finally, within a group, constraints are sorted according to
10237  * their coefficients (excluding the constant term).
10238  */
sort_constraint_cmp(const void * p1,const void * p2,void * arg)10239 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
10240 {
10241 	isl_int **c1 = (isl_int **) p1;
10242 	isl_int **c2 = (isl_int **) p2;
10243 	int l1, l2;
10244 	unsigned size = *(unsigned *) arg;
10245 	int cmp;
10246 
10247 	l1 = isl_seq_last_non_zero(*c1 + 1, size);
10248 	l2 = isl_seq_last_non_zero(*c2 + 1, size);
10249 
10250 	if (l1 != l2)
10251 		return l1 - l2;
10252 
10253 	cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10254 	if (cmp != 0)
10255 		return cmp;
10256 	cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10257 	if (cmp != 0)
10258 		return -cmp;
10259 
10260 	return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
10261 }
10262 
10263 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
10264  * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
10265  * and 0 if the two constraints are the same (up to the constant term).
10266  */
isl_basic_map_constraint_cmp(__isl_keep isl_basic_map * bmap,isl_int * c1,isl_int * c2)10267 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
10268 	isl_int *c1, isl_int *c2)
10269 {
10270 	isl_size total;
10271 	unsigned size;
10272 
10273 	total = isl_basic_map_dim(bmap, isl_dim_all);
10274 	if (total < 0)
10275 		return -2;
10276 	size = total;
10277 	return sort_constraint_cmp(&c1, &c2, &size);
10278 }
10279 
isl_basic_map_sort_constraints(__isl_take isl_basic_map * bmap)10280 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
10281 	__isl_take isl_basic_map *bmap)
10282 {
10283 	isl_size total;
10284 	unsigned size;
10285 
10286 	if (!bmap)
10287 		return NULL;
10288 	if (bmap->n_ineq == 0)
10289 		return bmap;
10290 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
10291 		return bmap;
10292 	total = isl_basic_map_dim(bmap, isl_dim_all);
10293 	if (total < 0)
10294 		return isl_basic_map_free(bmap);
10295 	size = total;
10296 	if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
10297 		    &sort_constraint_cmp, &size) < 0)
10298 		return isl_basic_map_free(bmap);
10299 	ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
10300 	return bmap;
10301 }
10302 
isl_basic_set_sort_constraints(__isl_take isl_basic_set * bset)10303 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
10304 	__isl_take isl_basic_set *bset)
10305 {
10306 	isl_basic_map *bmap = bset_to_bmap(bset);
10307 	return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
10308 }
10309 
isl_basic_map_normalize(__isl_take isl_basic_map * bmap)10310 __isl_give isl_basic_map *isl_basic_map_normalize(
10311 	__isl_take isl_basic_map *bmap)
10312 {
10313 	bmap = isl_basic_map_remove_redundancies(bmap);
10314 	bmap = isl_basic_map_sort_constraints(bmap);
10315 	return bmap;
10316 }
isl_basic_map_plain_cmp(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10317 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
10318 	__isl_keep isl_basic_map *bmap2)
10319 {
10320 	int i, cmp;
10321 	isl_size total;
10322 	isl_space *space1, *space2;
10323 
10324 	if (!bmap1 || !bmap2)
10325 		return -1;
10326 
10327 	if (bmap1 == bmap2)
10328 		return 0;
10329 	space1 = isl_basic_map_peek_space(bmap1);
10330 	space2 = isl_basic_map_peek_space(bmap2);
10331 	cmp = isl_space_cmp(space1, space2);
10332 	if (cmp)
10333 		return cmp;
10334 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
10335 	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
10336 		return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
10337 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
10338 	    ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10339 		return 0;
10340 	if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
10341 		return 1;
10342 	if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10343 		return -1;
10344 	if (bmap1->n_eq != bmap2->n_eq)
10345 		return bmap1->n_eq - bmap2->n_eq;
10346 	if (bmap1->n_ineq != bmap2->n_ineq)
10347 		return bmap1->n_ineq - bmap2->n_ineq;
10348 	if (bmap1->n_div != bmap2->n_div)
10349 		return bmap1->n_div - bmap2->n_div;
10350 	total = isl_basic_map_dim(bmap1, isl_dim_all);
10351 	if (total < 0)
10352 		return -1;
10353 	for (i = 0; i < bmap1->n_eq; ++i) {
10354 		cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
10355 		if (cmp)
10356 			return cmp;
10357 	}
10358 	for (i = 0; i < bmap1->n_ineq; ++i) {
10359 		cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
10360 		if (cmp)
10361 			return cmp;
10362 	}
10363 	for (i = 0; i < bmap1->n_div; ++i) {
10364 		cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
10365 		if (cmp)
10366 			return cmp;
10367 	}
10368 	return 0;
10369 }
10370 
isl_basic_set_plain_cmp(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10371 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
10372 	__isl_keep isl_basic_set *bset2)
10373 {
10374 	return isl_basic_map_plain_cmp(bset1, bset2);
10375 }
10376 
isl_set_plain_cmp(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10377 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
10378 {
10379 	int i, cmp;
10380 
10381 	if (set1 == set2)
10382 		return 0;
10383 	if (set1->n != set2->n)
10384 		return set1->n - set2->n;
10385 
10386 	for (i = 0; i < set1->n; ++i) {
10387 		cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
10388 		if (cmp)
10389 			return cmp;
10390 	}
10391 
10392 	return 0;
10393 }
10394 
isl_basic_map_plain_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10395 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
10396 	__isl_keep isl_basic_map *bmap2)
10397 {
10398 	if (!bmap1 || !bmap2)
10399 		return isl_bool_error;
10400 	return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
10401 }
10402 
isl_basic_set_plain_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10403 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
10404 	__isl_keep isl_basic_set *bset2)
10405 {
10406 	return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
10407 					    bset_to_bmap(bset2));
10408 }
10409 
qsort_bmap_cmp(const void * p1,const void * p2)10410 static int qsort_bmap_cmp(const void *p1, const void *p2)
10411 {
10412 	isl_basic_map *bmap1 = *(isl_basic_map **) p1;
10413 	isl_basic_map *bmap2 = *(isl_basic_map **) p2;
10414 
10415 	return isl_basic_map_plain_cmp(bmap1, bmap2);
10416 }
10417 
10418 /* Sort the basic maps of "map" and remove duplicate basic maps.
10419  *
10420  * While removing basic maps, we make sure that the basic maps remain
10421  * sorted because isl_map_normalize expects the basic maps of the result
10422  * to be sorted.
10423  */
sort_and_remove_duplicates(__isl_take isl_map * map)10424 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
10425 {
10426 	int i, j;
10427 
10428 	map = isl_map_remove_empty_parts(map);
10429 	if (!map)
10430 		return NULL;
10431 	qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
10432 	for (i = map->n - 1; i >= 1; --i) {
10433 		if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
10434 			continue;
10435 		isl_basic_map_free(map->p[i-1]);
10436 		for (j = i; j < map->n; ++j)
10437 			map->p[j - 1] = map->p[j];
10438 		map->n--;
10439 	}
10440 
10441 	return map;
10442 }
10443 
10444 /* Remove obvious duplicates among the basic maps of "map".
10445  *
10446  * Unlike isl_map_normalize, this function does not remove redundant
10447  * constraints and only removes duplicates that have exactly the same
10448  * constraints in the input.  It does sort the constraints and
10449  * the basic maps to ease the detection of duplicates.
10450  *
10451  * If "map" has already been normalized or if the basic maps are
10452  * disjoint, then there can be no duplicates.
10453  */
isl_map_remove_obvious_duplicates(__isl_take isl_map * map)10454 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
10455 {
10456 	int i;
10457 	isl_basic_map *bmap;
10458 
10459 	if (!map)
10460 		return NULL;
10461 	if (map->n <= 1)
10462 		return map;
10463 	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
10464 		return map;
10465 	for (i = 0; i < map->n; ++i) {
10466 		bmap = isl_basic_map_copy(map->p[i]);
10467 		bmap = isl_basic_map_sort_constraints(bmap);
10468 		if (!bmap)
10469 			return isl_map_free(map);
10470 		isl_basic_map_free(map->p[i]);
10471 		map->p[i] = bmap;
10472 	}
10473 
10474 	map = sort_and_remove_duplicates(map);
10475 	return map;
10476 }
10477 
10478 /* We normalize in place, but if anything goes wrong we need
10479  * to return NULL, so we need to make sure we don't change the
10480  * meaning of any possible other copies of map.
10481  */
isl_map_normalize(__isl_take isl_map * map)10482 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
10483 {
10484 	int i;
10485 	struct isl_basic_map *bmap;
10486 
10487 	if (!map)
10488 		return NULL;
10489 	if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
10490 		return map;
10491 	for (i = 0; i < map->n; ++i) {
10492 		bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
10493 		if (!bmap)
10494 			goto error;
10495 		isl_basic_map_free(map->p[i]);
10496 		map->p[i] = bmap;
10497 	}
10498 
10499 	map = sort_and_remove_duplicates(map);
10500 	if (map)
10501 		ISL_F_SET(map, ISL_MAP_NORMALIZED);
10502 	return map;
10503 error:
10504 	isl_map_free(map);
10505 	return NULL;
10506 }
10507 
isl_set_normalize(__isl_take isl_set * set)10508 __isl_give isl_set *isl_set_normalize(__isl_take isl_set *set)
10509 {
10510 	return set_from_map(isl_map_normalize(set_to_map(set)));
10511 }
10512 
isl_map_plain_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)10513 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
10514 	__isl_keep isl_map *map2)
10515 {
10516 	int i;
10517 	isl_bool equal;
10518 
10519 	if (!map1 || !map2)
10520 		return isl_bool_error;
10521 
10522 	if (map1 == map2)
10523 		return isl_bool_true;
10524 	equal = isl_map_has_equal_space(map1, map2);
10525 	if (equal < 0 || !equal)
10526 		return equal;
10527 
10528 	map1 = isl_map_copy(map1);
10529 	map2 = isl_map_copy(map2);
10530 	map1 = isl_map_normalize(map1);
10531 	map2 = isl_map_normalize(map2);
10532 	if (!map1 || !map2)
10533 		goto error;
10534 	equal = map1->n == map2->n;
10535 	for (i = 0; equal && i < map1->n; ++i) {
10536 		equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
10537 		if (equal < 0)
10538 			goto error;
10539 	}
10540 	isl_map_free(map1);
10541 	isl_map_free(map2);
10542 	return equal;
10543 error:
10544 	isl_map_free(map1);
10545 	isl_map_free(map2);
10546 	return isl_bool_error;
10547 }
10548 
isl_set_plain_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10549 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
10550 	__isl_keep isl_set *set2)
10551 {
10552 	return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
10553 }
10554 
10555 /* Return the basic maps in "map" as a list.
10556  */
isl_map_get_basic_map_list(__isl_keep isl_map * map)10557 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
10558 	__isl_keep isl_map *map)
10559 {
10560 	int i;
10561 	isl_ctx *ctx;
10562 	isl_basic_map_list *list;
10563 
10564 	if (!map)
10565 		return NULL;
10566 	ctx = isl_map_get_ctx(map);
10567 	list = isl_basic_map_list_alloc(ctx, map->n);
10568 
10569 	for (i = 0; i < map->n; ++i) {
10570 		isl_basic_map *bmap;
10571 
10572 		bmap = isl_basic_map_copy(map->p[i]);
10573 		list = isl_basic_map_list_add(list, bmap);
10574 	}
10575 
10576 	return list;
10577 }
10578 
10579 /* Return the intersection of the elements in the non-empty list "list".
10580  * All elements are assumed to live in the same space.
10581  */
isl_basic_map_list_intersect(__isl_take isl_basic_map_list * list)10582 __isl_give isl_basic_map *isl_basic_map_list_intersect(
10583 	__isl_take isl_basic_map_list *list)
10584 {
10585 	int i;
10586 	isl_size n;
10587 	isl_basic_map *bmap;
10588 
10589 	n = isl_basic_map_list_n_basic_map(list);
10590 	if (n < 0)
10591 		goto error;
10592 	if (n < 1)
10593 		isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
10594 			"expecting non-empty list", goto error);
10595 
10596 	bmap = isl_basic_map_list_get_basic_map(list, 0);
10597 	for (i = 1; i < n; ++i) {
10598 		isl_basic_map *bmap_i;
10599 
10600 		bmap_i = isl_basic_map_list_get_basic_map(list, i);
10601 		bmap = isl_basic_map_intersect(bmap, bmap_i);
10602 	}
10603 
10604 	isl_basic_map_list_free(list);
10605 	return bmap;
10606 error:
10607 	isl_basic_map_list_free(list);
10608 	return NULL;
10609 }
10610 
10611 /* Return the intersection of the elements in the non-empty list "list".
10612  * All elements are assumed to live in the same space.
10613  */
isl_basic_set_list_intersect(__isl_take isl_basic_set_list * list)10614 __isl_give isl_basic_set *isl_basic_set_list_intersect(
10615 	__isl_take isl_basic_set_list *list)
10616 {
10617 	return isl_basic_map_list_intersect(list);
10618 }
10619 
10620 /* Return the union of the elements of "list".
10621  * The list is required to have at least one element.
10622  */
isl_basic_set_list_union(__isl_take isl_basic_set_list * list)10623 __isl_give isl_set *isl_basic_set_list_union(
10624 	__isl_take isl_basic_set_list *list)
10625 {
10626 	int i;
10627 	isl_size n;
10628 	isl_space *space;
10629 	isl_basic_set *bset;
10630 	isl_set *set;
10631 
10632 	n = isl_basic_set_list_n_basic_set(list);
10633 	if (n < 0)
10634 		goto error;
10635 	if (n < 1)
10636 		isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
10637 			"expecting non-empty list", goto error);
10638 
10639 	bset = isl_basic_set_list_get_basic_set(list, 0);
10640 	space = isl_basic_set_get_space(bset);
10641 	isl_basic_set_free(bset);
10642 
10643 	set = isl_set_alloc_space(space, n, 0);
10644 	for (i = 0; i < n; ++i) {
10645 		bset = isl_basic_set_list_get_basic_set(list, i);
10646 		set = isl_set_add_basic_set(set, bset);
10647 	}
10648 
10649 	isl_basic_set_list_free(list);
10650 	return set;
10651 error:
10652 	isl_basic_set_list_free(list);
10653 	return NULL;
10654 }
10655 
10656 /* Return the union of the elements in the non-empty list "list".
10657  * All elements are assumed to live in the same space.
10658  */
isl_set_list_union(__isl_take isl_set_list * list)10659 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
10660 {
10661 	int i;
10662 	isl_size n;
10663 	isl_set *set;
10664 
10665 	n = isl_set_list_n_set(list);
10666 	if (n < 0)
10667 		goto error;
10668 	if (n < 1)
10669 		isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
10670 			"expecting non-empty list", goto error);
10671 
10672 	set = isl_set_list_get_set(list, 0);
10673 	for (i = 1; i < n; ++i) {
10674 		isl_set *set_i;
10675 
10676 		set_i = isl_set_list_get_set(list, i);
10677 		set = isl_set_union(set, set_i);
10678 	}
10679 
10680 	isl_set_list_free(list);
10681 	return set;
10682 error:
10683 	isl_set_list_free(list);
10684 	return NULL;
10685 }
10686 
isl_basic_map_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10687 __isl_give isl_basic_map *isl_basic_map_product(
10688 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10689 {
10690 	isl_space *space_result = NULL;
10691 	struct isl_basic_map *bmap;
10692 	unsigned in1, in2, out1, out2, nparam, total, pos;
10693 	struct isl_dim_map *dim_map1, *dim_map2;
10694 
10695 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10696 		goto error;
10697 	space_result = isl_space_product(isl_space_copy(bmap1->dim),
10698 						   isl_space_copy(bmap2->dim));
10699 
10700 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10701 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10702 	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10703 	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10704 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10705 
10706 	total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
10707 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10708 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10709 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10710 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10711 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10712 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10713 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10714 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10715 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
10716 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10717 
10718 	bmap = isl_basic_map_alloc_space(space_result,
10719 			bmap1->n_div + bmap2->n_div,
10720 			bmap1->n_eq + bmap2->n_eq,
10721 			bmap1->n_ineq + bmap2->n_ineq);
10722 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10723 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10724 	bmap = isl_basic_map_simplify(bmap);
10725 	return isl_basic_map_finalize(bmap);
10726 error:
10727 	isl_basic_map_free(bmap1);
10728 	isl_basic_map_free(bmap2);
10729 	return NULL;
10730 }
10731 
isl_basic_map_flat_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10732 __isl_give isl_basic_map *isl_basic_map_flat_product(
10733 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10734 {
10735 	isl_basic_map *prod;
10736 
10737 	prod = isl_basic_map_product(bmap1, bmap2);
10738 	prod = isl_basic_map_flatten(prod);
10739 	return prod;
10740 }
10741 
isl_basic_set_flat_product(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)10742 __isl_give isl_basic_set *isl_basic_set_flat_product(
10743 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10744 {
10745 	return isl_basic_map_flat_range_product(bset1, bset2);
10746 }
10747 
isl_basic_map_domain_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10748 __isl_give isl_basic_map *isl_basic_map_domain_product(
10749 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10750 {
10751 	isl_space *space1, *space2;
10752 	isl_space *space_result = NULL;
10753 	isl_basic_map *bmap;
10754 	isl_size in1, in2, out, nparam;
10755 	unsigned total, pos;
10756 	struct isl_dim_map *dim_map1, *dim_map2;
10757 
10758 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10759 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10760 	out = isl_basic_map_dim(bmap1, isl_dim_out);
10761 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10762 	if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
10763 		goto error;
10764 
10765 	space1 = isl_basic_map_get_space(bmap1);
10766 	space2 = isl_basic_map_get_space(bmap2);
10767 	space_result = isl_space_domain_product(space1, space2);
10768 
10769 	total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10770 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10771 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10772 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10773 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10774 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10775 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10776 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10777 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10778 	isl_dim_map_div(dim_map1, bmap1, pos += out);
10779 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10780 
10781 	bmap = isl_basic_map_alloc_space(space_result,
10782 			bmap1->n_div + bmap2->n_div,
10783 			bmap1->n_eq + bmap2->n_eq,
10784 			bmap1->n_ineq + bmap2->n_ineq);
10785 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10786 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10787 	bmap = isl_basic_map_simplify(bmap);
10788 	return isl_basic_map_finalize(bmap);
10789 error:
10790 	isl_basic_map_free(bmap1);
10791 	isl_basic_map_free(bmap2);
10792 	return NULL;
10793 }
10794 
isl_basic_map_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10795 __isl_give isl_basic_map *isl_basic_map_range_product(
10796 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10797 {
10798 	isl_bool rational;
10799 	isl_space *space_result = NULL;
10800 	isl_basic_map *bmap;
10801 	isl_size in, out1, out2, nparam;
10802 	unsigned total, pos;
10803 	struct isl_dim_map *dim_map1, *dim_map2;
10804 
10805 	rational = isl_basic_map_is_rational(bmap1);
10806 	if (rational >= 0 && rational)
10807 		rational = isl_basic_map_is_rational(bmap2);
10808 	in = isl_basic_map_dim(bmap1, isl_dim_in);
10809 	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10810 	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10811 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10812 	if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
10813 		goto error;
10814 
10815 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10816 		goto error;
10817 
10818 	space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10819 					   isl_space_copy(bmap2->dim));
10820 
10821 	total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10822 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10823 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10824 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10825 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10826 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10827 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10828 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10829 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10830 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
10831 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10832 
10833 	bmap = isl_basic_map_alloc_space(space_result,
10834 			bmap1->n_div + bmap2->n_div,
10835 			bmap1->n_eq + bmap2->n_eq,
10836 			bmap1->n_ineq + bmap2->n_ineq);
10837 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10838 	bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10839 	if (rational)
10840 		bmap = isl_basic_map_set_rational(bmap);
10841 	bmap = isl_basic_map_simplify(bmap);
10842 	return isl_basic_map_finalize(bmap);
10843 error:
10844 	isl_basic_map_free(bmap1);
10845 	isl_basic_map_free(bmap2);
10846 	return NULL;
10847 }
10848 
isl_basic_map_flat_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10849 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10850 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10851 {
10852 	isl_basic_map *prod;
10853 
10854 	prod = isl_basic_map_range_product(bmap1, bmap2);
10855 	prod = isl_basic_map_flatten_range(prod);
10856 	return prod;
10857 }
10858 
10859 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10860  * and collect the results.
10861  * The result live in the space obtained by calling "space_product"
10862  * on the spaces of "map1" and "map2".
10863  * If "remove_duplicates" is set then the result may contain duplicates
10864  * (even if the inputs do not) and so we try and remove the obvious
10865  * duplicates.
10866  */
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)10867 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10868 	__isl_take isl_map *map2,
10869 	__isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10870 					   __isl_take isl_space *right),
10871 	__isl_give isl_basic_map *(*basic_map_product)(
10872 		__isl_take isl_basic_map *left,
10873 		__isl_take isl_basic_map *right),
10874 	int remove_duplicates)
10875 {
10876 	unsigned flags = 0;
10877 	struct isl_map *result;
10878 	int i, j;
10879 	isl_bool m;
10880 
10881 	m = isl_map_has_equal_params(map1, map2);
10882 	if (m < 0)
10883 		goto error;
10884 	if (!m)
10885 		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10886 			"parameters don't match", goto error);
10887 
10888 	if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10889 	    ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10890 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10891 
10892 	result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10893 					       isl_space_copy(map2->dim)),
10894 				map1->n * map2->n, flags);
10895 	if (!result)
10896 		goto error;
10897 	for (i = 0; i < map1->n; ++i)
10898 		for (j = 0; j < map2->n; ++j) {
10899 			struct isl_basic_map *part;
10900 			part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10901 						 isl_basic_map_copy(map2->p[j]));
10902 			if (isl_basic_map_is_empty(part))
10903 				isl_basic_map_free(part);
10904 			else
10905 				result = isl_map_add_basic_map(result, part);
10906 			if (!result)
10907 				goto error;
10908 		}
10909 	if (remove_duplicates)
10910 		result = isl_map_remove_obvious_duplicates(result);
10911 	isl_map_free(map1);
10912 	isl_map_free(map2);
10913 	return result;
10914 error:
10915 	isl_map_free(map1);
10916 	isl_map_free(map2);
10917 	return NULL;
10918 }
10919 
10920 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10921  */
isl_map_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10922 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10923 	__isl_take isl_map *map2)
10924 {
10925 	isl_map_align_params_bin(&map1, &map2);
10926 	return map_product(map1, map2, &isl_space_product,
10927 			&isl_basic_map_product, 0);
10928 }
10929 
10930 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10931  */
isl_map_flat_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10932 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10933 	__isl_take isl_map *map2)
10934 {
10935 	isl_map *prod;
10936 
10937 	prod = isl_map_product(map1, map2);
10938 	prod = isl_map_flatten(prod);
10939 	return prod;
10940 }
10941 
10942 /* Given two set A and B, construct its Cartesian product A x B.
10943  */
isl_set_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10944 __isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
10945 	__isl_take isl_set *set2)
10946 {
10947 	return isl_map_range_product(set1, set2);
10948 }
10949 
isl_set_flat_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10950 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10951 	__isl_take isl_set *set2)
10952 {
10953 	return isl_map_flat_range_product(set1, set2);
10954 }
10955 
10956 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10957  */
isl_map_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10958 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10959 	__isl_take isl_map *map2)
10960 {
10961 	isl_map_align_params_bin(&map1, &map2);
10962 	return map_product(map1, map2, &isl_space_domain_product,
10963 				&isl_basic_map_domain_product, 1);
10964 }
10965 
10966 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10967  */
isl_map_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10968 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10969 	__isl_take isl_map *map2)
10970 {
10971 	isl_map_align_params_bin(&map1, &map2);
10972 	return map_product(map1, map2, &isl_space_range_product,
10973 				&isl_basic_map_range_product, 1);
10974 }
10975 
10976 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10977  */
isl_map_factor_domain(__isl_take isl_map * map)10978 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10979 {
10980 	isl_space *space;
10981 	isl_size total1, keep1, total2, keep2;
10982 
10983 	total1 = isl_map_dim(map, isl_dim_in);
10984 	total2 = isl_map_dim(map, isl_dim_out);
10985 	if (total1 < 0 || total2 < 0)
10986 		return isl_map_free(map);
10987 	if (!isl_space_domain_is_wrapping(map->dim) ||
10988 	    !isl_space_range_is_wrapping(map->dim))
10989 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
10990 			"not a product", return isl_map_free(map));
10991 
10992 	space = isl_map_get_space(map);
10993 	space = isl_space_factor_domain(space);
10994 	keep1 = isl_space_dim(space, isl_dim_in);
10995 	keep2 = isl_space_dim(space, isl_dim_out);
10996 	if (keep1 < 0 || keep2 < 0)
10997 		map = isl_map_free(map);
10998 	map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10999 	map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
11000 	map = isl_map_reset_space(map, space);
11001 
11002 	return map;
11003 }
11004 
11005 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
11006  */
isl_map_factor_range(__isl_take isl_map * map)11007 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
11008 {
11009 	isl_space *space;
11010 	isl_size total1, keep1, total2, keep2;
11011 
11012 	total1 = isl_map_dim(map, isl_dim_in);
11013 	total2 = isl_map_dim(map, isl_dim_out);
11014 	if (total1 < 0 || total2 < 0)
11015 		return isl_map_free(map);
11016 	if (!isl_space_domain_is_wrapping(map->dim) ||
11017 	    !isl_space_range_is_wrapping(map->dim))
11018 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
11019 			"not a product", return isl_map_free(map));
11020 
11021 	space = isl_map_get_space(map);
11022 	space = isl_space_factor_range(space);
11023 	keep1 = isl_space_dim(space, isl_dim_in);
11024 	keep2 = isl_space_dim(space, isl_dim_out);
11025 	if (keep1 < 0 || keep2 < 0)
11026 		map = isl_map_free(map);
11027 	map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
11028 	map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
11029 	map = isl_map_reset_space(map, space);
11030 
11031 	return map;
11032 }
11033 
11034 /* Given a map of the form [A -> B] -> C, return the map A -> C.
11035  */
isl_map_domain_factor_domain(__isl_take isl_map * map)11036 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
11037 {
11038 	isl_space *space;
11039 	isl_size total, keep;
11040 
11041 	total = isl_map_dim(map, isl_dim_in);
11042 	if (total < 0)
11043 		return isl_map_free(map);
11044 	if (!isl_space_domain_is_wrapping(map->dim))
11045 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
11046 			"domain is not a product", return isl_map_free(map));
11047 
11048 	space = isl_map_get_space(map);
11049 	space = isl_space_domain_factor_domain(space);
11050 	keep = isl_space_dim(space, isl_dim_in);
11051 	if (keep < 0)
11052 		map = isl_map_free(map);
11053 	map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
11054 	map = isl_map_reset_space(map, space);
11055 
11056 	return map;
11057 }
11058 
11059 /* Given a map of the form [A -> B] -> C, return the map B -> C.
11060  */
isl_map_domain_factor_range(__isl_take isl_map * map)11061 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
11062 {
11063 	isl_space *space;
11064 	isl_size total, keep;
11065 
11066 	total = isl_map_dim(map, isl_dim_in);
11067 	if (total < 0)
11068 		return isl_map_free(map);
11069 	if (!isl_space_domain_is_wrapping(map->dim))
11070 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
11071 			"domain is not a product", return isl_map_free(map));
11072 
11073 	space = isl_map_get_space(map);
11074 	space = isl_space_domain_factor_range(space);
11075 	keep = isl_space_dim(space, isl_dim_in);
11076 	if (keep < 0)
11077 		map = isl_map_free(map);
11078 	map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
11079 	map = isl_map_reset_space(map, space);
11080 
11081 	return map;
11082 }
11083 
11084 /* Given a map A -> [B -> C], extract the map A -> B.
11085  */
isl_map_range_factor_domain(__isl_take isl_map * map)11086 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
11087 {
11088 	isl_space *space;
11089 	isl_size total, keep;
11090 
11091 	total = isl_map_dim(map, isl_dim_out);
11092 	if (total < 0)
11093 		return isl_map_free(map);
11094 	if (!isl_space_range_is_wrapping(map->dim))
11095 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
11096 			"range is not a product", return isl_map_free(map));
11097 
11098 	space = isl_map_get_space(map);
11099 	space = isl_space_range_factor_domain(space);
11100 	keep = isl_space_dim(space, isl_dim_out);
11101 	if (keep < 0)
11102 		map = isl_map_free(map);
11103 	map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
11104 	map = isl_map_reset_space(map, space);
11105 
11106 	return map;
11107 }
11108 
11109 /* Given a map A -> [B -> C], extract the map A -> C.
11110  */
isl_map_range_factor_range(__isl_take isl_map * map)11111 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
11112 {
11113 	isl_space *space;
11114 	isl_size total, keep;
11115 
11116 	total = isl_map_dim(map, isl_dim_out);
11117 	if (total < 0)
11118 		return isl_map_free(map);
11119 	if (!isl_space_range_is_wrapping(map->dim))
11120 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
11121 			"range is not a product", return isl_map_free(map));
11122 
11123 	space = isl_map_get_space(map);
11124 	space = isl_space_range_factor_range(space);
11125 	keep = isl_space_dim(space, isl_dim_out);
11126 	if (keep < 0)
11127 		map = isl_map_free(map);
11128 	map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
11129 	map = isl_map_reset_space(map, space);
11130 
11131 	return map;
11132 }
11133 
11134 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
11135  */
isl_map_flat_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)11136 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
11137 	__isl_take isl_map *map2)
11138 {
11139 	isl_map *prod;
11140 
11141 	prod = isl_map_domain_product(map1, map2);
11142 	prod = isl_map_flatten_domain(prod);
11143 	return prod;
11144 }
11145 
11146 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
11147  */
isl_map_flat_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)11148 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
11149 	__isl_take isl_map *map2)
11150 {
11151 	isl_map *prod;
11152 
11153 	prod = isl_map_range_product(map1, map2);
11154 	prod = isl_map_flatten_range(prod);
11155 	return prod;
11156 }
11157 
isl_basic_map_get_hash(__isl_keep isl_basic_map * bmap)11158 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
11159 {
11160 	int i;
11161 	uint32_t hash = isl_hash_init();
11162 	isl_size total;
11163 
11164 	if (!bmap)
11165 		return 0;
11166 	bmap = isl_basic_map_copy(bmap);
11167 	bmap = isl_basic_map_normalize(bmap);
11168 	total = isl_basic_map_dim(bmap, isl_dim_all);
11169 	if (total < 0)
11170 		return 0;
11171 	isl_hash_byte(hash, bmap->n_eq & 0xFF);
11172 	for (i = 0; i < bmap->n_eq; ++i) {
11173 		uint32_t c_hash;
11174 		c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
11175 		isl_hash_hash(hash, c_hash);
11176 	}
11177 	isl_hash_byte(hash, bmap->n_ineq & 0xFF);
11178 	for (i = 0; i < bmap->n_ineq; ++i) {
11179 		uint32_t c_hash;
11180 		c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
11181 		isl_hash_hash(hash, c_hash);
11182 	}
11183 	isl_hash_byte(hash, bmap->n_div & 0xFF);
11184 	for (i = 0; i < bmap->n_div; ++i) {
11185 		uint32_t c_hash;
11186 		if (isl_int_is_zero(bmap->div[i][0]))
11187 			continue;
11188 		isl_hash_byte(hash, i & 0xFF);
11189 		c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
11190 		isl_hash_hash(hash, c_hash);
11191 	}
11192 	isl_basic_map_free(bmap);
11193 	return hash;
11194 }
11195 
isl_basic_set_get_hash(__isl_keep isl_basic_set * bset)11196 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
11197 {
11198 	return isl_basic_map_get_hash(bset_to_bmap(bset));
11199 }
11200 
isl_map_get_hash(__isl_keep isl_map * map)11201 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
11202 {
11203 	int i;
11204 	uint32_t hash;
11205 
11206 	if (!map)
11207 		return 0;
11208 	map = isl_map_copy(map);
11209 	map = isl_map_normalize(map);
11210 	if (!map)
11211 		return 0;
11212 
11213 	hash = isl_hash_init();
11214 	for (i = 0; i < map->n; ++i) {
11215 		uint32_t bmap_hash;
11216 		bmap_hash = isl_basic_map_get_hash(map->p[i]);
11217 		isl_hash_hash(hash, bmap_hash);
11218 	}
11219 
11220 	isl_map_free(map);
11221 
11222 	return hash;
11223 }
11224 
isl_set_get_hash(__isl_keep isl_set * set)11225 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
11226 {
11227 	return isl_map_get_hash(set_to_map(set));
11228 }
11229 
11230 /* Return the number of basic maps in the (current) representation of "map".
11231  */
isl_map_n_basic_map(__isl_keep isl_map * map)11232 isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
11233 {
11234 	return map ? map->n : isl_size_error;
11235 }
11236 
isl_set_n_basic_set(__isl_keep isl_set * set)11237 isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
11238 {
11239 	return set ? set->n : isl_size_error;
11240 }
11241 
isl_map_foreach_basic_map(__isl_keep isl_map * map,isl_stat (* fn)(__isl_take isl_basic_map * bmap,void * user),void * user)11242 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
11243 	isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
11244 {
11245 	int i;
11246 
11247 	if (!map)
11248 		return isl_stat_error;
11249 
11250 	for (i = 0; i < map->n; ++i)
11251 		if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
11252 			return isl_stat_error;
11253 
11254 	return isl_stat_ok;
11255 }
11256 
isl_set_foreach_basic_set(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_basic_set * bset,void * user),void * user)11257 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
11258 	isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
11259 {
11260 	int i;
11261 
11262 	if (!set)
11263 		return isl_stat_error;
11264 
11265 	for (i = 0; i < set->n; ++i)
11266 		if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
11267 			return isl_stat_error;
11268 
11269 	return isl_stat_ok;
11270 }
11271 
11272 /* Does "test" succeed on every basic set in "set"?
11273  */
isl_set_every_basic_set(__isl_keep isl_set * set,isl_bool (* test)(__isl_keep isl_basic_set * bset,void * user),void * user)11274 isl_bool isl_set_every_basic_set(__isl_keep isl_set *set,
11275 	isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),
11276 	void *user)
11277 {
11278 	int i;
11279 
11280 	if (!set)
11281 		return isl_bool_error;
11282 
11283 	for (i = 0; i < set->n; ++i) {
11284 		isl_bool r;
11285 
11286 		r = test(set->p[i], user);
11287 		if (r < 0 || !r)
11288 			return r;
11289 	}
11290 
11291 	return isl_bool_true;
11292 }
11293 
11294 /* Return a list of basic sets, the union of which is equal to "set".
11295  */
isl_set_get_basic_set_list(__isl_keep isl_set * set)11296 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
11297 	__isl_keep isl_set *set)
11298 {
11299 	int i;
11300 	isl_basic_set_list *list;
11301 
11302 	if (!set)
11303 		return NULL;
11304 
11305 	list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
11306 	for (i = 0; i < set->n; ++i) {
11307 		isl_basic_set *bset;
11308 
11309 		bset = isl_basic_set_copy(set->p[i]);
11310 		list = isl_basic_set_list_add(list, bset);
11311 	}
11312 
11313 	return list;
11314 }
11315 
isl_basic_set_lift(__isl_take isl_basic_set * bset)11316 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
11317 {
11318 	isl_space *space;
11319 
11320 	if (!bset)
11321 		return NULL;
11322 
11323 	bset = isl_basic_set_cow(bset);
11324 	if (!bset)
11325 		return NULL;
11326 
11327 	space = isl_basic_set_get_space(bset);
11328 	space = isl_space_lift(space, bset->n_div);
11329 	if (!space)
11330 		goto error;
11331 	isl_space_free(bset->dim);
11332 	bset->dim = space;
11333 	bset->extra -= bset->n_div;
11334 	bset->n_div = 0;
11335 
11336 	bset = isl_basic_set_finalize(bset);
11337 
11338 	return bset;
11339 error:
11340 	isl_basic_set_free(bset);
11341 	return NULL;
11342 }
11343 
isl_set_lift(__isl_take isl_set * set)11344 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
11345 {
11346 	int i;
11347 	isl_space *space;
11348 	unsigned n_div;
11349 
11350 	set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
11351 
11352 	if (!set)
11353 		return NULL;
11354 
11355 	set = isl_set_cow(set);
11356 	if (!set)
11357 		return NULL;
11358 
11359 	n_div = set->p[0]->n_div;
11360 	space = isl_set_get_space(set);
11361 	space = isl_space_lift(space, n_div);
11362 	if (!space)
11363 		goto error;
11364 	isl_space_free(set->dim);
11365 	set->dim = space;
11366 
11367 	for (i = 0; i < set->n; ++i) {
11368 		set->p[i] = isl_basic_set_lift(set->p[i]);
11369 		if (!set->p[i])
11370 			goto error;
11371 	}
11372 
11373 	return set;
11374 error:
11375 	isl_set_free(set);
11376 	return NULL;
11377 }
11378 
isl_basic_set_size(__isl_keep isl_basic_set * bset)11379 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
11380 {
11381 	isl_size dim;
11382 	int size = 0;
11383 
11384 	dim = isl_basic_set_dim(bset, isl_dim_all);
11385 	if (dim < 0)
11386 		return -1;
11387 	size += bset->n_eq * (1 + dim);
11388 	size += bset->n_ineq * (1 + dim);
11389 	size += bset->n_div * (2 + dim);
11390 
11391 	return size;
11392 }
11393 
isl_set_size(__isl_keep isl_set * set)11394 int isl_set_size(__isl_keep isl_set *set)
11395 {
11396 	int i;
11397 	int size = 0;
11398 
11399 	if (!set)
11400 		return -1;
11401 
11402 	for (i = 0; i < set->n; ++i)
11403 		size += isl_basic_set_size(set->p[i]);
11404 
11405 	return size;
11406 }
11407 
11408 /* Check if there is any lower bound (if lower == 0) and/or upper
11409  * bound (if upper == 0) on the specified dim.
11410  */
basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int lower,int upper)11411 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11412 	enum isl_dim_type type, unsigned pos, int lower, int upper)
11413 {
11414 	int i;
11415 
11416 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
11417 		return isl_bool_error;
11418 
11419 	pos += isl_basic_map_offset(bmap, type);
11420 
11421 	for (i = 0; i < bmap->n_div; ++i) {
11422 		if (isl_int_is_zero(bmap->div[i][0]))
11423 			continue;
11424 		if (!isl_int_is_zero(bmap->div[i][1 + pos]))
11425 			return isl_bool_true;
11426 	}
11427 
11428 	for (i = 0; i < bmap->n_eq; ++i)
11429 		if (!isl_int_is_zero(bmap->eq[i][pos]))
11430 			return isl_bool_true;
11431 
11432 	for (i = 0; i < bmap->n_ineq; ++i) {
11433 		int sgn = isl_int_sgn(bmap->ineq[i][pos]);
11434 		if (sgn > 0)
11435 			lower = 1;
11436 		if (sgn < 0)
11437 			upper = 1;
11438 	}
11439 
11440 	return lower && upper;
11441 }
11442 
isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11443 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11444 	enum isl_dim_type type, unsigned pos)
11445 {
11446 	return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
11447 }
11448 
isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11449 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
11450 	enum isl_dim_type type, unsigned pos)
11451 {
11452 	return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
11453 }
11454 
isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11455 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
11456 	enum isl_dim_type type, unsigned pos)
11457 {
11458 	return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
11459 }
11460 
isl_map_dim_is_bounded(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)11461 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
11462 	enum isl_dim_type type, unsigned pos)
11463 {
11464 	int i;
11465 
11466 	if (!map)
11467 		return isl_bool_error;
11468 
11469 	for (i = 0; i < map->n; ++i) {
11470 		isl_bool bounded;
11471 		bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
11472 		if (bounded < 0 || !bounded)
11473 			return bounded;
11474 	}
11475 
11476 	return isl_bool_true;
11477 }
11478 
11479 /* Return true if the specified dim is involved in both an upper bound
11480  * and a lower bound.
11481  */
isl_set_dim_is_bounded(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11482 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
11483 	enum isl_dim_type type, unsigned pos)
11484 {
11485 	return isl_map_dim_is_bounded(set_to_map(set), type, pos);
11486 }
11487 
11488 /* Does "map" have a bound (according to "fn") for any of its basic maps?
11489  */
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))11490 static isl_bool has_any_bound(__isl_keep isl_map *map,
11491 	enum isl_dim_type type, unsigned pos,
11492 	isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11493 		  enum isl_dim_type type, unsigned pos))
11494 {
11495 	int i;
11496 
11497 	if (!map)
11498 		return isl_bool_error;
11499 
11500 	for (i = 0; i < map->n; ++i) {
11501 		isl_bool bounded;
11502 		bounded = fn(map->p[i], type, pos);
11503 		if (bounded < 0 || bounded)
11504 			return bounded;
11505 	}
11506 
11507 	return isl_bool_false;
11508 }
11509 
11510 /* Return 1 if the specified dim is involved in any lower bound.
11511  */
isl_set_dim_has_any_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11512 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
11513 	enum isl_dim_type type, unsigned pos)
11514 {
11515 	return has_any_bound(set, type, pos,
11516 				&isl_basic_map_dim_has_lower_bound);
11517 }
11518 
11519 /* Return 1 if the specified dim is involved in any upper bound.
11520  */
isl_set_dim_has_any_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11521 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
11522 	enum isl_dim_type type, unsigned pos)
11523 {
11524 	return has_any_bound(set, type, pos,
11525 				&isl_basic_map_dim_has_upper_bound);
11526 }
11527 
11528 /* Does "map" have a bound (according to "fn") for all of its basic maps?
11529  */
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))11530 static isl_bool has_bound(__isl_keep isl_map *map,
11531 	enum isl_dim_type type, unsigned pos,
11532 	isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11533 		  enum isl_dim_type type, unsigned pos))
11534 {
11535 	int i;
11536 
11537 	if (!map)
11538 		return isl_bool_error;
11539 
11540 	for (i = 0; i < map->n; ++i) {
11541 		isl_bool bounded;
11542 		bounded = fn(map->p[i], type, pos);
11543 		if (bounded < 0 || !bounded)
11544 			return bounded;
11545 	}
11546 
11547 	return isl_bool_true;
11548 }
11549 
11550 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
11551  */
isl_set_dim_has_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11552 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
11553 	enum isl_dim_type type, unsigned pos)
11554 {
11555 	return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
11556 }
11557 
11558 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
11559  */
isl_set_dim_has_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11560 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
11561 	enum isl_dim_type type, unsigned pos)
11562 {
11563 	return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
11564 }
11565 
11566 /* For each of the "n" variables starting at "first", determine
11567  * the sign of the variable and put the results in the first "n"
11568  * elements of the array "signs".
11569  * Sign
11570  *	1 means that the variable is non-negative
11571  *	-1 means that the variable is non-positive
11572  *	0 means the variable attains both positive and negative values.
11573  */
isl_basic_set_vars_get_sign(__isl_keep isl_basic_set * bset,unsigned first,unsigned n,int * signs)11574 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
11575 	unsigned first, unsigned n, int *signs)
11576 {
11577 	isl_vec *bound = NULL;
11578 	struct isl_tab *tab = NULL;
11579 	struct isl_tab_undo *snap;
11580 	int i;
11581 	isl_size total;
11582 
11583 	total = isl_basic_set_dim(bset, isl_dim_all);
11584 	if (total < 0 || !signs)
11585 		return isl_stat_error;
11586 
11587 	bound = isl_vec_alloc(bset->ctx, 1 + total);
11588 	tab = isl_tab_from_basic_set(bset, 0);
11589 	if (!bound || !tab)
11590 		goto error;
11591 
11592 	isl_seq_clr(bound->el, bound->size);
11593 	isl_int_set_si(bound->el[0], -1);
11594 
11595 	snap = isl_tab_snap(tab);
11596 	for (i = 0; i < n; ++i) {
11597 		int empty;
11598 
11599 		isl_int_set_si(bound->el[1 + first + i], -1);
11600 		if (isl_tab_add_ineq(tab, bound->el) < 0)
11601 			goto error;
11602 		empty = tab->empty;
11603 		isl_int_set_si(bound->el[1 + first + i], 0);
11604 		if (isl_tab_rollback(tab, snap) < 0)
11605 			goto error;
11606 
11607 		if (empty) {
11608 			signs[i] = 1;
11609 			continue;
11610 		}
11611 
11612 		isl_int_set_si(bound->el[1 + first + i], 1);
11613 		if (isl_tab_add_ineq(tab, bound->el) < 0)
11614 			goto error;
11615 		empty = tab->empty;
11616 		isl_int_set_si(bound->el[1 + first + i], 0);
11617 		if (isl_tab_rollback(tab, snap) < 0)
11618 			goto error;
11619 
11620 		signs[i] = empty ? -1 : 0;
11621 	}
11622 
11623 	isl_tab_free(tab);
11624 	isl_vec_free(bound);
11625 	return isl_stat_ok;
11626 error:
11627 	isl_tab_free(tab);
11628 	isl_vec_free(bound);
11629 	return isl_stat_error;
11630 }
11631 
isl_basic_set_dims_get_sign(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n,int * signs)11632 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
11633 	enum isl_dim_type type, unsigned first, unsigned n, int *signs)
11634 {
11635 	if (!bset || !signs)
11636 		return isl_stat_error;
11637 	if (isl_basic_set_check_range(bset, type, first, n) < 0)
11638 		return isl_stat_error;
11639 
11640 	first += pos(bset->dim, type) - 1;
11641 	return isl_basic_set_vars_get_sign(bset, first, n, signs);
11642 }
11643 
11644 /* Is it possible for the integer division "div" to depend (possibly
11645  * indirectly) on any output dimensions?
11646  *
11647  * If the div is undefined, then we conservatively assume that it
11648  * may depend on them.
11649  * Otherwise, we check if it actually depends on them or on any integer
11650  * divisions that may depend on them.
11651  */
div_may_involve_output(__isl_keep isl_basic_map * bmap,int div)11652 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
11653 {
11654 	int i;
11655 	isl_size n_out, n_div;
11656 	unsigned o_out, o_div;
11657 
11658 	if (isl_int_is_zero(bmap->div[div][0]))
11659 		return isl_bool_true;
11660 
11661 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11662 	if (n_out < 0)
11663 		return isl_bool_error;
11664 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11665 
11666 	if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
11667 		return isl_bool_true;
11668 
11669 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11670 	if (n_div < 0)
11671 		return isl_bool_error;
11672 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11673 
11674 	for (i = 0; i < n_div; ++i) {
11675 		isl_bool may_involve;
11676 
11677 		if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
11678 			continue;
11679 		may_involve = div_may_involve_output(bmap, i);
11680 		if (may_involve < 0 || may_involve)
11681 			return may_involve;
11682 	}
11683 
11684 	return isl_bool_false;
11685 }
11686 
11687 /* Return the first integer division of "bmap" in the range
11688  * [first, first + n[ that may depend on any output dimensions and
11689  * that has a non-zero coefficient in "c" (where the first coefficient
11690  * in "c" corresponds to integer division "first").
11691  */
first_div_may_involve_output(__isl_keep isl_basic_map * bmap,isl_int * c,int first,int n)11692 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
11693 	isl_int *c, int first, int n)
11694 {
11695 	int k;
11696 
11697 	if (!bmap)
11698 		return -1;
11699 
11700 	for (k = first; k < first + n; ++k) {
11701 		isl_bool may_involve;
11702 
11703 		if (isl_int_is_zero(c[k]))
11704 			continue;
11705 		may_involve = div_may_involve_output(bmap, k);
11706 		if (may_involve < 0)
11707 			return -1;
11708 		if (may_involve)
11709 			return k;
11710 	}
11711 
11712 	return first + n;
11713 }
11714 
11715 /* Look for a pair of inequality constraints in "bmap" of the form
11716  *
11717  *	-l + i >= 0		or		i >= l
11718  * and
11719  *	n + l - i >= 0		or		i <= l + n
11720  *
11721  * with n < "m" and i the output dimension at position "pos".
11722  * (Note that n >= 0 as otherwise the two constraints would conflict.)
11723  * Furthermore, "l" is only allowed to involve parameters, input dimensions
11724  * and earlier output dimensions, as well as integer divisions that do
11725  * not involve any of the output dimensions.
11726  *
11727  * Return the index of the first inequality constraint or bmap->n_ineq
11728  * if no such pair can be found.
11729  */
find_modulo_constraint_pair(__isl_keep isl_basic_map * bmap,int pos,isl_int m)11730 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
11731 	int pos, isl_int m)
11732 {
11733 	int i, j;
11734 	isl_ctx *ctx;
11735 	isl_size total;
11736 	isl_size n_div, n_out;
11737 	unsigned o_div, o_out;
11738 	int less;
11739 
11740 	total = isl_basic_map_dim(bmap, isl_dim_all);
11741 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11742 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11743 	if (total < 0 || n_out < 0 || n_div < 0)
11744 		return -1;
11745 
11746 	ctx = isl_basic_map_get_ctx(bmap);
11747 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11748 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11749 	for (i = 0; i < bmap->n_ineq; ++i) {
11750 		if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
11751 			continue;
11752 		if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
11753 					n_out - (pos + 1)) != -1)
11754 			continue;
11755 		if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11756 						0, n_div) < n_div)
11757 			continue;
11758 		for (j = i + 1; j < bmap->n_ineq; ++j) {
11759 			if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11760 					    ctx->one))
11761 				continue;
11762 			if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11763 					    bmap->ineq[j] + 1, total))
11764 				continue;
11765 			break;
11766 		}
11767 		if (j >= bmap->n_ineq)
11768 			continue;
11769 		isl_int_add(bmap->ineq[i][0],
11770 			    bmap->ineq[i][0], bmap->ineq[j][0]);
11771 		less = isl_int_abs_lt(bmap->ineq[i][0], m);
11772 		isl_int_sub(bmap->ineq[i][0],
11773 			    bmap->ineq[i][0], bmap->ineq[j][0]);
11774 		if (!less)
11775 			continue;
11776 		if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11777 			return i;
11778 		else
11779 			return j;
11780 	}
11781 
11782 	return bmap->n_ineq;
11783 }
11784 
11785 /* Return the index of the equality of "bmap" that defines
11786  * the output dimension "pos" in terms of earlier dimensions.
11787  * The equality may also involve integer divisions, as long
11788  * as those integer divisions are defined in terms of
11789  * parameters or input dimensions.
11790  * In this case, *div is set to the number of integer divisions and
11791  * *ineq is set to the number of inequality constraints (provided
11792  * div and ineq are not NULL).
11793  *
11794  * The equality may also involve a single integer division involving
11795  * the output dimensions (typically only output dimension "pos") as
11796  * long as the coefficient of output dimension "pos" is 1 or -1 and
11797  * there is a pair of constraints i >= l and i <= l + n, with i referring
11798  * to output dimension "pos", l an expression involving only earlier
11799  * dimensions and n smaller than the coefficient of the integer division
11800  * in the equality.  In this case, the output dimension can be defined
11801  * in terms of a modulo expression that does not involve the integer division.
11802  * *div is then set to this single integer division and
11803  * *ineq is set to the index of constraint i >= l.
11804  *
11805  * Return bmap->n_eq if there is no such equality.
11806  * Return -1 on error.
11807  */
isl_basic_map_output_defining_equality(__isl_keep isl_basic_map * bmap,int pos,int * div,int * ineq)11808 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11809 	int pos, int *div, int *ineq)
11810 {
11811 	int j, k, l;
11812 	isl_size n_div, n_out;
11813 	unsigned o_div, o_out;
11814 
11815 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11816 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
11817 	if (n_out < 0 || n_div < 0)
11818 		return -1;
11819 
11820 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
11821 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
11822 
11823 	if (ineq)
11824 		*ineq = bmap->n_ineq;
11825 	if (div)
11826 		*div = n_div;
11827 	for (j = 0; j < bmap->n_eq; ++j) {
11828 		if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11829 			continue;
11830 		if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11831 					n_out - (pos + 1)) != -1)
11832 			continue;
11833 		k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11834 						0, n_div);
11835 		if (k >= n_div)
11836 			return j;
11837 		if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11838 		    !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11839 			continue;
11840 		if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11841 						k + 1, n_div - (k+1)) < n_div)
11842 			continue;
11843 		l = find_modulo_constraint_pair(bmap, pos,
11844 						bmap->eq[j][o_div + k]);
11845 		if (l < 0)
11846 			return -1;
11847 		if (l >= bmap->n_ineq)
11848 			continue;
11849 		if (div)
11850 			*div = k;
11851 		if (ineq)
11852 			*ineq = l;
11853 		return j;
11854 	}
11855 
11856 	return bmap->n_eq;
11857 }
11858 
11859 /* Check if the given basic map is obviously single-valued.
11860  * In particular, for each output dimension, check that there is
11861  * an equality that defines the output dimension in terms of
11862  * earlier dimensions.
11863  */
isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map * bmap)11864 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11865 {
11866 	int i;
11867 	isl_size n_out;
11868 
11869 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
11870 	if (n_out < 0)
11871 		return isl_bool_error;
11872 
11873 	for (i = 0; i < n_out; ++i) {
11874 		int eq;
11875 
11876 		eq = isl_basic_map_output_defining_equality(bmap, i,
11877 							    NULL, NULL);
11878 		if (eq < 0)
11879 			return isl_bool_error;
11880 		if (eq >= bmap->n_eq)
11881 			return isl_bool_false;
11882 	}
11883 
11884 	return isl_bool_true;
11885 }
11886 
11887 /* Check if the given basic map is single-valued.
11888  * We simply compute
11889  *
11890  *	M \circ M^-1
11891  *
11892  * and check if the result is a subset of the identity mapping.
11893  */
isl_basic_map_is_single_valued(__isl_keep isl_basic_map * bmap)11894 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11895 {
11896 	isl_space *space;
11897 	isl_basic_map *test;
11898 	isl_basic_map *id;
11899 	isl_bool sv;
11900 
11901 	sv = isl_basic_map_plain_is_single_valued(bmap);
11902 	if (sv < 0 || sv)
11903 		return sv;
11904 
11905 	test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11906 	test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11907 
11908 	space = isl_basic_map_get_space(bmap);
11909 	space = isl_space_map_from_set(isl_space_range(space));
11910 	id = isl_basic_map_identity(space);
11911 
11912 	sv = isl_basic_map_is_subset(test, id);
11913 
11914 	isl_basic_map_free(test);
11915 	isl_basic_map_free(id);
11916 
11917 	return sv;
11918 }
11919 
11920 /* Check if the given map is obviously single-valued.
11921  */
isl_map_plain_is_single_valued(__isl_keep isl_map * map)11922 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11923 {
11924 	if (!map)
11925 		return isl_bool_error;
11926 	if (map->n == 0)
11927 		return isl_bool_true;
11928 	if (map->n >= 2)
11929 		return isl_bool_false;
11930 
11931 	return isl_basic_map_plain_is_single_valued(map->p[0]);
11932 }
11933 
11934 /* Check if the given map is single-valued.
11935  * We simply compute
11936  *
11937  *	M \circ M^-1
11938  *
11939  * and check if the result is a subset of the identity mapping.
11940  */
isl_map_is_single_valued(__isl_keep isl_map * map)11941 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11942 {
11943 	isl_space *space;
11944 	isl_map *test;
11945 	isl_map *id;
11946 	isl_bool sv;
11947 
11948 	sv = isl_map_plain_is_single_valued(map);
11949 	if (sv < 0 || sv)
11950 		return sv;
11951 
11952 	test = isl_map_reverse(isl_map_copy(map));
11953 	test = isl_map_apply_range(test, isl_map_copy(map));
11954 
11955 	space = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11956 	id = isl_map_identity(space);
11957 
11958 	sv = isl_map_is_subset(test, id);
11959 
11960 	isl_map_free(test);
11961 	isl_map_free(id);
11962 
11963 	return sv;
11964 }
11965 
isl_map_is_injective(__isl_keep isl_map * map)11966 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11967 {
11968 	isl_bool in;
11969 
11970 	map = isl_map_copy(map);
11971 	map = isl_map_reverse(map);
11972 	in = isl_map_is_single_valued(map);
11973 	isl_map_free(map);
11974 
11975 	return in;
11976 }
11977 
11978 /* Check if the given map is obviously injective.
11979  */
isl_map_plain_is_injective(__isl_keep isl_map * map)11980 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11981 {
11982 	isl_bool in;
11983 
11984 	map = isl_map_copy(map);
11985 	map = isl_map_reverse(map);
11986 	in = isl_map_plain_is_single_valued(map);
11987 	isl_map_free(map);
11988 
11989 	return in;
11990 }
11991 
isl_map_is_bijective(__isl_keep isl_map * map)11992 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11993 {
11994 	isl_bool sv;
11995 
11996 	sv = isl_map_is_single_valued(map);
11997 	if (sv < 0 || !sv)
11998 		return sv;
11999 
12000 	return isl_map_is_injective(map);
12001 }
12002 
isl_set_is_singleton(__isl_keep isl_set * set)12003 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
12004 {
12005 	return isl_map_is_single_valued(set_to_map(set));
12006 }
12007 
12008 /* Does "map" only map elements to themselves?
12009  *
12010  * If the domain and range spaces are different, then "map"
12011  * is considered not to be an identity relation, even if it is empty.
12012  * Otherwise, construct the maximal identity relation and
12013  * check whether "map" is a subset of this relation.
12014  */
isl_map_is_identity(__isl_keep isl_map * map)12015 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
12016 {
12017 	isl_map *id;
12018 	isl_bool equal, is_identity;
12019 
12020 	equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
12021 	if (equal < 0 || !equal)
12022 		return equal;
12023 
12024 	id = isl_map_identity(isl_map_get_space(map));
12025 	is_identity = isl_map_is_subset(map, id);
12026 	isl_map_free(id);
12027 
12028 	return is_identity;
12029 }
12030 
isl_map_is_translation(__isl_keep isl_map * map)12031 int isl_map_is_translation(__isl_keep isl_map *map)
12032 {
12033 	int ok;
12034 	isl_set *delta;
12035 
12036 	delta = isl_map_deltas(isl_map_copy(map));
12037 	ok = isl_set_is_singleton(delta);
12038 	isl_set_free(delta);
12039 
12040 	return ok;
12041 }
12042 
unique(isl_int * p,unsigned pos,unsigned len)12043 static int unique(isl_int *p, unsigned pos, unsigned len)
12044 {
12045 	if (isl_seq_first_non_zero(p, pos) != -1)
12046 		return 0;
12047 	if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
12048 		return 0;
12049 	return 1;
12050 }
12051 
isl_basic_set_is_box(__isl_keep isl_basic_set * bset)12052 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
12053 {
12054 	int i, j;
12055 	isl_size nvar, n_div;
12056 	unsigned ovar;
12057 
12058 	n_div = isl_basic_set_dim(bset, isl_dim_div);
12059 	if (n_div < 0)
12060 		return isl_bool_error;
12061 	if (n_div != 0)
12062 		return isl_bool_false;
12063 
12064 	nvar = isl_basic_set_dim(bset, isl_dim_set);
12065 	if (nvar < 0)
12066 		return isl_bool_error;
12067 	ovar = isl_space_offset(bset->dim, isl_dim_set);
12068 	for (j = 0; j < nvar; ++j) {
12069 		int lower = 0, upper = 0;
12070 		for (i = 0; i < bset->n_eq; ++i) {
12071 			if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
12072 				continue;
12073 			if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
12074 				return isl_bool_false;
12075 			break;
12076 		}
12077 		if (i < bset->n_eq)
12078 			continue;
12079 		for (i = 0; i < bset->n_ineq; ++i) {
12080 			if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
12081 				continue;
12082 			if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
12083 				return isl_bool_false;
12084 			if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
12085 				lower = 1;
12086 			else
12087 				upper = 1;
12088 		}
12089 		if (!lower || !upper)
12090 			return isl_bool_false;
12091 	}
12092 
12093 	return isl_bool_true;
12094 }
12095 
isl_set_is_box(__isl_keep isl_set * set)12096 isl_bool isl_set_is_box(__isl_keep isl_set *set)
12097 {
12098 	if (!set)
12099 		return isl_bool_error;
12100 	if (set->n != 1)
12101 		return isl_bool_false;
12102 
12103 	return isl_basic_set_is_box(set->p[0]);
12104 }
12105 
isl_basic_set_is_wrapping(__isl_keep isl_basic_set * bset)12106 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
12107 {
12108 	if (!bset)
12109 		return isl_bool_error;
12110 
12111 	return isl_space_is_wrapping(bset->dim);
12112 }
12113 
isl_set_is_wrapping(__isl_keep isl_set * set)12114 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
12115 {
12116 	if (!set)
12117 		return isl_bool_error;
12118 
12119 	return isl_space_is_wrapping(set->dim);
12120 }
12121 
12122 /* Modify the space of "map" through a call to "change".
12123  * If "can_change" is set (not NULL), then first call it to check
12124  * if the modification is allowed, printing the error message "cannot_change"
12125  * if it is not.
12126  */
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))12127 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
12128 	isl_bool (*can_change)(__isl_keep isl_map *map),
12129 	const char *cannot_change,
12130 	__isl_give isl_space *(*change)(__isl_take isl_space *space))
12131 {
12132 	isl_bool ok;
12133 	isl_space *space;
12134 
12135 	if (!map)
12136 		return NULL;
12137 
12138 	ok = can_change ? can_change(map) : isl_bool_true;
12139 	if (ok < 0)
12140 		return isl_map_free(map);
12141 	if (!ok)
12142 		isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
12143 			return isl_map_free(map));
12144 
12145 	space = change(isl_map_get_space(map));
12146 	map = isl_map_reset_space(map, space);
12147 
12148 	return map;
12149 }
12150 
12151 /* Is the domain of "map" a wrapped relation?
12152  */
isl_map_domain_is_wrapping(__isl_keep isl_map * map)12153 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
12154 {
12155 	if (!map)
12156 		return isl_bool_error;
12157 
12158 	return isl_space_domain_is_wrapping(map->dim);
12159 }
12160 
12161 /* Does "map" have a wrapped relation in both domain and range?
12162  */
isl_map_is_product(__isl_keep isl_map * map)12163 isl_bool isl_map_is_product(__isl_keep isl_map *map)
12164 {
12165 	return isl_space_is_product(isl_map_peek_space(map));
12166 }
12167 
12168 /* Is the range of "map" a wrapped relation?
12169  */
isl_map_range_is_wrapping(__isl_keep isl_map * map)12170 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
12171 {
12172 	if (!map)
12173 		return isl_bool_error;
12174 
12175 	return isl_space_range_is_wrapping(map->dim);
12176 }
12177 
isl_basic_map_wrap(__isl_take isl_basic_map * bmap)12178 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
12179 {
12180 	isl_space *space;
12181 
12182 	space = isl_basic_map_take_space(bmap);
12183 	space = isl_space_wrap(space);
12184 	bmap = isl_basic_map_restore_space(bmap, space);
12185 
12186 	bmap = isl_basic_map_finalize(bmap);
12187 
12188 	return bset_from_bmap(bmap);
12189 }
12190 
12191 /* Given a map A -> B, return the set (A -> B).
12192  */
isl_map_wrap(__isl_take isl_map * map)12193 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
12194 {
12195 	return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
12196 }
12197 
isl_basic_set_unwrap(__isl_take isl_basic_set * bset)12198 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
12199 {
12200 	bset = isl_basic_set_cow(bset);
12201 	if (!bset)
12202 		return NULL;
12203 
12204 	bset->dim = isl_space_unwrap(bset->dim);
12205 	if (!bset->dim)
12206 		goto error;
12207 
12208 	bset = isl_basic_set_finalize(bset);
12209 
12210 	return bset_to_bmap(bset);
12211 error:
12212 	isl_basic_set_free(bset);
12213 	return NULL;
12214 }
12215 
12216 /* Given a set (A -> B), return the map A -> B.
12217  * Error out if "set" is not of the form (A -> B).
12218  */
isl_set_unwrap(__isl_take isl_set * set)12219 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
12220 {
12221 	return isl_map_change_space(set, &isl_set_is_wrapping,
12222 				    "not a wrapping set", &isl_space_unwrap);
12223 }
12224 
isl_basic_map_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)12225 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
12226 	enum isl_dim_type type)
12227 {
12228 	isl_space *space;
12229 
12230 	space = isl_basic_map_take_space(bmap);
12231 	space = isl_space_reset(space, type);
12232 	bmap = isl_basic_map_restore_space(bmap, space);
12233 
12234 	bmap = isl_basic_map_mark_final(bmap);
12235 
12236 	return bmap;
12237 }
12238 
isl_map_reset(__isl_take isl_map * map,enum isl_dim_type type)12239 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
12240 	enum isl_dim_type type)
12241 {
12242 	int i;
12243 	isl_space *space;
12244 
12245 	if (!map)
12246 		return NULL;
12247 
12248 	if (!isl_space_is_named_or_nested(map->dim, type))
12249 		return map;
12250 
12251 	map = isl_map_cow(map);
12252 	if (!map)
12253 		return NULL;
12254 
12255 	for (i = 0; i < map->n; ++i) {
12256 		map->p[i] = isl_basic_map_reset(map->p[i], type);
12257 		if (!map->p[i])
12258 			goto error;
12259 	}
12260 
12261 	space = isl_map_take_space(map);
12262 	space = isl_space_reset(space, type);
12263 	map = isl_map_restore_space(map, space);
12264 
12265 	return map;
12266 error:
12267 	isl_map_free(map);
12268 	return NULL;
12269 }
12270 
isl_basic_map_flatten(__isl_take isl_basic_map * bmap)12271 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
12272 {
12273 	isl_space *space;
12274 
12275 	space = isl_basic_map_take_space(bmap);
12276 	space = isl_space_flatten(space);
12277 	bmap = isl_basic_map_restore_space(bmap, space);
12278 
12279 	bmap = isl_basic_map_mark_final(bmap);
12280 
12281 	return bmap;
12282 }
12283 
isl_basic_set_flatten(__isl_take isl_basic_set * bset)12284 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
12285 {
12286 	return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
12287 }
12288 
isl_basic_map_flatten_domain(__isl_take isl_basic_map * bmap)12289 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
12290 	__isl_take isl_basic_map *bmap)
12291 {
12292 	isl_space *space;
12293 
12294 	space = isl_basic_map_take_space(bmap);
12295 	space = isl_space_flatten_domain(space);
12296 	bmap = isl_basic_map_restore_space(bmap, space);
12297 
12298 	bmap = isl_basic_map_mark_final(bmap);
12299 
12300 	return bmap;
12301 }
12302 
isl_basic_map_flatten_range(__isl_take isl_basic_map * bmap)12303 __isl_give isl_basic_map *isl_basic_map_flatten_range(
12304 	__isl_take isl_basic_map *bmap)
12305 {
12306 	isl_space *space;
12307 
12308 	space = isl_basic_map_take_space(bmap);
12309 	space = isl_space_flatten_range(space);
12310 	bmap = isl_basic_map_restore_space(bmap, space);
12311 
12312 	bmap = isl_basic_map_mark_final(bmap);
12313 
12314 	return bmap;
12315 }
12316 
12317 /* Remove any internal structure from the spaces of domain and range of "map".
12318  */
isl_map_flatten(__isl_take isl_map * map)12319 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
12320 {
12321 	if (!map)
12322 		return NULL;
12323 
12324 	if (!map->dim->nested[0] && !map->dim->nested[1])
12325 		return map;
12326 
12327 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
12328 }
12329 
isl_set_flatten(__isl_take isl_set * set)12330 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
12331 {
12332 	return set_from_map(isl_map_flatten(set_to_map(set)));
12333 }
12334 
isl_set_flatten_map(__isl_take isl_set * set)12335 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
12336 {
12337 	isl_space *space, *flat_space;
12338 	isl_map *map;
12339 
12340 	space = isl_set_get_space(set);
12341 	flat_space = isl_space_flatten(isl_space_copy(space));
12342 	map = isl_map_identity(isl_space_join(isl_space_reverse(space),
12343 						flat_space));
12344 	map = isl_map_intersect_domain(map, set);
12345 
12346 	return map;
12347 }
12348 
12349 /* Remove any internal structure from the space of the domain of "map".
12350  */
isl_map_flatten_domain(__isl_take isl_map * map)12351 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
12352 {
12353 	if (!map)
12354 		return NULL;
12355 
12356 	if (!map->dim->nested[0])
12357 		return map;
12358 
12359 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
12360 }
12361 
12362 /* Remove any internal structure from the space of the range of "map".
12363  */
isl_map_flatten_range(__isl_take isl_map * map)12364 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
12365 {
12366 	if (!map)
12367 		return NULL;
12368 
12369 	if (!map->dim->nested[1])
12370 		return map;
12371 
12372 	return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
12373 }
12374 
12375 /* Reorder the dimensions of "bmap" according to the given dim_map
12376  * and set the dimension specification to "space" and
12377  * perform Gaussian elimination on the result.
12378  */
isl_basic_map_realign(__isl_take isl_basic_map * bmap,__isl_take isl_space * space,__isl_take struct isl_dim_map * dim_map)12379 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
12380 	__isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
12381 {
12382 	isl_basic_map *res;
12383 	unsigned flags;
12384 	isl_size n_div;
12385 
12386 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
12387 	if (n_div < 0 || !space || !dim_map)
12388 		goto error;
12389 
12390 	flags = bmap->flags;
12391 	ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
12392 	ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
12393 	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
12394 	res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
12395 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
12396 	if (res)
12397 		res->flags = flags;
12398 	res = isl_basic_map_gauss(res, NULL);
12399 	res = isl_basic_map_finalize(res);
12400 	return res;
12401 error:
12402 	isl_dim_map_free(dim_map);
12403 	isl_basic_map_free(bmap);
12404 	isl_space_free(space);
12405 	return NULL;
12406 }
12407 
12408 /* Reorder the dimensions of "map" according to given reordering.
12409  */
isl_map_realign(__isl_take isl_map * map,__isl_take isl_reordering * r)12410 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
12411 	__isl_take isl_reordering *r)
12412 {
12413 	int i;
12414 	struct isl_dim_map *dim_map;
12415 
12416 	map = isl_map_cow(map);
12417 	dim_map = isl_dim_map_from_reordering(r);
12418 	if (!map || !r || !dim_map)
12419 		goto error;
12420 
12421 	for (i = 0; i < map->n; ++i) {
12422 		struct isl_dim_map *dim_map_i;
12423 		isl_space *space;
12424 
12425 		dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
12426 
12427 		space = isl_reordering_get_space(r);
12428 		map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
12429 
12430 		if (!map->p[i])
12431 			goto error;
12432 	}
12433 
12434 	map = isl_map_reset_space(map, isl_reordering_get_space(r));
12435 	map = isl_map_unmark_normalized(map);
12436 
12437 	isl_reordering_free(r);
12438 	isl_dim_map_free(dim_map);
12439 	return map;
12440 error:
12441 	isl_dim_map_free(dim_map);
12442 	isl_map_free(map);
12443 	isl_reordering_free(r);
12444 	return NULL;
12445 }
12446 
isl_set_realign(__isl_take isl_set * set,__isl_take isl_reordering * r)12447 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
12448 	__isl_take isl_reordering *r)
12449 {
12450 	return set_from_map(isl_map_realign(set_to_map(set), r));
12451 }
12452 
isl_map_align_params(__isl_take isl_map * map,__isl_take isl_space * model)12453 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
12454 	__isl_take isl_space *model)
12455 {
12456 	isl_ctx *ctx;
12457 	isl_bool aligned;
12458 
12459 	if (!map || !model)
12460 		goto error;
12461 
12462 	ctx = isl_space_get_ctx(model);
12463 	if (!isl_space_has_named_params(model))
12464 		isl_die(ctx, isl_error_invalid,
12465 			"model has unnamed parameters", goto error);
12466 	if (isl_map_check_named_params(map) < 0)
12467 		goto error;
12468 	aligned = isl_map_space_has_equal_params(map, model);
12469 	if (aligned < 0)
12470 		goto error;
12471 	if (!aligned) {
12472 		isl_reordering *exp;
12473 
12474 		exp = isl_parameter_alignment_reordering(map->dim, model);
12475 		exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
12476 		map = isl_map_realign(map, exp);
12477 	}
12478 
12479 	isl_space_free(model);
12480 	return map;
12481 error:
12482 	isl_space_free(model);
12483 	isl_map_free(map);
12484 	return NULL;
12485 }
12486 
isl_set_align_params(__isl_take isl_set * set,__isl_take isl_space * model)12487 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
12488 	__isl_take isl_space *model)
12489 {
12490 	return isl_map_align_params(set, model);
12491 }
12492 
12493 /* Align the parameters of "bmap" to those of "model", introducing
12494  * additional parameters if needed.
12495  */
isl_basic_map_align_params(__isl_take isl_basic_map * bmap,__isl_take isl_space * model)12496 __isl_give isl_basic_map *isl_basic_map_align_params(
12497 	__isl_take isl_basic_map *bmap, __isl_take isl_space *model)
12498 {
12499 	isl_ctx *ctx;
12500 	isl_bool equal_params;
12501 
12502 	if (!bmap || !model)
12503 		goto error;
12504 
12505 	ctx = isl_space_get_ctx(model);
12506 	if (!isl_space_has_named_params(model))
12507 		isl_die(ctx, isl_error_invalid,
12508 			"model has unnamed parameters", goto error);
12509 	if (isl_basic_map_check_named_params(bmap) < 0)
12510 		goto error;
12511 	equal_params = isl_space_has_equal_params(bmap->dim, model);
12512 	if (equal_params < 0)
12513 		goto error;
12514 	if (!equal_params) {
12515 		isl_reordering *exp;
12516 		struct isl_dim_map *dim_map;
12517 
12518 		exp = isl_parameter_alignment_reordering(bmap->dim, model);
12519 		exp = isl_reordering_extend_space(exp,
12520 					isl_basic_map_get_space(bmap));
12521 		dim_map = isl_dim_map_from_reordering(exp);
12522 		bmap = isl_basic_map_realign(bmap,
12523 				    isl_reordering_get_space(exp),
12524 				    isl_dim_map_extend(dim_map, bmap));
12525 		isl_reordering_free(exp);
12526 		isl_dim_map_free(dim_map);
12527 	}
12528 
12529 	isl_space_free(model);
12530 	return bmap;
12531 error:
12532 	isl_space_free(model);
12533 	isl_basic_map_free(bmap);
12534 	return NULL;
12535 }
12536 
12537 /* Do "bset" and "space" have the same parameters?
12538  */
isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set * bset,__isl_keep isl_space * space)12539 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
12540 	__isl_keep isl_space *space)
12541 {
12542 	isl_space *bset_space;
12543 
12544 	bset_space = isl_basic_set_peek_space(bset);
12545 	return isl_space_has_equal_params(bset_space, space);
12546 }
12547 
12548 /* Do "map" and "space" have the same parameters?
12549  */
isl_map_space_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_space * space)12550 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
12551 	__isl_keep isl_space *space)
12552 {
12553 	isl_space *map_space;
12554 
12555 	map_space = isl_map_peek_space(map);
12556 	return isl_space_has_equal_params(map_space, space);
12557 }
12558 
12559 /* Do "set" and "space" have the same parameters?
12560  */
isl_set_space_has_equal_params(__isl_keep isl_set * set,__isl_keep isl_space * space)12561 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
12562 	__isl_keep isl_space *space)
12563 {
12564 	return isl_map_space_has_equal_params(set_to_map(set), space);
12565 }
12566 
12567 /* Align the parameters of "bset" to those of "model", introducing
12568  * additional parameters if needed.
12569  */
isl_basic_set_align_params(__isl_take isl_basic_set * bset,__isl_take isl_space * model)12570 __isl_give isl_basic_set *isl_basic_set_align_params(
12571 	__isl_take isl_basic_set *bset, __isl_take isl_space *model)
12572 {
12573 	return isl_basic_map_align_params(bset, model);
12574 }
12575 
12576 /* Drop all parameters not referenced by "map".
12577  */
isl_map_drop_unused_params(__isl_take isl_map * map)12578 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
12579 {
12580 	int i;
12581 	isl_size n;
12582 
12583 	n = isl_map_dim(map, isl_dim_param);
12584 	if (isl_map_check_named_params(map) < 0 || n < 0)
12585 		return isl_map_free(map);
12586 
12587 	for (i = n - 1; i >= 0; i--) {
12588 		isl_bool involves;
12589 
12590 		involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
12591 		if (involves < 0)
12592 			return isl_map_free(map);
12593 		if (!involves)
12594 			map = isl_map_project_out(map, isl_dim_param, i, 1);
12595 	}
12596 
12597 	return map;
12598 }
12599 
12600 /* Drop all parameters not referenced by "set".
12601  */
isl_set_drop_unused_params(__isl_take isl_set * set)12602 __isl_give isl_set *isl_set_drop_unused_params(
12603 	__isl_take isl_set *set)
12604 {
12605 	return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
12606 }
12607 
12608 /* Drop all parameters not referenced by "bmap".
12609  */
isl_basic_map_drop_unused_params(__isl_take isl_basic_map * bmap)12610 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
12611 	__isl_take isl_basic_map *bmap)
12612 {
12613 	isl_size nparam;
12614 	int i;
12615 
12616 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
12617 	if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)
12618 		return isl_basic_map_free(bmap);
12619 
12620 	for (i = nparam - 1; i >= 0; i--) {
12621 		isl_bool involves;
12622 
12623 		involves = isl_basic_map_involves_dims(bmap,
12624 							isl_dim_param, i, 1);
12625 		if (involves < 0)
12626 			return isl_basic_map_free(bmap);
12627 		if (!involves)
12628 			bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
12629 	}
12630 
12631 	return bmap;
12632 }
12633 
12634 /* Drop all parameters not referenced by "bset".
12635  */
isl_basic_set_drop_unused_params(__isl_take isl_basic_set * bset)12636 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
12637 	__isl_take isl_basic_set *bset)
12638 {
12639 	return bset_from_bmap(isl_basic_map_drop_unused_params(
12640 							bset_to_bmap(bset)));
12641 }
12642 
12643 /* Given a tuple of identifiers "tuple" in a space that corresponds
12644  * to that of "set", if any of those identifiers appear as parameters
12645  * in "set", then equate those parameters with the corresponding
12646  * set dimensions and project out the parameters.
12647  * The result therefore has no such parameters.
12648  */
equate_params(__isl_take isl_set * set,__isl_keep isl_multi_id * tuple)12649 static __isl_give isl_set *equate_params(__isl_take isl_set *set,
12650 	__isl_keep isl_multi_id *tuple)
12651 {
12652 	int i;
12653 	isl_size n;
12654 	isl_space *set_space, *tuple_space;
12655 
12656 	set_space = isl_set_peek_space(set);
12657 	tuple_space = isl_multi_id_peek_space(tuple);
12658 	if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
12659 		return isl_set_free(set);
12660 	n = isl_multi_id_size(tuple);
12661 	if (n < 0)
12662 		return isl_set_free(set);
12663 	for (i = 0; i < n; ++i) {
12664 		isl_id *id;
12665 		int pos;
12666 
12667 		id = isl_multi_id_get_at(tuple, i);
12668 		if (!id)
12669 			return isl_set_free(set);
12670 		pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
12671 		isl_id_free(id);
12672 		if (pos < 0)
12673 			continue;
12674 		set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
12675 		set = isl_set_project_out(set, isl_dim_param, pos, 1);
12676 	}
12677 	return set;
12678 }
12679 
12680 /* Bind the set dimensions of "set" to parameters with identifiers
12681  * specified by "tuple", living in the same space as "set".
12682  *
12683  * If no parameters with these identifiers appear in "set" already,
12684  * then the set dimensions are simply reinterpreted as parameters.
12685  * Otherwise, the parameters are first equated to the corresponding
12686  * set dimensions.
12687  */
isl_set_bind(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12688 __isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
12689 	__isl_take isl_multi_id *tuple)
12690 {
12691 	isl_space *space;
12692 
12693 	set = equate_params(set, tuple);
12694 	space = isl_set_get_space(set);
12695 	space = isl_space_bind_set(space, tuple);
12696 	isl_multi_id_free(tuple);
12697 	set = isl_set_reset_space(set, space);
12698 
12699 	return set;
12700 }
12701 
12702 /* Given a tuple of identifiers "tuple" in a space that corresponds
12703  * to the domain of "map", if any of those identifiers appear as parameters
12704  * in "map", then equate those parameters with the corresponding
12705  * input dimensions and project out the parameters.
12706  * The result therefore has no such parameters.
12707  */
map_equate_params(__isl_take isl_map * map,__isl_keep isl_multi_id * tuple)12708 static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
12709 	__isl_keep isl_multi_id *tuple)
12710 {
12711 	int i;
12712 	isl_size n;
12713 	isl_space *map_space, *tuple_space;
12714 
12715 	map_space = isl_map_peek_space(map);
12716 	tuple_space = isl_multi_id_peek_space(tuple);
12717 	if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
12718 		return isl_map_free(map);
12719 	n = isl_multi_id_size(tuple);
12720 	if (n < 0)
12721 		return isl_map_free(map);
12722 	for (i = 0; i < n; ++i) {
12723 		isl_id *id;
12724 		int pos;
12725 
12726 		id = isl_multi_id_get_at(tuple, i);
12727 		if (!id)
12728 			return isl_map_free(map);
12729 		pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
12730 		isl_id_free(id);
12731 		if (pos < 0)
12732 			continue;
12733 		map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
12734 		map = isl_map_project_out(map, isl_dim_param, pos, 1);
12735 	}
12736 	return map;
12737 }
12738 
12739 /* Bind the input dimensions of "map" to parameters with identifiers
12740  * specified by "tuple", living in the domain space of "map".
12741  *
12742  * If no parameters with these identifiers appear in "map" already,
12743  * then the input dimensions are simply reinterpreted as parameters.
12744  * Otherwise, the parameters are first equated to the corresponding
12745  * input dimensions.
12746  */
isl_map_bind_domain(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12747 __isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
12748 	__isl_take isl_multi_id *tuple)
12749 {
12750 	isl_space *space;
12751 	isl_set *set;
12752 
12753 	map = map_equate_params(map, tuple);
12754 	space = isl_map_get_space(map);
12755 	space = isl_space_bind_map_domain(space, tuple);
12756 	isl_multi_id_free(tuple);
12757 	set = set_from_map(isl_map_reset_space(map, space));
12758 
12759 	return set;
12760 }
12761 
12762 /* Bind the output dimensions of "map" to parameters with identifiers
12763  * specified by "tuple", living in the range space of "map".
12764  *
12765  * Since binding is more easily implemented on the domain,
12766  * bind the input dimensions of the inverse of "map".
12767  */
isl_map_bind_range(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12768 __isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
12769 	__isl_take isl_multi_id *tuple)
12770 {
12771 	return isl_map_bind_domain(isl_map_reverse(map), tuple);
12772 }
12773 
12774 /* Insert a domain corresponding to "tuple"
12775  * into the nullary or unary relation "set".
12776  * The result has an extra initial tuple and is therefore
12777  * either a unary or binary relation.
12778  * Any parameters with identifiers in "tuple" are reinterpreted
12779  * as the corresponding domain dimensions.
12780  */
unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12781 static __isl_give isl_map *unbind_params_insert_domain(
12782 	__isl_take isl_set *set, __isl_take isl_multi_id *tuple)
12783 {
12784 	isl_space *space;
12785 	isl_reordering *r;
12786 
12787 	space = isl_set_peek_space(set);
12788 	r = isl_reordering_unbind_params_insert_domain(space, tuple);
12789 	isl_multi_id_free(tuple);
12790 
12791 	return isl_map_realign(set_to_map(set), r);
12792 }
12793 
12794 /* Construct a set with "tuple" as domain from the parameter domain "set".
12795  * Any parameters with identifiers in "tuple" are reinterpreted
12796  * as the corresponding set dimensions.
12797  */
isl_set_unbind_params(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12798 __isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
12799 	__isl_take isl_multi_id *tuple)
12800 {
12801 	isl_bool is_params;
12802 
12803 	is_params = isl_set_is_params(set);
12804 	if (is_params < 0)
12805 		set = isl_set_free(set);
12806 	else if (!is_params)
12807 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
12808 			"expecting parameter domain", set = isl_set_free(set));
12809 	return set_from_map(unbind_params_insert_domain(set, tuple));
12810 }
12811 
12812 /* Check that "set" is a proper set, i.e., that it is not a parameter domain.
12813  */
isl_set_check_is_set(__isl_keep isl_set * set)12814 static isl_stat isl_set_check_is_set(__isl_keep isl_set *set)
12815 {
12816 	isl_bool is_params;
12817 
12818 	is_params = isl_set_is_params(set);
12819 	if (is_params < 0)
12820 		return isl_stat_error;
12821 	else if (is_params)
12822 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
12823 			"expecting proper set", return isl_stat_error);
12824 
12825 	return isl_stat_ok;
12826 }
12827 
12828 /* Construct a map with "domain" as domain and "set" as range.
12829  * Any parameters with identifiers in "domain" are reinterpreted
12830  * as the corresponding domain dimensions.
12831  */
isl_set_unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * domain)12832 __isl_give isl_map *isl_set_unbind_params_insert_domain(
12833 	__isl_take isl_set *set, __isl_take isl_multi_id *domain)
12834 {
12835 	if (isl_set_check_is_set(set) < 0)
12836 		set = isl_set_free(set);
12837 	return unbind_params_insert_domain(set, domain);
12838 }
12839 
12840 /* Construct a map with "domain" as domain and "set" as range.
12841  */
isl_set_insert_domain(__isl_take isl_set * set,__isl_take isl_space * domain)12842 __isl_give isl_map *isl_set_insert_domain(__isl_take isl_set *set,
12843 	__isl_take isl_space *domain)
12844 {
12845 	isl_size dim;
12846 	isl_space *space;
12847 	isl_map *map;
12848 
12849 	if (isl_set_check_is_set(set) < 0 || isl_space_check_is_set(domain) < 0)
12850 		domain = isl_space_free(domain);
12851 	dim = isl_space_dim(domain, isl_dim_set);
12852 	if (dim < 0)
12853 		domain = isl_space_free(domain);
12854 	space = isl_set_get_space(set);
12855 	domain = isl_space_replace_params(domain, space);
12856 	space = isl_space_map_from_domain_and_range(domain, space);
12857 
12858 	map = isl_map_from_range(set);
12859 	map = isl_map_add_dims(map, isl_dim_in, dim);
12860 	map = isl_map_reset_space(map, space);
12861 
12862 	return map;
12863 }
12864 
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)12865 __isl_give isl_mat *isl_basic_map_equalities_matrix(
12866 		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12867 		enum isl_dim_type c2, enum isl_dim_type c3,
12868 		enum isl_dim_type c4, enum isl_dim_type c5)
12869 {
12870 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12871 	struct isl_mat *mat;
12872 	int i, j, k;
12873 	int pos;
12874 	isl_size total;
12875 
12876 	total = isl_basic_map_dim(bmap, isl_dim_all);
12877 	if (total < 0)
12878 		return NULL;
12879 	mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
12880 	if (!mat)
12881 		return NULL;
12882 	for (i = 0; i < bmap->n_eq; ++i)
12883 		for (j = 0, pos = 0; j < 5; ++j) {
12884 			int off = isl_basic_map_offset(bmap, c[j]);
12885 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12886 			if (dim < 0)
12887 				return isl_mat_free(mat);
12888 			for (k = 0; k < dim; ++k) {
12889 				isl_int_set(mat->row[i][pos],
12890 					    bmap->eq[i][off + k]);
12891 				++pos;
12892 			}
12893 		}
12894 
12895 	return mat;
12896 }
12897 
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)12898 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
12899 		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12900 		enum isl_dim_type c2, enum isl_dim_type c3,
12901 		enum isl_dim_type c4, enum isl_dim_type c5)
12902 {
12903 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12904 	struct isl_mat *mat;
12905 	int i, j, k;
12906 	int pos;
12907 	isl_size total;
12908 
12909 	total = isl_basic_map_dim(bmap, isl_dim_all);
12910 	if (total < 0)
12911 		return NULL;
12912 	mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
12913 	if (!mat)
12914 		return NULL;
12915 	for (i = 0; i < bmap->n_ineq; ++i)
12916 		for (j = 0, pos = 0; j < 5; ++j) {
12917 			int off = isl_basic_map_offset(bmap, c[j]);
12918 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12919 			if (dim < 0)
12920 				return isl_mat_free(mat);
12921 			for (k = 0; k < dim; ++k) {
12922 				isl_int_set(mat->row[i][pos],
12923 					    bmap->ineq[i][off + k]);
12924 				++pos;
12925 			}
12926 		}
12927 
12928 	return mat;
12929 }
12930 
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)12931 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
12932 	__isl_take isl_space *space,
12933 	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12934 	enum isl_dim_type c2, enum isl_dim_type c3,
12935 	enum isl_dim_type c4, enum isl_dim_type c5)
12936 {
12937 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12938 	isl_basic_map *bmap = NULL;
12939 	isl_size dim;
12940 	unsigned total;
12941 	unsigned extra;
12942 	int i, j, k, l;
12943 	int pos;
12944 
12945 	dim = isl_space_dim(space, isl_dim_all);
12946 	if (dim < 0 || !eq || !ineq)
12947 		goto error;
12948 
12949 	if (eq->n_col != ineq->n_col)
12950 		isl_die(space->ctx, isl_error_invalid,
12951 			"equalities and inequalities matrices should have "
12952 			"same number of columns", goto error);
12953 
12954 	total = 1 + dim;
12955 
12956 	if (eq->n_col < total)
12957 		isl_die(space->ctx, isl_error_invalid,
12958 			"number of columns too small", goto error);
12959 
12960 	extra = eq->n_col - total;
12961 
12962 	bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
12963 				       eq->n_row, ineq->n_row);
12964 	if (!bmap)
12965 		goto error;
12966 	for (i = 0; i < extra; ++i) {
12967 		k = isl_basic_map_alloc_div(bmap);
12968 		if (k < 0)
12969 			goto error;
12970 		isl_int_set_si(bmap->div[k][0], 0);
12971 	}
12972 	for (i = 0; i < eq->n_row; ++i) {
12973 		l = isl_basic_map_alloc_equality(bmap);
12974 		if (l < 0)
12975 			goto error;
12976 		for (j = 0, pos = 0; j < 5; ++j) {
12977 			int off = isl_basic_map_offset(bmap, c[j]);
12978 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12979 			if (dim < 0)
12980 				goto error;
12981 			for (k = 0; k < dim; ++k) {
12982 				isl_int_set(bmap->eq[l][off + k],
12983 					    eq->row[i][pos]);
12984 				++pos;
12985 			}
12986 		}
12987 	}
12988 	for (i = 0; i < ineq->n_row; ++i) {
12989 		l = isl_basic_map_alloc_inequality(bmap);
12990 		if (l < 0)
12991 			goto error;
12992 		for (j = 0, pos = 0; j < 5; ++j) {
12993 			int off = isl_basic_map_offset(bmap, c[j]);
12994 			isl_size dim = isl_basic_map_dim(bmap, c[j]);
12995 			if (dim < 0)
12996 				goto error;
12997 			for (k = 0; k < dim; ++k) {
12998 				isl_int_set(bmap->ineq[l][off + k],
12999 					    ineq->row[i][pos]);
13000 				++pos;
13001 			}
13002 		}
13003 	}
13004 
13005 	isl_space_free(space);
13006 	isl_mat_free(eq);
13007 	isl_mat_free(ineq);
13008 
13009 	bmap = isl_basic_map_simplify(bmap);
13010 	return isl_basic_map_finalize(bmap);
13011 error:
13012 	isl_space_free(space);
13013 	isl_mat_free(eq);
13014 	isl_mat_free(ineq);
13015 	isl_basic_map_free(bmap);
13016 	return NULL;
13017 }
13018 
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)13019 __isl_give isl_mat *isl_basic_set_equalities_matrix(
13020 	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
13021 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
13022 {
13023 	return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
13024 						c1, c2, c3, c4, isl_dim_in);
13025 }
13026 
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)13027 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
13028 	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
13029 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
13030 {
13031 	return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
13032 						 c1, c2, c3, c4, isl_dim_in);
13033 }
13034 
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)13035 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
13036 	__isl_take isl_space *space,
13037 	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
13038 	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
13039 {
13040 	isl_basic_map *bmap;
13041 	bmap = isl_basic_map_from_constraint_matrices(space, eq, ineq,
13042 						   c1, c2, c3, c4, isl_dim_in);
13043 	return bset_from_bmap(bmap);
13044 }
13045 
isl_basic_map_can_zip(__isl_keep isl_basic_map * bmap)13046 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
13047 {
13048 	if (!bmap)
13049 		return isl_bool_error;
13050 
13051 	return isl_space_can_zip(bmap->dim);
13052 }
13053 
isl_map_can_zip(__isl_keep isl_map * map)13054 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
13055 {
13056 	if (!map)
13057 		return isl_bool_error;
13058 
13059 	return isl_space_can_zip(map->dim);
13060 }
13061 
13062 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
13063  * (A -> C) -> (B -> D).
13064  */
isl_basic_map_zip(__isl_take isl_basic_map * bmap)13065 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
13066 {
13067 	unsigned pos;
13068 	isl_size n_in;
13069 	isl_size n1;
13070 	isl_size n2;
13071 
13072 	if (!bmap)
13073 		return NULL;
13074 
13075 	if (!isl_basic_map_can_zip(bmap))
13076 		isl_die(bmap->ctx, isl_error_invalid,
13077 			"basic map cannot be zipped", goto error);
13078 	n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
13079 	n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
13080 	n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
13081 	if (n_in < 0 || n1 < 0 || n2 < 0)
13082 		return isl_basic_map_free(bmap);
13083 	pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
13084 	bmap = isl_basic_map_cow(bmap);
13085 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
13086 	if (!bmap)
13087 		return NULL;
13088 	bmap->dim = isl_space_zip(bmap->dim);
13089 	if (!bmap->dim)
13090 		goto error;
13091 	bmap = isl_basic_map_mark_final(bmap);
13092 	return bmap;
13093 error:
13094 	isl_basic_map_free(bmap);
13095 	return NULL;
13096 }
13097 
13098 /* Given a map (A -> B) -> (C -> D), return the corresponding map
13099  * (A -> C) -> (B -> D).
13100  */
isl_map_zip(__isl_take isl_map * map)13101 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
13102 {
13103 	if (!map)
13104 		return NULL;
13105 
13106 	if (!isl_map_can_zip(map))
13107 		isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
13108 			goto error);
13109 
13110 	return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);
13111 error:
13112 	isl_map_free(map);
13113 	return NULL;
13114 }
13115 
13116 /* Can we apply isl_basic_map_curry to "bmap"?
13117  * That is, does it have a nested relation in its domain?
13118  */
isl_basic_map_can_curry(__isl_keep isl_basic_map * bmap)13119 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
13120 {
13121 	if (!bmap)
13122 		return isl_bool_error;
13123 
13124 	return isl_space_can_curry(bmap->dim);
13125 }
13126 
13127 /* Can we apply isl_map_curry to "map"?
13128  * That is, does it have a nested relation in its domain?
13129  */
isl_map_can_curry(__isl_keep isl_map * map)13130 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
13131 {
13132 	if (!map)
13133 		return isl_bool_error;
13134 
13135 	return isl_space_can_curry(map->dim);
13136 }
13137 
13138 /* Given a basic map (A -> B) -> C, return the corresponding basic map
13139  * A -> (B -> C).
13140  */
isl_basic_map_curry(__isl_take isl_basic_map * bmap)13141 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
13142 {
13143 
13144 	if (!bmap)
13145 		return NULL;
13146 
13147 	if (!isl_basic_map_can_curry(bmap))
13148 		isl_die(bmap->ctx, isl_error_invalid,
13149 			"basic map cannot be curried", goto error);
13150 	bmap = isl_basic_map_cow(bmap);
13151 	if (!bmap)
13152 		return NULL;
13153 	bmap->dim = isl_space_curry(bmap->dim);
13154 	if (!bmap->dim)
13155 		goto error;
13156 	bmap = isl_basic_map_mark_final(bmap);
13157 	return bmap;
13158 error:
13159 	isl_basic_map_free(bmap);
13160 	return NULL;
13161 }
13162 
13163 /* Given a map (A -> B) -> C, return the corresponding map
13164  * A -> (B -> C).
13165  */
isl_map_curry(__isl_take isl_map * map)13166 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
13167 {
13168 	return isl_map_change_space(map, &isl_map_can_curry,
13169 				    "map cannot be curried", &isl_space_curry);
13170 }
13171 
13172 /* Can isl_map_range_curry be applied to "map"?
13173  * That is, does it have a nested relation in its range,
13174  * the domain of which is itself a nested relation?
13175  */
isl_map_can_range_curry(__isl_keep isl_map * map)13176 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
13177 {
13178 	if (!map)
13179 		return isl_bool_error;
13180 
13181 	return isl_space_can_range_curry(map->dim);
13182 }
13183 
13184 /* Given a map A -> ((B -> C) -> D), return the corresponding map
13185  * A -> (B -> (C -> D)).
13186  */
isl_map_range_curry(__isl_take isl_map * map)13187 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
13188 {
13189 	return isl_map_change_space(map, &isl_map_can_range_curry,
13190 				    "map range cannot be curried",
13191 				    &isl_space_range_curry);
13192 }
13193 
13194 /* Can we apply isl_basic_map_uncurry to "bmap"?
13195  * That is, does it have a nested relation in its domain?
13196  */
isl_basic_map_can_uncurry(__isl_keep isl_basic_map * bmap)13197 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
13198 {
13199 	if (!bmap)
13200 		return isl_bool_error;
13201 
13202 	return isl_space_can_uncurry(bmap->dim);
13203 }
13204 
13205 /* Can we apply isl_map_uncurry to "map"?
13206  * That is, does it have a nested relation in its domain?
13207  */
isl_map_can_uncurry(__isl_keep isl_map * map)13208 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
13209 {
13210 	if (!map)
13211 		return isl_bool_error;
13212 
13213 	return isl_space_can_uncurry(map->dim);
13214 }
13215 
13216 /* Given a basic map A -> (B -> C), return the corresponding basic map
13217  * (A -> B) -> C.
13218  */
isl_basic_map_uncurry(__isl_take isl_basic_map * bmap)13219 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
13220 {
13221 
13222 	if (!bmap)
13223 		return NULL;
13224 
13225 	if (!isl_basic_map_can_uncurry(bmap))
13226 		isl_die(bmap->ctx, isl_error_invalid,
13227 			"basic map cannot be uncurried",
13228 			return isl_basic_map_free(bmap));
13229 	bmap = isl_basic_map_cow(bmap);
13230 	if (!bmap)
13231 		return NULL;
13232 	bmap->dim = isl_space_uncurry(bmap->dim);
13233 	if (!bmap->dim)
13234 		return isl_basic_map_free(bmap);
13235 	bmap = isl_basic_map_mark_final(bmap);
13236 	return bmap;
13237 }
13238 
13239 /* Given a map A -> (B -> C), return the corresponding map
13240  * (A -> B) -> C.
13241  */
isl_map_uncurry(__isl_take isl_map * map)13242 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
13243 {
13244 	return isl_map_change_space(map, &isl_map_can_uncurry,
13245 				"map cannot be uncurried", &isl_space_uncurry);
13246 }
13247 
isl_set_equate(__isl_take isl_set * set,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13248 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
13249 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13250 {
13251 	return isl_map_equate(set, type1, pos1, type2, pos2);
13252 }
13253 
13254 /* Construct a basic map where the given dimensions are equal to each other.
13255  */
equator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13256 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
13257 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13258 {
13259 	isl_basic_map *bmap = NULL;
13260 	int i;
13261 	isl_size total;
13262 
13263 	total = isl_space_dim(space, isl_dim_all);
13264 	if (total < 0 ||
13265 	    isl_space_check_range(space, type1, pos1, 1) < 0 ||
13266 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13267 		goto error;
13268 
13269 	if (type1 == type2 && pos1 == pos2)
13270 		return isl_basic_map_universe(space);
13271 
13272 	bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
13273 	i = isl_basic_map_alloc_equality(bmap);
13274 	if (i < 0)
13275 		goto error;
13276 	isl_seq_clr(bmap->eq[i], 1 + total);
13277 	pos1 += isl_basic_map_offset(bmap, type1);
13278 	pos2 += isl_basic_map_offset(bmap, type2);
13279 	isl_int_set_si(bmap->eq[i][pos1], -1);
13280 	isl_int_set_si(bmap->eq[i][pos2], 1);
13281 	bmap = isl_basic_map_finalize(bmap);
13282 	isl_space_free(space);
13283 	return bmap;
13284 error:
13285 	isl_space_free(space);
13286 	isl_basic_map_free(bmap);
13287 	return NULL;
13288 }
13289 
13290 /* Add a constraint imposing that the given two dimensions are equal.
13291  */
isl_basic_map_equate(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13292 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
13293 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13294 {
13295 	isl_basic_map *eq;
13296 
13297 	eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13298 
13299 	bmap = isl_basic_map_intersect(bmap, eq);
13300 
13301 	return bmap;
13302 }
13303 
13304 /* Add a constraint imposing that the given two dimensions are equal.
13305  */
isl_map_equate(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13306 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
13307 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13308 {
13309 	isl_basic_map *bmap;
13310 
13311 	bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
13312 
13313 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13314 
13315 	return map;
13316 }
13317 
13318 /* Add a constraint imposing that the given two dimensions have opposite values.
13319  */
isl_map_oppose(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13320 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
13321 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13322 {
13323 	isl_basic_map *bmap = NULL;
13324 	int i;
13325 	isl_size total;
13326 
13327 	if (isl_map_check_range(map, type1, pos1, 1) < 0)
13328 		return isl_map_free(map);
13329 	if (isl_map_check_range(map, type2, pos2, 1) < 0)
13330 		return isl_map_free(map);
13331 
13332 	total = isl_map_dim(map, isl_dim_all);
13333 	if (total < 0)
13334 		return isl_map_free(map);
13335 	bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
13336 	i = isl_basic_map_alloc_equality(bmap);
13337 	if (i < 0)
13338 		goto error;
13339 	isl_seq_clr(bmap->eq[i], 1 + total);
13340 	pos1 += isl_basic_map_offset(bmap, type1);
13341 	pos2 += isl_basic_map_offset(bmap, type2);
13342 	isl_int_set_si(bmap->eq[i][pos1], 1);
13343 	isl_int_set_si(bmap->eq[i][pos2], 1);
13344 	bmap = isl_basic_map_finalize(bmap);
13345 
13346 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13347 
13348 	return map;
13349 error:
13350 	isl_basic_map_free(bmap);
13351 	isl_map_free(map);
13352 	return NULL;
13353 }
13354 
13355 /* Construct a constraint imposing that the value of the first dimension is
13356  * greater than or equal to that of the second.
13357  */
constraint_order_ge(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13358 static __isl_give isl_constraint *constraint_order_ge(
13359 	__isl_take isl_space *space, enum isl_dim_type type1, int pos1,
13360 	enum isl_dim_type type2, int pos2)
13361 {
13362 	isl_constraint *c;
13363 
13364 	if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13365 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13366 		space = isl_space_free(space);
13367 	if (!space)
13368 		return NULL;
13369 
13370 	c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
13371 
13372 	if (type1 == type2 && pos1 == pos2)
13373 		return c;
13374 
13375 	c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
13376 	c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
13377 
13378 	return c;
13379 }
13380 
13381 /* Add a constraint imposing that the value of the first dimension is
13382  * greater than or equal to that of the second.
13383  */
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)13384 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
13385 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13386 {
13387 	isl_constraint *c;
13388 	isl_space *space;
13389 
13390 	if (type1 == type2 && pos1 == pos2)
13391 		return bmap;
13392 	space = isl_basic_map_get_space(bmap);
13393 	c = constraint_order_ge(space, type1, pos1, type2, pos2);
13394 	bmap = isl_basic_map_add_constraint(bmap, c);
13395 
13396 	return bmap;
13397 }
13398 
13399 /* Add a constraint imposing that the value of the first dimension is
13400  * greater than or equal to that of the second.
13401  */
isl_map_order_ge(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13402 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
13403 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13404 {
13405 	isl_constraint *c;
13406 	isl_space *space;
13407 
13408 	if (type1 == type2 && pos1 == pos2)
13409 		return map;
13410 	space = isl_map_get_space(map);
13411 	c = constraint_order_ge(space, type1, pos1, type2, pos2);
13412 	map = isl_map_add_constraint(map, c);
13413 
13414 	return map;
13415 }
13416 
13417 /* Add a constraint imposing that the value of the first dimension is
13418  * less than or equal to that of the second.
13419  */
isl_map_order_le(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13420 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
13421 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13422 {
13423 	return isl_map_order_ge(map, type2, pos2, type1, pos1);
13424 }
13425 
13426 /* Construct a basic map where the value of the first dimension is
13427  * greater than that of the second.
13428  */
greator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13429 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
13430 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13431 {
13432 	isl_basic_map *bmap = NULL;
13433 	int i;
13434 	isl_size total;
13435 
13436 	if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13437 	    isl_space_check_range(space, type2, pos2, 1) < 0)
13438 		goto error;
13439 
13440 	if (type1 == type2 && pos1 == pos2)
13441 		return isl_basic_map_empty(space);
13442 
13443 	bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
13444 	total = isl_basic_map_dim(bmap, isl_dim_all);
13445 	i = isl_basic_map_alloc_inequality(bmap);
13446 	if (total < 0 || i < 0)
13447 		return isl_basic_map_free(bmap);
13448 	isl_seq_clr(bmap->ineq[i], 1 + total);
13449 	pos1 += isl_basic_map_offset(bmap, type1);
13450 	pos2 += isl_basic_map_offset(bmap, type2);
13451 	isl_int_set_si(bmap->ineq[i][pos1], 1);
13452 	isl_int_set_si(bmap->ineq[i][pos2], -1);
13453 	isl_int_set_si(bmap->ineq[i][0], -1);
13454 	bmap = isl_basic_map_finalize(bmap);
13455 
13456 	return bmap;
13457 error:
13458 	isl_space_free(space);
13459 	isl_basic_map_free(bmap);
13460 	return NULL;
13461 }
13462 
13463 /* Add a constraint imposing that the value of the first dimension is
13464  * greater than that of the second.
13465  */
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)13466 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
13467 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13468 {
13469 	isl_basic_map *gt;
13470 
13471 	gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13472 
13473 	bmap = isl_basic_map_intersect(bmap, gt);
13474 
13475 	return bmap;
13476 }
13477 
13478 /* Add a constraint imposing that the value of the first dimension is
13479  * greater than that of the second.
13480  */
isl_map_order_gt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13481 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
13482 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13483 {
13484 	isl_basic_map *bmap;
13485 
13486 	bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
13487 
13488 	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13489 
13490 	return map;
13491 }
13492 
13493 /* Add a constraint imposing that the value of the first dimension is
13494  * smaller than that of the second.
13495  */
isl_map_order_lt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13496 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
13497 	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13498 {
13499 	return isl_map_order_gt(map, type2, pos2, type1, pos1);
13500 }
13501 
isl_basic_map_get_div(__isl_keep isl_basic_map * bmap,int pos)13502 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
13503 	int pos)
13504 {
13505 	isl_aff *div;
13506 	isl_local_space *ls;
13507 
13508 	if (!bmap)
13509 		return NULL;
13510 
13511 	if (!isl_basic_map_divs_known(bmap))
13512 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13513 			"some divs are unknown", return NULL);
13514 
13515 	ls = isl_basic_map_get_local_space(bmap);
13516 	div = isl_local_space_get_div(ls, pos);
13517 	isl_local_space_free(ls);
13518 
13519 	return div;
13520 }
13521 
isl_basic_set_get_div(__isl_keep isl_basic_set * bset,int pos)13522 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
13523 	int pos)
13524 {
13525 	return isl_basic_map_get_div(bset, pos);
13526 }
13527 
13528 /* Plug in "subs" for set dimension "pos" of "set".
13529  */
isl_set_substitute(__isl_take isl_set * set,unsigned pos,__isl_keep isl_aff * subs)13530 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
13531 	unsigned pos, __isl_keep isl_aff *subs)
13532 {
13533 	isl_multi_aff *ma;
13534 
13535 	if (set && isl_set_plain_is_empty(set))
13536 		return set;
13537 
13538 	ma = isl_multi_aff_identity_on_domain_space(isl_set_get_space(set));
13539 	ma = isl_multi_aff_set_aff(ma, pos, isl_aff_copy(subs));
13540 	return isl_set_preimage_multi_aff(set, ma);
13541 }
13542 
13543 /* Check if the range of "ma" is compatible with the domain or range
13544  * (depending on "type") of "bmap".
13545  */
check_basic_map_compatible_range_multi_aff(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13546 static isl_stat check_basic_map_compatible_range_multi_aff(
13547 	__isl_keep isl_basic_map *bmap, enum isl_dim_type type,
13548 	__isl_keep isl_multi_aff *ma)
13549 {
13550 	isl_bool m;
13551 	isl_space *ma_space;
13552 
13553 	ma_space = isl_multi_aff_get_space(ma);
13554 
13555 	m = isl_space_has_equal_params(bmap->dim, ma_space);
13556 	if (m < 0)
13557 		goto error;
13558 	if (!m)
13559 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13560 			"parameters don't match", goto error);
13561 	m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
13562 	if (m < 0)
13563 		goto error;
13564 	if (!m)
13565 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13566 			"spaces don't match", goto error);
13567 
13568 	isl_space_free(ma_space);
13569 	return isl_stat_ok;
13570 error:
13571 	isl_space_free(ma_space);
13572 	return isl_stat_error;
13573 }
13574 
13575 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
13576  * coefficients before the transformed range of dimensions,
13577  * the "n_after" coefficients after the transformed range of dimensions
13578  * and the coefficients of the other divs in "bmap".
13579  */
set_ma_divs(__isl_take isl_basic_map * bmap,__isl_keep isl_multi_aff * ma,int n_before,int n_after,int n_div)13580 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
13581 	__isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
13582 {
13583 	int i;
13584 	isl_size n_param;
13585 	isl_size n_set;
13586 	isl_local_space *ls;
13587 
13588 	if (n_div == 0)
13589 		return bmap;
13590 
13591 	ls = isl_aff_get_domain_local_space(ma->u.p[0]);
13592 	n_param = isl_local_space_dim(ls, isl_dim_param);
13593 	n_set = isl_local_space_dim(ls, isl_dim_set);
13594 	if (n_param < 0 || n_set < 0)
13595 		return isl_basic_map_free(bmap);
13596 
13597 	for (i = 0; i < n_div; ++i) {
13598 		int o_bmap = 0, o_ls = 0;
13599 
13600 		isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
13601 		o_bmap += 1 + 1 + n_param;
13602 		o_ls += 1 + 1 + n_param;
13603 		isl_seq_clr(bmap->div[i] + o_bmap, n_before);
13604 		o_bmap += n_before;
13605 		isl_seq_cpy(bmap->div[i] + o_bmap,
13606 			    ls->div->row[i] + o_ls, n_set);
13607 		o_bmap += n_set;
13608 		o_ls += n_set;
13609 		isl_seq_clr(bmap->div[i] + o_bmap, n_after);
13610 		o_bmap += n_after;
13611 		isl_seq_cpy(bmap->div[i] + o_bmap,
13612 			    ls->div->row[i] + o_ls, n_div);
13613 		o_bmap += n_div;
13614 		o_ls += n_div;
13615 		isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
13616 		bmap = isl_basic_map_add_div_constraints(bmap, i);
13617 		if (!bmap)
13618 			goto error;
13619 	}
13620 
13621 	isl_local_space_free(ls);
13622 	return bmap;
13623 error:
13624 	isl_local_space_free(ls);
13625 	return isl_basic_map_free(bmap);
13626 }
13627 
13628 /* How many stride constraints does "ma" enforce?
13629  * That is, how many of the affine expressions have a denominator
13630  * different from one?
13631  */
multi_aff_strides(__isl_keep isl_multi_aff * ma)13632 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
13633 {
13634 	int i;
13635 	int strides = 0;
13636 
13637 	for (i = 0; i < ma->n; ++i)
13638 		if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
13639 			strides++;
13640 
13641 	return strides;
13642 }
13643 
13644 /* For each affine expression in ma of the form
13645  *
13646  *	x_i = (f_i y + h_i)/m_i
13647  *
13648  * with m_i different from one, add a constraint to "bmap"
13649  * of the form
13650  *
13651  *	f_i y + h_i = m_i alpha_i
13652  *
13653  * with alpha_i an additional existentially quantified variable.
13654  *
13655  * The input variables of "ma" correspond to a subset of the variables
13656  * of "bmap".  There are "n_before" variables in "bmap" before this
13657  * subset and "n_after" variables after this subset.
13658  * The integer divisions of the affine expressions in "ma" are assumed
13659  * to have been aligned.  There are "n_div_ma" of them and
13660  * they appear first in "bmap", straight after the "n_after" variables.
13661  */
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)13662 static __isl_give isl_basic_map *add_ma_strides(
13663 	__isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
13664 	int n_before, int n_after, int n_div_ma)
13665 {
13666 	int i, k;
13667 	int div;
13668 	isl_size total;
13669 	isl_size n_param;
13670 	isl_size n_in;
13671 
13672 	total = isl_basic_map_dim(bmap, isl_dim_all);
13673 	n_param = isl_multi_aff_dim(ma, isl_dim_param);
13674 	n_in = isl_multi_aff_dim(ma, isl_dim_in);
13675 	if (total < 0 || n_param < 0 || n_in < 0)
13676 		return isl_basic_map_free(bmap);
13677 	for (i = 0; i < ma->n; ++i) {
13678 		int o_bmap = 0, o_ma = 1;
13679 
13680 		if (isl_int_is_one(ma->u.p[i]->v->el[0]))
13681 			continue;
13682 		div = isl_basic_map_alloc_div(bmap);
13683 		k = isl_basic_map_alloc_equality(bmap);
13684 		if (div < 0 || k < 0)
13685 			goto error;
13686 		isl_int_set_si(bmap->div[div][0], 0);
13687 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13688 			    ma->u.p[i]->v->el + o_ma, 1 + n_param);
13689 		o_bmap += 1 + n_param;
13690 		o_ma += 1 + n_param;
13691 		isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
13692 		o_bmap += n_before;
13693 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13694 			    ma->u.p[i]->v->el + o_ma, n_in);
13695 		o_bmap += n_in;
13696 		o_ma += n_in;
13697 		isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
13698 		o_bmap += n_after;
13699 		isl_seq_cpy(bmap->eq[k] + o_bmap,
13700 			    ma->u.p[i]->v->el + o_ma, n_div_ma);
13701 		o_bmap += n_div_ma;
13702 		o_ma += n_div_ma;
13703 		isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
13704 		isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
13705 		total++;
13706 	}
13707 
13708 	return bmap;
13709 error:
13710 	isl_basic_map_free(bmap);
13711 	return NULL;
13712 }
13713 
13714 /* Replace the domain or range space (depending on "type) of "space" by "set".
13715  */
isl_space_set(__isl_take isl_space * space,enum isl_dim_type type,__isl_take isl_space * set)13716 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
13717 	enum isl_dim_type type, __isl_take isl_space *set)
13718 {
13719 	if (type == isl_dim_in) {
13720 		space = isl_space_range(space);
13721 		space = isl_space_map_from_domain_and_range(set, space);
13722 	} else {
13723 		space = isl_space_domain(space);
13724 		space = isl_space_map_from_domain_and_range(space, set);
13725 	}
13726 
13727 	return space;
13728 }
13729 
13730 /* Compute the preimage of the domain or range (depending on "type")
13731  * of "bmap" under the function represented by "ma".
13732  * In other words, plug in "ma" in the domain or range of "bmap".
13733  * The result is a basic map that lives in the same space as "bmap"
13734  * except that the domain or range has been replaced by
13735  * the domain space of "ma".
13736  *
13737  * If bmap is represented by
13738  *
13739  *	A(p) + S u + B x + T v + C(divs) >= 0,
13740  *
13741  * where u and x are input and output dimensions if type == isl_dim_out
13742  * while x and v are input and output dimensions if type == isl_dim_in,
13743  * and ma is represented by
13744  *
13745  *	x = D(p) + F(y) + G(divs')
13746  *
13747  * then the result is
13748  *
13749  *	A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
13750  *
13751  * The divs in the input set are similarly adjusted.
13752  * In particular
13753  *
13754  *	floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
13755  *
13756  * becomes
13757  *
13758  *	floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
13759  *		B_i G(divs') + c_i(divs))/n_i)
13760  *
13761  * If bmap is not a rational map and if F(y) involves any denominators
13762  *
13763  *	x_i = (f_i y + h_i)/m_i
13764  *
13765  * then additional constraints are added to ensure that we only
13766  * map back integer points.  That is we enforce
13767  *
13768  *	f_i y + h_i = m_i alpha_i
13769  *
13770  * with alpha_i an additional existentially quantified variable.
13771  *
13772  * We first copy over the divs from "ma".
13773  * Then we add the modified constraints and divs from "bmap".
13774  * Finally, we add the stride constraints, if needed.
13775  */
isl_basic_map_preimage_multi_aff(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13776 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
13777 	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
13778 	__isl_take isl_multi_aff *ma)
13779 {
13780 	int i, k;
13781 	isl_space *space;
13782 	isl_basic_map *res = NULL;
13783 	isl_size n_before, n_after, n_div_bmap, n_div_ma;
13784 	isl_int f, c1, c2, g;
13785 	isl_bool rational;
13786 	int strides;
13787 
13788 	isl_int_init(f);
13789 	isl_int_init(c1);
13790 	isl_int_init(c2);
13791 	isl_int_init(g);
13792 
13793 	ma = isl_multi_aff_align_divs(ma);
13794 	if (!bmap || !ma)
13795 		goto error;
13796 	if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
13797 		goto error;
13798 
13799 	if (type == isl_dim_in) {
13800 		n_before = 0;
13801 		n_after = isl_basic_map_dim(bmap, isl_dim_out);
13802 	} else {
13803 		n_before = isl_basic_map_dim(bmap, isl_dim_in);
13804 		n_after = 0;
13805 	}
13806 	n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
13807 	n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
13808 	if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
13809 		goto error;
13810 
13811 	space = isl_multi_aff_get_domain_space(ma);
13812 	space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
13813 	rational = isl_basic_map_is_rational(bmap);
13814 	strides = rational ? 0 : multi_aff_strides(ma);
13815 	res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
13816 			    bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
13817 	if (rational)
13818 		res = isl_basic_map_set_rational(res);
13819 
13820 	for (i = 0; i < n_div_ma + n_div_bmap; ++i)
13821 		if (isl_basic_map_alloc_div(res) < 0)
13822 			goto error;
13823 
13824 	res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
13825 	if (!res)
13826 		goto error;
13827 
13828 	for (i = 0; i < bmap->n_eq; ++i) {
13829 		k = isl_basic_map_alloc_equality(res);
13830 		if (k < 0)
13831 			goto error;
13832 		if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13833 				    n_after, n_div_ma, n_div_bmap,
13834 				    f, c1, c2, g, 0) < 0)
13835 			goto error;
13836 	}
13837 
13838 	for (i = 0; i < bmap->n_ineq; ++i) {
13839 		k = isl_basic_map_alloc_inequality(res);
13840 		if (k < 0)
13841 			goto error;
13842 		if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13843 				    n_after, n_div_ma, n_div_bmap,
13844 				    f, c1, c2, g, 0) < 0)
13845 			goto error;
13846 	}
13847 
13848 	for (i = 0; i < bmap->n_div; ++i) {
13849 		if (isl_int_is_zero(bmap->div[i][0])) {
13850 			isl_int_set_si(res->div[n_div_ma + i][0], 0);
13851 			continue;
13852 		}
13853 		if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13854 				    n_before, n_after, n_div_ma, n_div_bmap,
13855 				    f, c1, c2, g, 1) < 0)
13856 			goto error;
13857 	}
13858 
13859 	if (strides)
13860 		res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13861 
13862 	isl_int_clear(f);
13863 	isl_int_clear(c1);
13864 	isl_int_clear(c2);
13865 	isl_int_clear(g);
13866 	isl_basic_map_free(bmap);
13867 	isl_multi_aff_free(ma);
13868 	res = isl_basic_map_simplify(res);
13869 	return isl_basic_map_finalize(res);
13870 error:
13871 	isl_int_clear(f);
13872 	isl_int_clear(c1);
13873 	isl_int_clear(c2);
13874 	isl_int_clear(g);
13875 	isl_basic_map_free(bmap);
13876 	isl_multi_aff_free(ma);
13877 	isl_basic_map_free(res);
13878 	return NULL;
13879 }
13880 
13881 /* Compute the preimage of "bset" under the function represented by "ma".
13882  * In other words, plug in "ma" in "bset".  The result is a basic set
13883  * that lives in the domain space of "ma".
13884  */
isl_basic_set_preimage_multi_aff(__isl_take isl_basic_set * bset,__isl_take isl_multi_aff * ma)13885 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13886 	__isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13887 {
13888 	return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13889 }
13890 
13891 /* Compute the preimage of the domain of "bmap" under the function
13892  * represented by "ma".
13893  * In other words, plug in "ma" in the domain of "bmap".
13894  * The result is a basic map that lives in the same space as "bmap"
13895  * except that the domain has been replaced by the domain space of "ma".
13896  */
isl_basic_map_preimage_domain_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13897 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13898 	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13899 {
13900 	return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13901 }
13902 
13903 /* Compute the preimage of the range of "bmap" under the function
13904  * represented by "ma".
13905  * In other words, plug in "ma" in the range of "bmap".
13906  * The result is a basic map that lives in the same space as "bmap"
13907  * except that the range has been replaced by the domain space of "ma".
13908  */
isl_basic_map_preimage_range_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13909 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13910 	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13911 {
13912 	return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13913 }
13914 
13915 /* Check if the range of "ma" is compatible with the domain or range
13916  * (depending on "type") of "map".
13917  * Return isl_stat_error if anything is wrong.
13918  */
check_map_compatible_range_multi_aff(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13919 static isl_stat check_map_compatible_range_multi_aff(
13920 	__isl_keep isl_map *map, enum isl_dim_type type,
13921 	__isl_keep isl_multi_aff *ma)
13922 {
13923 	isl_bool m;
13924 	isl_space *ma_space;
13925 
13926 	ma_space = isl_multi_aff_get_space(ma);
13927 	m = isl_map_space_tuple_is_equal(map, type, ma_space, isl_dim_out);
13928 	isl_space_free(ma_space);
13929 	if (m < 0)
13930 		return isl_stat_error;
13931 	if (!m)
13932 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
13933 			"spaces don't match", return isl_stat_error);
13934 	return isl_stat_ok;
13935 }
13936 
13937 /* Compute the preimage of the domain or range (depending on "type")
13938  * of "map" under the function represented by "ma".
13939  * In other words, plug in "ma" in the domain or range of "map".
13940  * The result is a map that lives in the same space as "map"
13941  * except that the domain or range has been replaced by
13942  * the domain space of "ma".
13943  *
13944  * The parameters are assumed to have been aligned.
13945  */
map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13946 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13947 	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13948 {
13949 	int i;
13950 	isl_space *space;
13951 
13952 	map = isl_map_cow(map);
13953 	ma = isl_multi_aff_align_divs(ma);
13954 	if (!map || !ma)
13955 		goto error;
13956 	if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13957 		goto error;
13958 
13959 	for (i = 0; i < map->n; ++i) {
13960 		map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13961 							isl_multi_aff_copy(ma));
13962 		if (!map->p[i])
13963 			goto error;
13964 	}
13965 
13966 	space = isl_multi_aff_get_domain_space(ma);
13967 	space = isl_space_set(isl_map_get_space(map), type, space);
13968 
13969 	isl_space_free(isl_map_take_space(map));
13970 	map = isl_map_restore_space(map, space);
13971 	if (!map)
13972 		goto error;
13973 
13974 	isl_multi_aff_free(ma);
13975 	if (map->n > 1)
13976 		ISL_F_CLR(map, ISL_MAP_DISJOINT);
13977 	ISL_F_CLR(map, ISL_SET_NORMALIZED);
13978 	return map;
13979 error:
13980 	isl_multi_aff_free(ma);
13981 	isl_map_free(map);
13982 	return NULL;
13983 }
13984 
13985 /* Compute the preimage of the domain or range (depending on "type")
13986  * of "map" under the function represented by "ma".
13987  * In other words, plug in "ma" in the domain or range of "map".
13988  * The result is a map that lives in the same space as "map"
13989  * except that the domain or range has been replaced by
13990  * the domain space of "ma".
13991  */
isl_map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13992 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13993 	enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13994 {
13995 	isl_bool aligned;
13996 
13997 	if (!map || !ma)
13998 		goto error;
13999 
14000 	aligned = isl_map_space_has_equal_params(map, ma->space);
14001 	if (aligned < 0)
14002 		goto error;
14003 	if (aligned)
14004 		return map_preimage_multi_aff(map, type, ma);
14005 
14006 	if (isl_map_check_named_params(map) < 0)
14007 		goto error;
14008 	if (!isl_space_has_named_params(ma->space))
14009 		isl_die(map->ctx, isl_error_invalid,
14010 			"unaligned unnamed parameters", goto error);
14011 	map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
14012 	ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
14013 
14014 	return map_preimage_multi_aff(map, type, ma);
14015 error:
14016 	isl_multi_aff_free(ma);
14017 	return isl_map_free(map);
14018 }
14019 
14020 /* Compute the preimage of "set" under the function represented by "ma".
14021  * In other words, plug in "ma" in "set".  The result is a set
14022  * that lives in the domain space of "ma".
14023  */
isl_set_preimage_multi_aff(__isl_take isl_set * set,__isl_take isl_multi_aff * ma)14024 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
14025 	__isl_take isl_multi_aff *ma)
14026 {
14027 	return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
14028 }
14029 
14030 /* Compute the preimage of the domain of "map" under the function
14031  * represented by "ma".
14032  * In other words, plug in "ma" in the domain of "map".
14033  * The result is a map that lives in the same space as "map"
14034  * except that the domain has been replaced by the domain space of "ma".
14035  */
isl_map_preimage_domain_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)14036 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
14037 	__isl_take isl_multi_aff *ma)
14038 {
14039 	return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
14040 }
14041 
14042 /* Compute the preimage of the range of "map" under the function
14043  * represented by "ma".
14044  * In other words, plug in "ma" in the range of "map".
14045  * The result is a map that lives in the same space as "map"
14046  * except that the range has been replaced by the domain space of "ma".
14047  */
isl_map_preimage_range_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)14048 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
14049 	__isl_take isl_multi_aff *ma)
14050 {
14051 	return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
14052 }
14053 
14054 /* Compute the preimage of "map" under the function represented by "pma".
14055  * In other words, plug in "pma" in the domain or range of "map".
14056  * The result is a map that lives in the same space as "map",
14057  * except that the space of type "type" has been replaced by
14058  * the domain space of "pma".
14059  *
14060  * The parameters of "map" and "pma" are assumed to have been aligned.
14061  */
isl_map_preimage_pw_multi_aff_aligned(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14062 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
14063 	__isl_take isl_map *map, enum isl_dim_type type,
14064 	__isl_take isl_pw_multi_aff *pma)
14065 {
14066 	int i;
14067 	isl_map *res;
14068 
14069 	if (!pma)
14070 		goto error;
14071 
14072 	if (pma->n == 0) {
14073 		isl_pw_multi_aff_free(pma);
14074 		res = isl_map_empty(isl_map_get_space(map));
14075 		isl_map_free(map);
14076 		return res;
14077 	}
14078 
14079 	res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14080 					isl_multi_aff_copy(pma->p[0].maff));
14081 	if (type == isl_dim_in)
14082 		res = isl_map_intersect_domain(res,
14083 						isl_map_copy(pma->p[0].set));
14084 	else
14085 		res = isl_map_intersect_range(res,
14086 						isl_map_copy(pma->p[0].set));
14087 
14088 	for (i = 1; i < pma->n; ++i) {
14089 		isl_map *res_i;
14090 
14091 		res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14092 					isl_multi_aff_copy(pma->p[i].maff));
14093 		if (type == isl_dim_in)
14094 			res_i = isl_map_intersect_domain(res_i,
14095 						isl_map_copy(pma->p[i].set));
14096 		else
14097 			res_i = isl_map_intersect_range(res_i,
14098 						isl_map_copy(pma->p[i].set));
14099 		res = isl_map_union(res, res_i);
14100 	}
14101 
14102 	isl_pw_multi_aff_free(pma);
14103 	isl_map_free(map);
14104 	return res;
14105 error:
14106 	isl_pw_multi_aff_free(pma);
14107 	isl_map_free(map);
14108 	return NULL;
14109 }
14110 
14111 /* Compute the preimage of "map" under the function represented by "pma".
14112  * In other words, plug in "pma" in the domain or range of "map".
14113  * The result is a map that lives in the same space as "map",
14114  * except that the space of type "type" has been replaced by
14115  * the domain space of "pma".
14116  */
isl_map_preimage_pw_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14117 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
14118 	enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
14119 {
14120 	isl_bool aligned;
14121 
14122 	if (!map || !pma)
14123 		goto error;
14124 
14125 	aligned = isl_map_space_has_equal_params(map, pma->dim);
14126 	if (aligned < 0)
14127 		goto error;
14128 	if (aligned)
14129 		return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14130 
14131 	if (isl_map_check_named_params(map) < 0)
14132 		goto error;
14133 	if (isl_pw_multi_aff_check_named_params(pma) < 0)
14134 		goto error;
14135 	map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
14136 	pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
14137 
14138 	return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14139 error:
14140 	isl_pw_multi_aff_free(pma);
14141 	return isl_map_free(map);
14142 }
14143 
14144 /* Compute the preimage of "set" under the function represented by "pma".
14145  * In other words, plug in "pma" in "set".  The result is a set
14146  * that lives in the domain space of "pma".
14147  */
isl_set_preimage_pw_multi_aff(__isl_take isl_set * set,__isl_take isl_pw_multi_aff * pma)14148 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
14149 	__isl_take isl_pw_multi_aff *pma)
14150 {
14151 	return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
14152 }
14153 
14154 /* Compute the preimage of the domain of "map" under the function
14155  * represented by "pma".
14156  * In other words, plug in "pma" in the domain of "map".
14157  * The result is a map that lives in the same space as "map",
14158  * except that domain space has been replaced by the domain space of "pma".
14159  */
isl_map_preimage_domain_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14160 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
14161 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14162 {
14163 	return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
14164 }
14165 
14166 /* Compute the preimage of the range of "map" under the function
14167  * represented by "pma".
14168  * In other words, plug in "pma" in the range of "map".
14169  * The result is a map that lives in the same space as "map",
14170  * except that range space has been replaced by the domain space of "pma".
14171  */
isl_map_preimage_range_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14172 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
14173 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14174 {
14175 	return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
14176 }
14177 
14178 /* Compute the preimage of "map" under the function represented by "mpa".
14179  * In other words, plug in "mpa" in the domain or range of "map".
14180  * The result is a map that lives in the same space as "map",
14181  * except that the space of type "type" has been replaced by
14182  * the domain space of "mpa".
14183  *
14184  * If the map does not involve any constraints that refer to the
14185  * dimensions of the substituted space, then the only possible
14186  * effect of "mpa" on the map is to map the space to a different space.
14187  * We create a separate isl_multi_aff to effectuate this change
14188  * in order to avoid spurious splitting of the map along the pieces
14189  * of "mpa".
14190  * If "mpa" has a non-trivial explicit domain, however,
14191  * then the full substitution should be performed.
14192  */
isl_map_preimage_multi_pw_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_pw_aff * mpa)14193 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
14194 	enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
14195 {
14196 	isl_size n;
14197 	isl_bool full;
14198 	isl_pw_multi_aff *pma;
14199 
14200 	n = isl_map_dim(map, type);
14201 	if (n < 0 || !mpa)
14202 		goto error;
14203 
14204 	full = isl_map_involves_dims(map, type, 0, n);
14205 	if (full >= 0 && !full)
14206 		full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
14207 	if (full < 0)
14208 		goto error;
14209 	if (!full) {
14210 		isl_space *space;
14211 		isl_multi_aff *ma;
14212 
14213 		space = isl_multi_pw_aff_get_space(mpa);
14214 		isl_multi_pw_aff_free(mpa);
14215 		ma = isl_multi_aff_zero(space);
14216 		return isl_map_preimage_multi_aff(map, type, ma);
14217 	}
14218 
14219 	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
14220 	return isl_map_preimage_pw_multi_aff(map, type, pma);
14221 error:
14222 	isl_map_free(map);
14223 	isl_multi_pw_aff_free(mpa);
14224 	return NULL;
14225 }
14226 
14227 /* Compute the preimage of "map" under the function represented by "mpa".
14228  * In other words, plug in "mpa" in the domain "map".
14229  * The result is a map that lives in the same space as "map",
14230  * except that domain space has been replaced by the domain space of "mpa".
14231  */
isl_map_preimage_domain_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * mpa)14232 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
14233 	__isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
14234 {
14235 	return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
14236 }
14237 
14238 /* Compute the preimage of "set" by the function represented by "mpa".
14239  * In other words, plug in "mpa" in "set".
14240  */
isl_set_preimage_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * mpa)14241 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
14242 	__isl_take isl_multi_pw_aff *mpa)
14243 {
14244 	return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
14245 }
14246 
14247 /* Return a copy of the equality constraints of "bset" as a matrix.
14248  */
isl_basic_set_extract_equalities(__isl_keep isl_basic_set * bset)14249 __isl_give isl_mat *isl_basic_set_extract_equalities(
14250 	__isl_keep isl_basic_set *bset)
14251 {
14252 	isl_ctx *ctx;
14253 	isl_size total;
14254 
14255 	total = isl_basic_set_dim(bset, isl_dim_all);
14256 	if (total < 0)
14257 		return NULL;
14258 
14259 	ctx = isl_basic_set_get_ctx(bset);
14260 	return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
14261 }
14262 
14263 /* Are the "n" "coefficients" starting at "first" of the integer division
14264  * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
14265  * to each other?
14266  * The "coefficient" at position 0 is the denominator.
14267  * The "coefficient" at position 1 is the constant term.
14268  */
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)14269 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
14270 	int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
14271 	unsigned first, unsigned n)
14272 {
14273 	if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
14274 		return isl_bool_error;
14275 	if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
14276 		return isl_bool_error;
14277 	return isl_seq_eq(bmap1->div[pos1] + first,
14278 			  bmap2->div[pos2] + first, n);
14279 }
14280 
14281 /* Are the integer division expressions at position "pos1" in "bmap1" and
14282  * "pos2" in "bmap2" equal to each other, except that the constant terms
14283  * are different?
14284  */
isl_basic_map_equal_div_expr_except_constant(__isl_keep isl_basic_map * bmap1,int pos1,__isl_keep isl_basic_map * bmap2,int pos2)14285 isl_bool isl_basic_map_equal_div_expr_except_constant(
14286 	__isl_keep isl_basic_map *bmap1, int pos1,
14287 	__isl_keep isl_basic_map *bmap2, int pos2)
14288 {
14289 	isl_bool equal;
14290 	isl_size total, total2;
14291 
14292 	total = isl_basic_map_dim(bmap1, isl_dim_all);
14293 	total2 = isl_basic_map_dim(bmap2, isl_dim_all);
14294 	if (total < 0 || total2 < 0)
14295 		return isl_bool_error;
14296 	if (total != total2)
14297 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
14298 			"incomparable div expressions", return isl_bool_error);
14299 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14300 						0, 1);
14301 	if (equal < 0 || !equal)
14302 		return equal;
14303 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14304 						1, 1);
14305 	if (equal < 0 || equal)
14306 		return isl_bool_not(equal);
14307 	return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14308 						2, total);
14309 }
14310 
14311 /* Replace the numerator of the constant term of the integer division
14312  * expression at position "div" in "bmap" by "value".
14313  * The caller guarantees that this does not change the meaning
14314  * of the input.
14315  */
isl_basic_map_set_div_expr_constant_num_si_inplace(__isl_take isl_basic_map * bmap,int div,int value)14316 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
14317 	__isl_take isl_basic_map *bmap, int div, int value)
14318 {
14319 	if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
14320 		return isl_basic_map_free(bmap);
14321 
14322 	isl_int_set_si(bmap->div[div][1], value);
14323 
14324 	return bmap;
14325 }
14326 
14327 /* Is the point "inner" internal to inequality constraint "ineq"
14328  * of "bset"?
14329  * The point is considered to be internal to the inequality constraint,
14330  * if it strictly lies on the positive side of the inequality constraint,
14331  * or if it lies on the constraint and the constraint is lexico-positive.
14332  */
is_internal(__isl_keep isl_vec * inner,__isl_keep isl_basic_set * bset,int ineq)14333 static isl_bool is_internal(__isl_keep isl_vec *inner,
14334 	__isl_keep isl_basic_set *bset, int ineq)
14335 {
14336 	isl_ctx *ctx;
14337 	int pos;
14338 	isl_size total;
14339 
14340 	if (!inner || !bset)
14341 		return isl_bool_error;
14342 
14343 	ctx = isl_basic_set_get_ctx(bset);
14344 	isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
14345 				&ctx->normalize_gcd);
14346 	if (!isl_int_is_zero(ctx->normalize_gcd))
14347 		return isl_int_is_nonneg(ctx->normalize_gcd);
14348 
14349 	total = isl_basic_set_dim(bset, isl_dim_all);
14350 	if (total < 0)
14351 		return isl_bool_error;
14352 	pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
14353 	return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
14354 }
14355 
14356 /* Tighten the inequality constraints of "bset" that are outward with respect
14357  * to the point "vec".
14358  * That is, tighten the constraints that are not satisfied by "vec".
14359  *
14360  * "vec" is a point internal to some superset S of "bset" that is used
14361  * to make the subsets of S disjoint, by tightening one half of the constraints
14362  * that separate two subsets.  In particular, the constraints of S
14363  * are all satisfied by "vec" and should not be tightened.
14364  * Of the internal constraints, those that have "vec" on the outside
14365  * are tightened.  The shared facet is included in the adjacent subset
14366  * with the opposite constraint.
14367  * For constraints that saturate "vec", this criterion cannot be used
14368  * to determine which of the two sides should be tightened.
14369  * Instead, the sign of the first non-zero coefficient is used
14370  * to make this choice.  Note that this second criterion is never used
14371  * on the constraints of S since "vec" is interior to "S".
14372  */
isl_basic_set_tighten_outward(__isl_take isl_basic_set * bset,__isl_keep isl_vec * vec)14373 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
14374 	__isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
14375 {
14376 	int j;
14377 
14378 	bset = isl_basic_set_cow(bset);
14379 	if (!bset)
14380 		return NULL;
14381 	for (j = 0; j < bset->n_ineq; ++j) {
14382 		isl_bool internal;
14383 
14384 		internal = is_internal(vec, bset, j);
14385 		if (internal < 0)
14386 			return isl_basic_set_free(bset);
14387 		if (internal)
14388 			continue;
14389 		isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
14390 	}
14391 
14392 	return bset;
14393 }
14394 
14395 /* Replace the variables x of type "type" starting at "first" in "bmap"
14396  * by x' with x = M x' with M the matrix trans.
14397  * That is, replace the corresponding coefficients c by c M.
14398  *
14399  * The transformation matrix should be a square matrix.
14400  */
isl_basic_map_transform_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14401 __isl_give isl_basic_map *isl_basic_map_transform_dims(
14402 	__isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
14403 	__isl_take isl_mat *trans)
14404 {
14405 	unsigned pos;
14406 
14407 	bmap = isl_basic_map_cow(bmap);
14408 	if (!bmap || !trans)
14409 		goto error;
14410 
14411 	if (trans->n_row != trans->n_col)
14412 		isl_die(trans->ctx, isl_error_invalid,
14413 			"expecting square transformation matrix", goto error);
14414 	if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
14415 		goto error;
14416 
14417 	pos = isl_basic_map_offset(bmap, type) + first;
14418 
14419 	if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
14420 			isl_mat_copy(trans)) < 0)
14421 		goto error;
14422 	if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
14423 		      isl_mat_copy(trans)) < 0)
14424 		goto error;
14425 	if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
14426 		      isl_mat_copy(trans)) < 0)
14427 		goto error;
14428 
14429 	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
14430 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
14431 
14432 	isl_mat_free(trans);
14433 	return bmap;
14434 error:
14435 	isl_mat_free(trans);
14436 	isl_basic_map_free(bmap);
14437 	return NULL;
14438 }
14439 
14440 /* Replace the variables x of type "type" starting at "first" in "bset"
14441  * by x' with x = M x' with M the matrix trans.
14442  * That is, replace the corresponding coefficients c by c M.
14443  *
14444  * The transformation matrix should be a square matrix.
14445  */
isl_basic_set_transform_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14446 __isl_give isl_basic_set *isl_basic_set_transform_dims(
14447 	__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
14448 	__isl_take isl_mat *trans)
14449 {
14450 	return isl_basic_map_transform_dims(bset, type, first, trans);
14451 }
14452